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.

  1. 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).

  2. 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: object

Manages job progress and interruption signals via SharedMemory.

The shared memory buffer is expected to be a uint32 array 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: Exception

Custom 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: object

Centralises 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]
get_patch_kernel(dtype=numpy.uint8) numpy.ndarray[source]
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: Enum

Options 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. nps indicates how many parallel rows (or stripes) will run per region.

Output is kept the same for different values of nps if the remaining arguments are kept the same; however, because the algorithm segments the generation area, its output differs from the generate_texture output.

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=1 sets 1 parallel stripe per region, resulting in 4 processes. nps=2 sets 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_texture is 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_texts is None.

  • src_texs – If provided, the patches are obtained from src_texs; otherwise, they will be fetched from target_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_size defined in patching_config is 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_size defined in patching_config is 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: object

Centralises 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
get_patch_kernel(dtype=numpy.uint8) numpy.ndarray[source]
class bmquilting.circular.AstarVariant(*values)[source]

Bases: Enum

Options 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 provided seed can only ensure reproducibility when the spacing_factor in patching_config is 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_factor is 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() and generate_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_tex use the utils.texture.set_invalid_texture_area function 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() and generate_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_texts is None.

  • src_texs – If provided, the patches are obtained from src_texs; otherwise, they will be fetched from target_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() and generate_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_tex both 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_tex vertically 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_tex 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.

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_texs and src_texs are not provided, proxy_target_tex and target_tex will 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 with target_tex and 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 in patching_configs is processed over the provided target_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 in patching_configs is processed in the same way as generate_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_texs and target_img need 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 diameter is used for the first iteration, and overlap_ratio is 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_img where 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 None when calling from a script with no UI.

Returns:

A tuple (texture, seams) where: texture is the synthesised output image in the same colour space and value range as the inputs. seams is 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 the curated_target_img, but can differ from src_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_transfer that 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_texs that 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 the curated_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_texs resolution, not at the proxy_texs resolution.

  • 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: object

Manages job progress and interruption signals via SharedMemory.

The shared memory buffer is expected to be a uint32 array 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.

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.utils.ui_coord.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.utils.ui_coord.JobInterrupted[source]

Bases: Exception

Custom 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.optional_njit(*args, **kwargs)[source]
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)

bmquilting.utils.texture.crop_to_multiple(arr: numpy.ndarray, multiple: int)[source]

Mathematical Functions

class bmquilting.utils.functions.FuncWrapper[source]

Bases: ABC

Single 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.

func(x: numpy.ndarray) numpy.ndarray[source]
abstractmethod inplace_func(x: numpy.ndarray)[source]
class bmquilting.utils.functions.NormalizedTunableSigmoid(k=-0.5, deadzone=0.0, beta=0.5)[source]

Bases: FuncWrapper

Normalized 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
inplace_func(x: numpy.ndarray) None[source]
get_label() str[source]
class bmquilting.utils.functions.PowerCurve(p: float = 2.0, top: float = 1.0)[source]

Bases: FuncWrapper

Power-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

inplace_func(x: numpy.ndarray)[source]
get_label() str[source]
class bmquilting.utils.functions.LogScalingFunc(gain: float = 100.0, top: float = 0.5)[source]

Bases: FuncWrapper

Logarithmic 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

inplace_func(x: numpy.ndarray)[source]
get_label() str[source]
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

apply_output_transform(y: numpy.ndarray) numpy.ndarray[source]

Applies the output scaling and offset: z = y * scale + offset

apply_output_transform_inplace(y: numpy.ndarray) None[source]

Applies the output scaling and offset IN-PLACE: y = y * scale + offset

class bmquilting.utils.functions.FuncSum(func_params_1: FuncParams, func_params_2: FuncParams)[source]

Bases: FuncWrapper

A 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: FuncSum

FuncSum 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.

get_label() str[source]