API Reference¶
This section covers the public API of bmquilting.
Core Configuration & Types¶
These classes and types are exposed at the root level for easy access.
- class bmquilting.BlendConfig(sobel_kernel_size: 'NumPixels' = 3, min_blur_diameter: 'NumPixels' = 3, max_blur_diameter: 'NumPixels' = 11, use_vignette: 'bool' = True, blur_size_func: 'FuncWrapper' = <factory>, blur_shape_func: 'FuncWrapper' = <factory>, adaptive_maximum_filter_number_of_levels: 'int' = 3, grad_diff_func: 'Callable' = <function sum_squared_differences at 0x7fb4cc3002c0>, use_blur_radii_limiter: 'bool' = True)[source]
Bases:
object- sobel_kernel_size: NumPixels
- min_blur_diameter: NumPixels
- max_blur_diameter: NumPixels
- use_vignette: bool
Applies a fade to the patch as its content approaches its shape edges (not the seams).
This effect can be used alongside seams to soften transitions, or with seams disabled to achieve pure feathering between patches. While effective at masking color or value discrepancies, it introduces a blurring effect that make it unsuitable for textures containing fine, sharp details, such as text, where clarity is required.
- blur_size_func: FuncWrapper
Function used to remap the Normalized Gradient Differences (NGDs) computed around the seam.
The remapped values remain within the interval [0, 1], as they are used to interpolate between the minimum and maximum blur diameters. This remapping introduces a non-linear relationship between the blur size and the NGDs.
Note
NGDs are normalized with respect to the theoretical maximum possible value for the given kernel size used to compute the gradients.
- Default Behavior:
The LogScalingFunc is used with gain=100 and top=0.5.
Setting top=0.5 ensures the function reaches 1 (the maximum blur radius)
when the NGD value is half of its theoretical maximum. - Setting gain=100 makes the function concave, steep at the start, meaning the blur radius increases quickly for small gradients and more slowly as it approaches the top.
- blur_shape_func: FuncWrapper
Function used to shape the transition curve when blending two patches (e.g., in a multi-patch surface).
This function maps the signed distance to the seam to an interpolation weight (ranging from 0 to 1) used for blending. It determines how the two patches transition within the specified blur area, influencing the resulting smoothness or sharp change.
- Default Behavior:
The TwoNTS (Two-NormalizedTunableSigmoid) is used with k=-0.5.
The resulting curve shape is composed of two scaled sigmoid-like curves that meet smoothly near the seam (where the distance is zero). Visual Analogy: The transition resembles two gentle “hills” meeting at their bases, providing a very smooth, Gaussian-kernel-like transition rather than a simple linear ramp. This makes the blending effect strongest at the seam and rapidly decreases away from it.
- adaptive_maximum_filter_number_of_levels: int
- This parameter sets the number of iterations (or levels) with different kernel sizes
that the adaptive maximum filter executes when computing the blur diameters.
Context: 1. Blur Diameter Calculation: When blending a seam, the initial blur diameter is determined
based on the gradient differences computed near the seam.
Diameter Propagation: These initial diameters need to be propagated across the texture to determine the correct blend amount for every pixel (i.e., if a pixel’s distance to the seam is less than the propagated radius, it needs blending).
Adaptive Filter: An adaptive maximum filter is used for this propagation/expansion. This filter runs with different kernel sizes across multiple iterations to ensure that locally lower blur diameters aren’t overshadowed by higher values during expansion.
- Note on Quantization:
The final quantization interval for the diameters is determined by the min_blur_diameter and the maximum diameter found in the propagation process (it is not based on the theoretical possible maximum defined by max_blur_diameter).
- grad_diff_func: Callable
Computes a seam’s “errors”, i.e. how much the seam is noticeable, with respect to the gradients differences.
- The function receives the following numpy arrays as input:
dgx: (H, W, C) already computed x gradients difference, per channel; view into dgxy.
dgy: (H, W, C) already computed y gradients difference, per channel; view into dgxy.
dgxy: (2, H, W, C) -> dgxy[0] = dgx; dgxy[1] = dgy; may be used instead of dgx and dgy.
out: (H, W) pre-allocated output array; can be used for intermediate computations.
- Default behavior:
Sum of Squared Differences (SSD), similar to L2 norm without the square root overhead.
- use_blur_radii_limiter: bool
Attempts to mitigate seam blurring artifacts AFTER seam computation. This is done by limiting the seam blur radius with respect to its proximity to the overlapping area edges. This helps prevent seam artifacts near the edges that could visually give away the generation grid layout.
- classmethod auto_blend_config_2(block_size: NumPixels, overlap: NumPixels, use_vignette: bool = False) BlendConfig[source]
Creates a BlendConfig by heuristically determining an adequate sobel kernel size and blur diameter bounds based on the provided inputs.
- Parameters:
block_size – The length of one of the patch’s edges.
overlap – The size of the overlapping area between patches.
use_vignette – Whether to apply a vignette-like mask for additional smoothing.
- Returns:
A BlendConfig instance with calculated blur bounds.
- classmethod auto_blend_config_1(sobel_kernel_size: NumPixels, overlap: NumPixels, use_vignette: bool = False) BlendConfig[source]
Creates a BlendConfig by heuristically determining the blur diameter bounds based on the provided inputs.
- Parameters:
sobel_kernel_size – The kernel size used for gradient computation.
overlap – The size of the overlapping area between patches.
use_vignette – Whether to apply a vignette-like mask for additional smoothing.
- Returns:
A BlendConfig instance with calculated blur bounds.
- class bmquilting.UiCoordData(jobs_shm_name: str, job_id: int)[source]
Bases:
objectManages job progress and interruption signals via SharedMemory.
The shared memory buffer is expected to be a
uint32array where: * Index 0: Interrupt signal (value > 0 triggers interruption). * Index 1+: Job data slots for progress tracking.- Parameters:
jobs_shm_name – The unique name of the shared memory block.
job_id – The index offset for this specific job’s data slot.
- raise_or_add(value: int = 0) None[source]
Raises JobInterrupted if an interrupt signal is detected. Otherwise, adds count to the progress tracker shared memory array.
- Raises:
JobInterrupted – If the UI has signaled to stop.
- request_interrupt() None[source]
Sets the interrupt signal for this shared memory block. Call this from the UI thread/process to stop the worker.
- close() None[source]
Closes the shared memory connection.
- static get_number_of_jobs_for(parallelization_lvl: int, batch_size: int = 1) int[source]
- Parameters:
parallelization_lvl – the parallelization_lvl used for the generation
batch_size – how many generations will run simultaneously
- Returns:
the total number of jobs
- static get_required_shm_size_and_number_of_jobs(parallelization_lvl: int, batch_size: int = 1) tuple[int, int][source]
- class bmquilting.JobMemoryManager(num_jobs: int)[source]
Bases:
object- property name
- get_progress() int[source]
Reads current progress of all jobs from memory.
- stop_all()[source]
Sets the interrupt flag at index 0.
- register_thread(thread: Thread)[source]
Register the UI monitoring thread so we can join it on exit.
- is_interrupted() bool[source]
Check the shared signal. Use this in the thread loop.
- create() str[source]
- exception bmquilting.JobInterrupted[source]
Bases:
ExceptionCustom exception to signal a UI interrupt.
- bmquilting.guess_nice_block_size(src: numpy.ndarray, heuristic: str | bool = 'fft', max_block_size: NumPixels | None = None) NumPixels[source]
Block size guess heuristic selector.
- Parameters:
src – must be single channel if “fft” is used.
heuristic –
“fft”: FFT-based analysis only (default)
”sift”: SIFT keypoint-based analysis only
”both”: FFT + SIFT combined analysis
- bool: backward-compatible flag for old freq_analysis_only behavior
True => FFT only
False => both, FFT + SIFT
max_block_size – further restricts the upper bound for the guess. the actually used upper bound might be lower than max_block_size.
Square Patching¶
- class bmquilting.square.SquarePatchingConfig(block_size: NumPixels, overlap: NumPixels, tolerance: Percentage, blend_config: SquarePatchingBlendConfig | None, vignette_on_match_template: bool, _compute_seam_callable: Callable, _error_func: Callable, match_template_method: int = cv2.TM_SQDIFF)[source]¶
Bases:
objectCentralises all parameters needed across the square patching subroutines.
Instances should be created via the class methods rather than directly, as the internal seam and error callables are managed automatically:
with_seams(),with_feathering(),with_hybrid(),advanced(),custom().- block_size: NumPixels¶
- overlap: NumPixels¶
- tolerance: Percentage¶
- blend_config: SquarePatchingBlendConfig | None¶
- vignette_on_match_template: bool¶
whether to use the blending vignette as a mask when searching for a matching patch
- match_template_method: int¶
Match template method used when searching for a patch with a matching overlap section. Only TM_SQDIFF and TM_CCOEFF_NORMED are supported.
- classmethod with_seams(block_size: NumPixels, overlap: NumPixels, tolerance: Percentage, blend: bool = True) SquarePatchingConfig[source]¶
Uses seams whose blur size bounds are heuristically determined by the provided argument; they are complemented with a vignette-like mask.
Uses A* to compute the seams, where the error is the channels’ averaged squared difference.
- classmethod with_feathering(block_size: NumPixels, overlap: NumPixels, tolerance: Percentage) SquarePatchingConfig[source]¶
Does not compute seams, the patch is blended using a vignette-like mask.
- classmethod with_hybrid(block_size: NumPixels, overlap: NumPixels, tolerance: Percentage) SquarePatchingConfig[source]¶
- classmethod advanced(block_size: NumPixels, overlap: NumPixels, tolerance: Percentage, blend_config: SquarePatchingBlendConfig | BlendConfig, seam_algorithm: SeamsAlgorithm = SeamsAlgorithm.ASTAR, vignette_on_match_template: bool = False, match_template_method=cv2.TM_SQDIFF, custom_error_func: Callable = None) SquarePatchingConfig[source]¶
- classmethod custom(block_size: NumPixels, overlap: NumPixels, tolerance: Percentage, blend_config: SquarePatchingBlendConfig | BlendConfig, custom_func: CallableSeamsAlgorithm, vignette_on_match_template: bool = False, match_template_method=cv2.TM_SQDIFF) SquarePatchingConfig[source]¶
Create a config using a user‑supplied min‑cut function.
- property blend_into_patch: bool¶
- property bo: tuple[NumPixels, NumPixels]¶
- property bot: tuple[NumPixels, NumPixels, Percentage]¶
- class bmquilting.square.SquarePatchingBlendConfig(sobel_kernel_size: 'NumPixels' = 3, min_blur_diameter: 'NumPixels' = 3, max_blur_diameter: 'NumPixels' = 11, use_vignette: 'bool' = True, blur_size_func: 'FuncWrapper' = <factory>, blur_shape_func: 'FuncWrapper' = <factory>, adaptive_maximum_filter_number_of_levels: 'int' = 3, grad_diff_func: 'Callable' = <function sum_squared_differences at 0x7fb4cc3002c0>, use_blur_radii_limiter: 'bool' = True, use_blur_radii_guess_pathfind_limiter: 'bool' = True)[source]¶
Bases:
BlendConfig- use_blur_radii_guess_pathfind_limiter: bool¶
Attempts to mitigate seam blurring artifacts BEFORE seam computation. Prior to computing the seam, make an educated guess of the potential max blur radius. When computing the seam the overlapping area is further constrained with respect to this guess to avoid having the seam go near the edges of the overlapping area.
Only applicable when using pyastar2d to compute the seam.
- class bmquilting.square.SeamsAlgorithm(*values)[source]¶
Bases:
EnumOptions for the minimum cut patch search algorithm.
- ASTAR = 'astar'¶
Implemented using pyastar2d; check documentation for more information.
- MIN_CUT = 'min_cut'¶
Implemented using numpy; adapted from jena2020.
- NONE = 'none'¶
Bypasses seam computation.
- bmquilting.square.generate_texture(src_texs: list[numpy.ndarray], patching_config: SquarePatchingConfig, out_h: NumPixels, out_w: NumPixels, seed: int, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray] | RetOnInterrupt[source]¶
Generate a texture with patches drawn from the provided source textures.
This is the vanilla, straightforward, sequential implementation.
- Parameters:
src_texs – Source textures from where the patches will be drawn.
patching_config – Patching configuration contains the parameters for the generation, such as the block size.
out_h – Output’s height in pixels.
out_w – Output’s width in pixels.
seed – Random Number Generator’s seed, ensures reproducibility.
uicd – Utility to track the generation progress and to process UI interrupts.
- Returns:
A tuple
(texture, seams).
- bmquilting.square.generate_texture_parallel(src_texs: list[numpy.ndarray], patching_config: SquarePatchingConfig, out_h: NumPixels, out_w: NumPixels, nps: int, seed: int, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray] | RetOnInterrupt[source]¶
Similar to generate_texture, but starts the generation from the center, dividing the generation into four separate regions that are synthesized independently. There will always be a created process for each one of the four regions, independently of the value set for
nps.Furthermore, each independent region can be further parallelized by generating multiple rows in parallel, although, due to the sequential nature of the algorithm, rows may halt temporarily.
npsindicates how many parallel rows (or stripes) will run per region.Output is kept the same for different values of
npsif the remaining arguments are kept the same; however, because the algorithm segments the generation area, its output differs from thegenerate_textureoutput.For info regarding the remaining parameters and returned data see
generate_texture().- Parameters:
nps – Number of Parallel Stripes (NPS); tells how many jobs to use for each of the 4 sections. Examples:
nps=1sets 1 parallel stripe per region, resulting in 4 processes.nps=2sets 2 parallel stripes per region, resulting in 8 processes.
- bmquilting.square.generate_texture_diagonal(src_texs: list[numpy.ndarray], patching_config: SquarePatchingConfig, out_h: NumPixels, out_w: NumPixels, seed: int, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray][source]¶
I’ve wondered if iterating diagonally with an overlap sized offset — so that the corners shared by 4 patches are covered by the new patches — could improve the generation quality, and perhaps help avoid “loose” seams.
For the most part doesn’t seem to make that big of a difference.
For info regarding the parameters and returned data see
generate_texture().
- bmquilting.square.generate_guided(proxy_texs: list[numpy.ndarray], src_texs: list[numpy.ndarray], patching_config: SquarePatchingConfig, out_h: NumPixels, out_w: NumPixels, seed: int, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray] | tuple[None, None, None][source]¶
Uses a variant of the source textures — the proxy textures — to guide the texture synthesis algorithm and reconstruct the synthesis result using the source textures.
Can be used, for example, in noisy images, where a filter can be applied so that the generation is not influenced by noise or some other visual artefacts or features.
For info regarding the remaining parameters see
generate_texture().- Parameters:
proxy_texs – Textures used to guide the generation; the textures order MUST MATCH those in the source textures list.
src_texs – Textures used to build the final result post proxy synthesis.
- Returns:
A tuple
(texture, seams, proxy_texture).proxy_textureis the output generated from the proxy synthesis, before reconstruction with the source textures.
- bmquilting.square.seamless_horizontal_multi(target_tex: numpy.ndarray, patching_config: SquarePatchingConfig, seed: int, src_texs: list[numpy.ndarray] = None, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray] | RetOnInterrupt[source]¶
Attempts to make a texture horizontally tileable by patching the texture at the edge, assembling a column of block sized patches over at the texture edge seam.
For info regarding the remaining parameters see
generate_texture().- Parameters:
target_tex – The texture to make seamless; will also be used to fetch the patches if
src_textsis None.src_texs – If provided, the patches are obtained from
src_texs; otherwise, they will be fetched fromtarget_tex.
- Returns:
A tuple
(texture, seams).
- bmquilting.square.seamless_vertical_multi(target_tex: numpy.ndarray, patching_config: SquarePatchingConfig, seed: int, src_texs: list[numpy.ndarray] = None, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray] | RetOnInterrupt[source]¶
Attempts to make a texture vertically tileable by patching the texture at the edge, assembling a row of block sized patches over at the texture edge seam.
For info regarding the parameters and returned data see
seamless_horizontal_multi().
- bmquilting.square.seamless_both_multi(target_tex, patching_config: SquarePatchingConfig, seed: int, src_texs: list[numpy.ndarray] = None, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray] | RetOnInterrupt[source]¶
Attempts to make a texture seamless, both vertically and horizontally tileable.
For info regarding the parameters and returned data see
seamless_horizontal_multi().
- bmquilting.square.seamless_horizontal_single(target_tex: numpy.ndarray, src_texs: numpy.ndarray, patching_config: SquarePatchingConfig, seed: int, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray] | RetOnInterrupt[source]¶
Attempts to make a texture horizontally tileable by patching the texture at the edge.
A single patch with width equal to the
block_sizedefined inpatching_configis used to patch the texture.For info regarding the parameters and returned data see
seamless_horizontal_multi().
- bmquilting.square.seamless_vertical_single(target_tex: numpy.ndarray, src_texs: numpy.ndarray, patching_config: SquarePatchingConfig, seed: int, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray] | RetOnInterrupt[source]¶
Attempts to make a texture vertically tileable by patching the texture at the edge.
A single patch with height equal to the
block_sizedefined inpatching_configis used to patch the texture.For info regarding the parameters and returned data see
seamless_horizontal_multi().
- bmquilting.square.seamless_both_single(target_tex: numpy.ndarray, src_texs: numpy.ndarray, patching_config: SquarePatchingConfig, seed: int, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray] | RetOnInterrupt[source]¶
Attempts to make a texture both vertically and horizontally tileable by patching the texture at the edges.
For info regarding the parameters and returned data see
seamless_horizontal_multi().
Circular Patching (CPHL)¶
- class bmquilting.circular.CircularPatchingConfig(patch_params: CircularPatchParams, blend_config: BlendConfig | None, tolerance: Percentage, outer_corners_weighted_template_matching: bool, spacing_factor: Percentage, astar_heur: int, _error_func: Callable)[source]¶
Bases:
objectCentralises all parameters needed across the circular patching subroutines.
Instances should be created via the class methods rather than directly, as the internal seam and error callables are managed automatically:
with_seams(),with_feathering(),with_hybrid(),advanced()- patch_params: CircularPatchParams¶
- blend_config: BlendConfig | None¶
- tolerance: Percentage¶
- outer_corners_weighted_template_matching: bool¶
- spacing_factor: Percentage¶
Spacing between the centers of two horizontal adjacent patches in the lattice with respect to the radius size.
May affect reproducibility of some algorithms when set to ~1.12 or lower.
- astar_heur: int¶
Heuristic for the astar algorithm used when computing seams.
Available options via the advanced class method:
DEFAULT: Uses Heuristic.DEFAULT.
ORTHO_Y: Uses Heuristic.ORTHOGONAL_Y.
NONE: No seams are computed.
- classmethod with_seams(diameter: NumPixels, overlap_ratio: Percentage, tolerance: Percentage, spacing_factor: Percentage, blend: bool = True) CircularPatchingConfig[source]¶
- classmethod with_feathering(diameter: NumPixels, overlap_ratio: Percentage, tolerance: Percentage, spacing_factor: Percentage) CircularPatchingConfig[source]¶
- classmethod with_hybrid(diameter: NumPixels, overlap_ratio: Percentage, tolerance: Percentage, spacing_factor: Percentage) CircularPatchingConfig[source]¶
- classmethod advanced(diameter: NumPixels, overlap_ratio: Percentage, blend_config: BlendConfig, tolerance: Percentage, spacing_factor: Percentage, a_star_variant: AstarVariant, outer_corners_weighted_template_matching: bool = False, custom_error_func: Callable = None) CircularPatchingConfig[source]¶
- property blend_into_patch: bool¶
- property spacing: int¶
- property use_seams: bool¶
- class bmquilting.circular.AstarVariant(*values)[source]¶
Bases:
EnumOptions for the minimum cut patch search algorithm.
- DEFAULT = 'default'¶
Uses the default pyastar2d with diagonals set to true.
- ORTHO_Y = 'ortho_y'¶
Uses pyastar2d with ORTHOGONAL_Y heuristic override and diagonals set to true.
- NONE = 'none'¶
Bypasses seam computation.
- bmquilting.circular.generate_cphl6p(src_texs: list[numpy.ndarray], patching_config: CircularPatchingConfig, out_h: NumPixels, out_w: NumPixels, seed: int, n_processes: int = 1, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray] | RetOnInterrupt[source]¶
Generates a texture using Circular Patches over a Hexagonal Lattice with 6 Partitions (CHPL6P).
Similar to
generate_cphl, but starts from the center of the generation area splitting it into 6 separate regions.The output from this function is not consistent with
generate_function. Furthermore, the providedseedcan only ensure reproducibility when thespacing_factorinpatching_configis higher than 1.12 due to potential patch overlaps at the partitions’ edges.For info regarding the remaining parameters and returned data see
generate_cphl().- Parameters:
n_processes – the number of processes to use; the minimum is 1, the maximum is 6.
- bmquilting.circular.generate_cphl6p_guided(proxy_texs: list[numpy.ndarray], src_texs: list[numpy.ndarray], patching_config: CircularPatchingConfig, out_h: NumPixels, out_w: NumPixels, seed: int, n_processes: int = 1, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray] | tuple[None, None, None][source]¶
Uses a variant of the source textures — the proxy textures — to guide the texture synthesis algorithm and reconstruct the synthesis result using the source textures.
Can be used, for example, in noisy images, where a filter can be applied so that the generation is not influenced by noise or some other visual artefacts or features.
When using proxy textures with a different size than the source, the patching parameters (radius and spacing) may be auto-adjusted to ensure perfect grid alignment and prevent spatial drift.
All proxy textures should have the same resolution, i.e., their scale with respect to their matching source texture should be the same.
If the
spacing_factoris not higher than 1.12 and the number of processes is higher than 1, there may be overlaps in the proxy generation whose application order during reconstruction differs, creating visual artefacts.For info regarding the remaining parameters see
generate_cphl()andgenerate_cphl6p().- Parameters:
proxy_texs – Textures used to guide the generation; the textures order MUST MATCH those in the source textures list.
src_texs – Textures used to build the final result post proxy synthesis.
patching_config – Patching Configuration set with respect to the source textures’ resolution.
- Returns:
A tuple
(texture, seams, proxy_synthesis)where:texture: reconstructed synthesis result using the source textures;seams: seams map, can be used for debug or for further refinements;proxy_synthesis: synthesis result using the proxy textures.
- bmquilting.circular.fill_cphl(target_tex: numpy.ndarray, mask: numpy.ndarray, src_texs: list[numpy.ndarray], patching_config: CircularPatchingConfig, seed: int, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray] | RetOnInterrupt[source]¶
Patch a texture with missing or corrupt areas.
In order to drawn patches from
target_texuse theutils.texture.set_invalid_texture_areafunction and pass the resulting texture as the source texture.For info regarding the remaining parameters and returned data see
generate_cphl().- Parameters:
target_tex – Target Texture, the texture to patch.
src_texs – Source Textures, the textures from where the patches are drawn from.
mask – Binary mask. If provided in float32 format the area to patch should be filled with zeroes, and the remaining area with ones. If provided in uint8 format use 255 instead of 1.
- bmquilting.circular.fill_cphl_guided(proxy_target_tex: numpy.ndarray, target_tex: numpy.ndarray, mask: numpy.ndarray, proxy_texs: list[numpy.ndarray], src_texs: list[numpy.ndarray], patching_config: CircularPatchingConfig, seed: int, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray] | tuple[None, None, None][source]¶
Patch a texture with missing or corrupt areas via a set of proxy textures.
For info regarding the remaining parameters and returned data see
generate_cphl6p_guided().- Parameters:
proxy_target_tex – Proxy Target Texture, the proxy for the texture to patch.
target_tex – Target Texture, the texture to patch.
patching_config – Patching Configuration set with respect to the source textures’ resolution.
mask – Binary mask. If provided in float32 format the area to patch should be filled with zeroes, and the remaining area with ones. If provided in uint8 format use 255 instead of 1.
- bmquilting.circular.seamless_vertical(target_tex: numpy.ndarray, patching_config: CircularPatchingConfig, seed: int, src_texs: list[numpy.ndarray] | None = None, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray] | tuple[None, None][source]¶
Attempts to make a texture vertically tileable by patching the texture at the edge, assembling a row of patches over at the texture edge seam.
For info regarding the parameters and returned data see
seamless_horizontal()andgenerate_texture().
- bmquilting.circular.seamless_horizontal(target_tex: numpy.ndarray, patching_config: CircularPatchingConfig, seed: int, src_texs: list[numpy.ndarray] | None = None, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray] | tuple[None, None][source]¶
Attempts to make a texture horizontally tileable by patching the texture at the edge, assembling a column of patches over at the texture edge seam.
For info regarding the remaining parameters see
generate_texture().- Parameters:
target_tex – The texture to make seamless; will also be used to fetch the patches if
src_textsis None.src_texs – If provided, the patches are obtained from
src_texs; otherwise, they will be fetched fromtarget_tex.
- Returns:
A tuple
(texture, seams).
- bmquilting.circular.seamless_both(target_tex: numpy.ndarray, patching_config: CircularPatchingConfig, seed: int, src_texs: list[numpy.ndarray] | None = None, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray] | tuple[None, None][source]¶
Attempts to make a texture both horizontally and vertically tileable by patching the texture at the edges.
For info regarding the parameters and returned data see
seamless_horizontal()andgenerate_texture().
- bmquilting.circular.seamless_both_guided(proxy_target_tex: numpy.ndarray, target_tex: numpy.ndarray, patching_config: CircularPatchingConfig, seed: int, proxy_texs: list[numpy.ndarray] | None = None, src_texs: list[numpy.ndarray] | None = None, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray] | tuple[None, None, None][source]¶
Attempts to make
target_texboth vertically and horizontally tileable by using a variant of the source textures — the proxy textures — to guide the texture synthesis algorithm and reconstruct the synthesis result using the source textures.For info regarding the parameters and returned data see
seamless_horizontal_guided().
- bmquilting.circular.seamless_vertical_guided(proxy_target_tex: np.ndarray, target_tex: np.ndarray, patching_config: CircularPatchingConfig, seed: int | SeedSequence, proxy_texs: list[np.ndarray] | None = None, src_texs: list[np.ndarray] | None = None, uicd: UiCoordData | None = None) tuple[np.ndarray, np.ndarray, np.ndarray] | tuple[None, None, None][source]¶
Attempts to make
target_texvertically tileable by using a variant of the source textures — the proxy textures — to guide the texture synthesis algorithm and reconstruct the synthesis result using the source textures.For info regarding the parameters and returned data see
seamless_horizontal_guided().
- bmquilting.circular.seamless_horizontal_guided(proxy_target_tex: np.ndarray, target_tex: np.ndarray, patching_config: CircularPatchingConfig, seed: int | SeedSequence, proxy_texs: list[np.ndarray] | None = None, src_texs: list[np.ndarray] | None = None, uicd: UiCoordData | None = None) tuple[np.ndarray, np.ndarray, np.ndarray] | tuple[None, None, None][source]¶
Attempts to make
target_texhorizontally tileable by using a variant of the source textures — the proxy textures — to guide the texture synthesis algorithm and reconstruct the synthesis result using the source textures.Can be used, for example, in noisy images, where a filter can be applied so that the generation is not influenced by noise or some other visual artefacts or features.
When using proxy textures with a different size than the source, the patching parameters (radius and spacing) may be auto-adjusted to ensure perfect grid alignment and prevent spatial drift.
If
proxy_texsandsrc_texsare not provided,proxy_target_texandtarget_texwill be used instead to draw patches during the proxy synthesis and reconstruction procedures respectively.For info regarding the remaining parameters and returned data see
generate_cphl().- Parameters:
proxy_target_tex – Proxy Target Texture, the proxy synthesis will run over this texture.
target_tex – Target Texture, the final output will be reconstructed using this texture.
patching_config – Patching Configuration set with respect to the source textures’ resolution.
proxy_texs – Textures used to guide the generation; the textures order MUST MATCH those in the source textures list.
src_texs – Textures used to build the final result post proxy synthesis.
- bmquilting.circular.refill_cphl(target_tex: numpy.ndarray, src_texs: list[numpy.ndarray], patching_config: CircularPatchingConfig, seed: int, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray] | RetOnInterrupt[source]¶
Synthesises on top of the provided
target_tex. Patch selection will consider the patch’s overlap withtarget_texand other patches.For info regarding the remaining parameters and returned data see
generate_cphl().- Parameters:
target_tex – Target Texture, the starting canvas for the generation.
- bmquilting.circular.refill_cphl_recursive(target_tex: numpy.ndarray, src_texs: list[numpy.ndarray], patching_configs: list[CircularPatchingConfig], seed: int, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray] | RetOnInterrupt[source]¶
Iterates the
patching_configs. The 1st item inpatching_configsis processed over the providedtarget_tex; the following generations run on top of prior outputs.For info regarding the remaining parameters and returned data see
generate_cphl().- Parameters:
target_tex – Target Texture, the starting canvas for the generation.
- bmquilting.circular.generate_cphl(src_texs: list[numpy.ndarray], patching_config: CircularPatchingConfig, out_h: int, out_w: int, seed: int, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray] | RetOnInterrupt[source]¶
Generate a texture with patches drawn from the provided source textures. This is done using Circular Patches over a Hexagonal Lattice (CPHL)
- Parameters:
src_texs – Source textures from where the patches will be drawn.
patching_config – Patching configuration contains the parameters for the generation, such as the patches’ diameter.
out_h – Output’s height in pixels.
out_w – Output’s width in pixels.
seed – Random Number Generator’s seed, ensures reproducibility.
uicd – Utility to track the generation progress and to process UI interrupts.
- Returns:
A tuple
(texture, seams).
- bmquilting.circular.generate_cphl_recursive(src_texs: list[numpy.ndarray], patching_configs: list[CircularPatchingConfig], out_h: int, out_w: int, seed: int, uicd: UiCoordData | None = None) tuple[numpy.ndarray, numpy.ndarray] | RetOnInterrupt[source]¶
Iterates the
patching_configs. The 1st item inpatching_configsis processed in the same way asgenerate_cphl, with an empty canvas; the following generations run on top of prior outputs.For info regarding the remaining parameters and returned data see
generate_cphl().
- bmquilting.circular.texture_transfer(src_texs: list[np.ndarray], target_img: np.ndarray, patching_config: CircularPatchingConfig, seed: int, last_diameter: int | None = None, alphas: list[float] | None = None, downscale_factor: int | None = None, target_roi: np.ndarray | None = None, invert_curated_target_values: bool = False, uicd: UiCoordData | None = None) tuple[np.ndarray, np.ndarray] | tuple[None, None][source]¶
Synthesise a new image by stitching patches from source textures to match a target image.
This is the simplest entry point for texture transfer: source textures and target are automatically curated, and an optional downscale path enables guided mode for faster synthesis. Despite its simplicity, it offers a comprehensive set of parameters for tweaking the synthesis.
Both
src_texsandtarget_imgneed to be either in BGR format (NOT RGB!) or in a single channel format representing the luminance; but they do not need to share the same format.- Parameters:
src_texs – List of one or more source texture images (numpy arrays). Patches are drawn from these images.
target_img – Guidance image whose overall appearance the result should match.
patching_config – Base configuration for all iterations. The
diameteris used for the first iteration, andoverlap_ratiois forced to 0.5 at every iteration regardless of the value set here.seed – Random seed for reproducibility. Two calls with identical arguments and the same seed produce identical outputs.
last_diameter – Patch diameter used in the final iteration. If
None, defaults to roughly 28% of the starting diameter. Intermediate diameters are interpolated between the first and last diameters.alphas – Per-iteration alpha weights controlling the trade-off between patch-overlap coherence (α=0) and target similarity (α=1). Defaults to
[0.75, 0.5, 0.25](three passes). The number of elements determines the number of iterations.downscale_factor – Integer divisor applied to both source and target before synthesis. For example, a value of 2 halves the dimensions. Patches are then blended at the original resolution (guided mode).
target_roi – Binary mask with the same height and width as
target_imgwhere 0 marks pixels to ignore (e.g., plain background). Improves target curation and avoids unnecessary computations.invert_curated_target_values – If
True, the normalised target is inverted (1 − value). Useful when the source texture is light-on-dark but the target is dark-on-light (or vice versa).uicd – UI coordination data for progress reporting and cancellation hooks. Can be left as
Nonewhen calling from a script with no UI.
- Returns:
A tuple
(texture, seams)where:textureis the synthesised output image in the same colour space and value range as the inputs.seamsis a diagnostic image visualising patch boundaries, useful for debugging tiling artefacts.
- bmquilting.circular.texture_transfer_advanced(src_texs: list[np.ndarray], curated_texs: list[np.ndarray], curated_target_img: np.ndarray, config_alpha_pairs: list[tuple[CircularPatchingConfig, float]], seed: int, target_roi: np.ndarray | None = None, uicd: UiCoordData | None = None) tuple[np.ndarray, np.ndarray] | tuple[None, None][source]¶
Advanced variant of
texture_transfer. Does not handle curation and the entire synthesis schedule must be provided by the user.For info regarding the remaining parameters see
texture_transfer().- Parameters:
curated_texs – The source textures processed in the same way as the
curated_target_img. The number of channels should be the same as thecurated_target_img, but can differ fromsrc_texs.curated_target_img – The target image processed in a way that makes its values meaningfully comparable with other equally curated images (e.g. normalised luminance).
config_alpha_pairs – The settings to run in each iteration (iteration schedule). Typically, both the block sizes and alphas are decreasing. Alpha is the weight given to a patch similitude to the target during patch selection: if alpha=1, then only the similitude with the target, at the location, is used; if alpha=0, then only the overlap with existing data is used for patch selection.
target_roi – Mask with the area of interest in the target marked with 1s (for float32) or 255s (for uint8), and the remaining area with 0s.
- Returns:
A tuple
(texture, seams).
- bmquilting.circular.texture_transfer_guided_advanced(proxy_texs: list[np.ndarray], src_texs: list[np.ndarray], curated_proxy_texs: list[np.ndarray], curated_proxy_target_img: np.ndarray, config_alpha_pairs: list[tuple[CircularPatchingConfig, float]], seed: int, proxy_target_roi: np.ndarray | None = None, uicd: UiCoordData | None = None) tuple[np.ndarray, np.ndarray, np.ndarray] | tuple[None, None, None][source]¶
Advanced variant of
texture_transferthat uses a variant of the source textures — the proxy textures — to guide the texture synthesis algorithm and reconstruct the synthesis result using the source textures.Can be used, for example, in noisy images, where a filter can be applied so that the generation is not influenced by noise or some other visual artefacts or features.
For info regarding the remaining parameters see
texture_transfer().- Parameters:
proxy_texs – The proxy textures used during proxy synthesis. All should have a matching source texture in
src_texsthat has the same index.src_texs – The source textures used during reconstruction to obtain the final output.
curated_proxy_texs – Proxy textures processed in the same way as
curated_proxy_target_img. The number of channels should be the same as thecurated_proxy_target_img, but can differ from the source and proxy textures.curated_proxy_target_img – Its resolution should be the same as the proxy textures
config_alpha_pairs – The “quasi” settings to run in each iteration (iteration schedule). The configs should be set as if they were to run at the
src_texsresolution, not at theproxy_texsresolution.proxy_target_roi – Mask with the area of interest in the target marked with 1s (for float32) or 255s (for uint8), and the remaining area with 0s. Should have the same size and resolution as
curated_proxy_target_img.
- Returns:
texture, seams, proxy_texture
Utilities¶
These utilities are located in the bmquilting.utils subpackage.
Progress Tracking & Interruption¶
Utilities to sync a GUI with the generation, or to interrupt the generation via a GUI.
- bmquilting.utils.ui_coord.DTYPE = 'uint32'¶
dtype used for the shared memory array
- bmquilting.utils.ui_coord.ON_THREAD_JOIN_TIMEOUT = 2.0¶
timeout used when joining a registered thread on JobMemoryManager exit
- class bmquilting.utils.ui_coord.UiCoordData(jobs_shm_name: str, job_id: int)[source]¶
Bases:
objectManages job progress and interruption signals via SharedMemory.
The shared memory buffer is expected to be a
uint32array where: * Index 0: Interrupt signal (value > 0 triggers interruption). * Index 1+: Job data slots for progress tracking.- Parameters:
jobs_shm_name – The unique name of the shared memory block.
job_id – The index offset for this specific job’s data slot.
- jobs_shm_name: str¶
- job_id: int¶
- raise_or_add(value: int = 0) None[source]¶
Raises JobInterrupted if an interrupt signal is detected. Otherwise, adds count to the progress tracker shared memory array.
- Raises:
JobInterrupted – If the UI has signaled to stop.
- request_interrupt() None[source]¶
Sets the interrupt signal for this shared memory block. Call this from the UI thread/process to stop the worker.
- class bmquilting.utils.ui_coord.JobMemoryManager(num_jobs: int)[source]¶
Bases:
object- property name¶
- exception bmquilting.utils.ui_coord.JobInterrupted[source]¶
Bases:
ExceptionCustom exception to signal a UI interrupt.
- bmquilting.utils.ui_coord.handle_ui_interrupts(return_on_cancel: any = 'INTERRUPTED', auto_close: bool = True, re_raise: bool = False)[source]¶
Decorator for job functions that handle UI interruptions via UiCoordData.
- Parameters:
return_on_cancel – The value to return if a JobInterrupted exception is caught.
auto_close – If True, automatically calls .close() on the ‘uicd’ object found in arguments.
re_raise – Raise JobInterrupted again after closing uicd.
- bmquilting.utils.ui_coord.check_ui(uicd: UiCoordData | None, to_add: int = 0)[source]¶
Helper to be called inside functions. Keeps the code readable and raises the JobInterrupt when an interrupt is triggered.
Block Size Estimation¶
- bmquilting.utils.guess_blocksize.guess_nice_block_size(src: numpy.ndarray, heuristic: str | bool = 'fft', max_block_size: NumPixels | None = None) NumPixels[source]¶
Block size guess heuristic selector.
- Parameters:
src – must be single channel if “fft” is used.
heuristic –
“fft”: FFT-based analysis only (default)
”sift”: SIFT keypoint-based analysis only
”both”: FFT + SIFT combined analysis
- bool: backward-compatible flag for old freq_analysis_only behavior
True => FFT only
False => both, FFT + SIFT
max_block_size – further restricts the upper bound for the guess. the actually used upper bound might be lower than max_block_size.
Texture Helpers¶
- bmquilting.utils.texture.get_texture_variants(img: numpy.ndarray, original: bool = True, flip_h: bool = True, flip_v: bool = True, flip_both: bool = True, transposed: bool = True, transpose_flip_h: bool = True, transpose_flip_v: bool = True, transpose_flip_both: bool = True) list[numpy.ndarray][source]¶
- Parameters:
flip_both – Same as rotating 180 degrees.
transpose_flip_h – Same as rotating 90 degrees clockwise.
transpose_flip_v – Same as rotating 90 degrees anti-clockwise.
Compute mirrored and transposed variants of the provided image.
- bmquilting.utils.texture.arrange_texture_variants_grid(img: numpy.ndarray, margin: int = 1, original: bool = True, flip_h: bool = True, flip_v: bool = True, flip_both: bool = True, transposed: bool = True, transpose_flip_h: bool = True, transpose_flip_v: bool = True, transpose_flip_both: bool = True) numpy.ndarray[source]¶
WARNING: Can worsen performance significantly and may affect patch selection due to matchTemplate optimizations.
Why use this despite the above warning?
It can improve performance significantly under specific conditions. Here are some points to take into account:
If the texture shape is not approximately a square, avoid transposed variants as these will increase the invalid area, leading to more wasted computations.
There are less wasted computations the smaller the patch; this make it a potential good candidate to deal with latent sources.
DevNote: Based on some preliminary tests it seems that the “sweet spot” appears to be: 1) above the 160.000 addressable units (pixels if dealing with images); so a 200x200 using only mirrors or 100x100 using both mirrors and transposed variants 2) a block size smaller than 20% the texture size and bigger than 2.5% the texture size. x) There seem to be a no-go area within the above defined parameter area, usually around a particular block size; I do not know why that is.
Call get_texture_variants and composite all results into a single grid image.
Layout rationale — the 8 variants form 4 natural vertical-mirror pairs, so each pair occupies one column (mirror placed directly below its counterpart):
col 0 col 1 col 2 col 3
┌──────────┬────────────┬─────────────┬──────────────────────┐ | original │ flip_h │ transposed │ transpose_flip_h │ row 0 |──────────┼────────────┼─────────────┼──────────────────────┤ | flip_v │ flip_both │ transpose_ │ transpose_flip_both │ row 1 | │ │ flip_v │ │ └──────────┴────────────┴─────────────┴──────────────────────┘
Disabled variants simply reduce a column to a single image (or skip the column entirely if both halves of a pair are disabled). A hole therefore only ever appears at the bottom of a column — never mid-layout — keeping wasted space to an absolute minimum without any search algorithm.
Column width = max image width inside that column. Row height = max image height at that row index across all columns. Images are top-left aligned within their cell.
- Parameters:
img – Source image (H × W × C); integer arrays are cast to float32 and divided by 255.0.
margin – Minimum gap in pixels between adjacent images.
1 suffices; unless, perhaps, you want to patch the image before using it.
- Returns:
Single composite image as a float32 np.ndarray.
- bmquilting.utils.texture.get_texture_rotated_variants(img: numpy.ndarray, number_of_cardinals: int, interpolation=cv2.INTER_LINEAR) list[numpy.ndarray][source]¶
Generate N equally-spaced rotations (360° / N). Each rotated texture is tightly cropped to remove empty pixels.
- Parameters:
img – Input texture (2D or 3D).
number_of_cardinals – Number of equally spaced orientations.
interpolation – OpenCV interpolation flag. Examples: cv2.INTER_LINEAR (default), cv2.INTER_NEAREST, cv2.INTER_CUBIC, etc.
- Returns:
List[np.ndarray]: All rotated & cropped textures.
- bmquilting.utils.texture.quick_checksum(tensor: numpy.ndarray, check_ratio: float = 0.05) int[source]¶
Computes a quick, position-sensitive checksum by hashing a strategic slice (the first N% of the array) of the tensor’s raw bytes.
- bmquilting.utils.texture.add_salt_and_pepper(image: numpy.ndarray, amount: float = 0.05, salt_vs_pepper: float = 0.5, seed: int = 1)[source]¶
Adds salt and pepper noise to an image. :param image: Input image :param amount: Total proportion of image pixels to replace with noise :param salt_vs_pepper: Proportion of salt (white) vs pepper (black) :param seed: Seed for the random generated noise :return: Noisy image
- bmquilting.utils.texture.set_invalid_texture_area(src: numpy.ndarray, mask: numpy.ndarray) numpy.ndarray[source]¶
Invalidate an area in the src texture so that no patch can be fetched from it. If the source is of integer type (except for signed int8), the values in the returned array will be divided by 255. :param src: will not be edited, the output is a new numpy array. :param mask: zeroes will be set as invalid :return: a copy of src with the invalid texture area set to np.inf
- bmquilting.utils.texture.curate_for_tex_transfer(tex: np.ndarray, cvt_code: int | None = cv2.COLOR_BGR2GRAY, mask: np.ndarray | None = None) np.ndarray[source]¶
Converts tex to a single channels 2D array, if not already converted. Applies the following operations in order: Gaussian Blur; CLAHE; Equalize Histogram. :param tex: image :param cvt_code: if set to None, the channels’ mean is used; otherwise, cv2.cvtColor(tex, cvt_code) is used. :param mask: binary mask (1s & 0s; not 255s in case of uint8 masks). :return: the “curated” texture with shape HxWx1 (ndim=3)
Mathematical Functions¶
- class bmquilting.utils.functions.FuncWrapper[source]¶
Bases:
ABCSingle variable function.
inplace_func MUST be implemented, and SHOULD do computations inplace.
Child classes should also implement get_label for plotting purposes but not required to use in texture generation.
- class bmquilting.utils.functions.NormalizedTunableSigmoid(k=-0.5, deadzone=0.0, beta=0.5)[source]¶
Bases:
FuncWrapperNormalized Tunable Sigmoid (NTS) with optional soft deadzone, in-place on ND arrays.
- Variables:
k – Controls the overall shape of the function. Positive values make the graph ‘N’ shaped. Negative values make the graph ‘S’ shaped. Default value is -0.5.
deadzone – Defines the size of the dead-zone (where y is fixed) around x=0.5. IMPORTANT: setting deadzone to zero or a negative value selects a faster function variant. Default value is 0.0, meaning that dead-zone is ignored.
beta – Controls how soft/hard does the function blend into the dead-zone. Only applicable for positive dead-zone values. Default value is 0.5.
Notes
Supports Numba (flat memory) or NumPy fallback
k ∈ [-0.99, 0.99]
Input clamped to [-1,1]
Output always in [0,1]
- property adjusted_beta¶
- property beta¶
- property deadzone¶
- property k¶
- class bmquilting.utils.functions.PowerCurve(p: float = 2.0, top: float = 1.0)[source]¶
Bases:
FuncWrapperPower-curve mapping in [0,1]: - y = (x^p) / (top^p) - y is clamped into [0,1].
- Variables:
p – Curvature exponent.
top – Input at which the output should reach 1 (before clipping). Must be in the interval (0,1].
Notes
Computation is performed fully in-place.
If Numba is available, a faster JIT version is used.
Input x values are clamped to [-1,1] before the transformation.
p < 1 → convex soft fade-in
p > 1 → concave, steeper near top
- class bmquilting.utils.functions.LogScalingFunc(gain: float = 100.0, top: float = 0.5)[source]¶
Bases:
FuncWrapperLogarithmic Rescaling in [0, 1]: - y = log1p(gain * x) / log1p(gain * top) - final y is clipped to [0,1]
- Variables:
gain – steepness of the curve.
top – Input at which the output should reach 1 (before clipping). Must be in the interval (0,1].
Notes
Computation is performed fully in-place.
If Numba is available, a faster JIT version is used.
Input x values are clamped to [0,1] before the transformation.
- gain: float¶
Controls the steepness of the curve
- top: float¶
Defines the maximum input for the normalizer
- class bmquilting.utils.functions.FuncParams(func_wrapper: bmquilting.utils.functions.FuncWrapper, input_scaling: float = 1.0, input_offset: float = 0.0, output_scaling: float = 1.0, output_offset: float = 0.0)[source]¶
Bases:
object- func_wrapper: FuncWrapper¶
- input_scaling: float = 1.0¶
- input_offset: float = 0.0¶
applied post scaling
- output_scaling: float = 1.0¶
- output_offset: float = 0.0¶
applied post scaling
- apply_input_transform(x: numpy.ndarray) numpy.ndarray[source]¶
Applies the input scaling and offset: y = x * scale + offset
- apply_input_transform_inplace(x: numpy.ndarray) numpy.ndarray[source]¶
Applies the input scaling and offset IN-PLACE: y = x * scale + offset
- class bmquilting.utils.functions.FuncSum(func_params_1: FuncParams, func_params_2: FuncParams)[source]¶
Bases:
FuncWrapperA FuncWrapper that computes the sum of two underlying function’s outputs, each with independent input and output scaling/offset transforms.
The computation is:
[ (f1(x * s1_in + o1_in) * s1_out + o1_out) ] + [ (f2(x * s2_in + o2_in) * s2_out + o2_out) ]
It prioritizes using f2’s in-place method to minimize memory allocation for the final sum operation.
- func_params_1: FuncParams¶
- func_params_2: FuncParams¶
- inplace_func(x: numpy.ndarray) None[source]¶
Computes the sum of the two transformed function outputs, storing the result in the input array ‘x’ (inplace).
The calculation order is optimized to use f2’s in-place capability: 1. Calculate f1_y (out-of-place) and store it. 2. Calculate f2_y (in-place in x). 3. Add the stored f1_y to x.
- Parameters:
x – The input numpy array (np.ndarray). This array will be overwritten with the final sum result.
- class bmquilting.utils.functions.TwoNTS(k: float = -0.5)[source]¶
Bases:
FuncSumFuncSum composed of 2 scaled and offset NTS functions (without dead-zones). Input clipped to [-1, 1] post input scaling & offset. Output clipped to [ 0, 1] prior to output scaling & offset.
- property k¶
- inplace_func(x: numpy.ndarray)[source]¶
Computes the sum of the two transformed function outputs, storing the result in the input array ‘x’ (inplace).
The calculation order is optimized to use f2’s in-place capability: 1. Calculate f1_y (out-of-place) and store it. 2. Calculate f2_y (in-place in x). 3. Add the stored f1_y to x.
- Parameters:
x – The input numpy array (np.ndarray). This array will be overwritten with the final sum result.