phenotypic.correction#

Image/grid correction for agar plate captures.

Offers operations that realign grids or correct field-of-view drift so detected colonies stay anchored to their intended wells or pins. The grid aligner adjusts spacing and offsets using reference points or heuristics suited to arrayed plate layouts. Also includes wavelet denoising correctors for full-image noise removal across all components (RGB, gray, detect_mat).

class phenotypic.correction.BayesShrinkCorrector(sigma: float | None = None, wavelet: str = 'db2', mode: Literal['soft', 'hard'] = 'soft', wavelet_levels: int | None = None, convert2ycbcr: bool = True)[source]#

Bases: ImageCorrector

Denoise all image components using adaptive BayesShrink wavelet thresholding.

Apply subband-adaptive wavelet denoising to RGB (if present), grayscale, and detection matrix simultaneously. BayesShrink estimates a separate threshold for each wavelet subband, preserving fine colony detail while suppressing noise more selectively than a universal threshold.

For algorithm details, see What Enhancement Actually Does.

Parameters:
  • sigma (float | None) – Noise standard deviation. None auto-estimates from the finest wavelet subband. Typical range: 0.01–0.1 for normalized images. Default: None.

  • wavelet (str) – Wavelet family name. 'db2' balances smoothness and locality; 'db4' preserves finer spatial detail. Default: 'db2'.

  • mode (Literal['soft', 'hard']) – Thresholding mode. 'soft' produces smoother results; 'hard' retains sharper edges with possible noise residue. Default: 'soft'.

  • wavelet_levels (int | None) – Number of decomposition levels. None uses the maximum minus three (automatic). Default: None.

  • convert2ycbcr (bool) – Denoise RGB in YCbCr space so luminance and chrominance are handled separately, preserving colony color. Only applies when RGB data is present. Default: True.

Returns:

Input image with all components (RGB, gray, detect_mat) transformed by adaptive wavelet denoising.

Return type:

Image

Best For:
  • Plates imaged with aging or high-ISO cameras that introduce spatially varying sensor noise.

  • RGB plate scans destined for publication where color fidelity and fine detail must be preserved.

  • Pre-processing before multi-channel feature extraction (color composition and morphology).

Consider Also:
  • VisuShrinkCorrector when a faster, simpler universal threshold is acceptable.

  • StableDenoise for variance-stabilized BM3D denoising of grayscale channels with Poisson-Gaussian noise.

  • BayesShrinkEnhancer when only the detection matrix should be denoised (non-destructive to RGB and gray).

References

[1] S. G. Chang, B. Yu, and M. Vetterli, “Adaptive wavelet thresholding for image denoising and compression,” IEEE Trans. Image Process., vol. 9, no. 9, pp. 1532–1546, Sep. 2000.

See also

/how_to/notebooks/correct_color_cast for a walkthrough of denoising plate images before color analysis.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(sigma: float | None = None, wavelet: str = 'db2', mode: Literal['soft', 'hard'] = 'soft', wavelet_levels: int | None = None, convert2ycbcr: bool = True)[source]#

Initialize BayesShrink adaptive corrector for all image components.

Parameters:
  • sigma (float | None) – Noise level. None (default) auto-estimates. BayesShrink benefits from accurate sigma for optimal adaptive thresholding. Test explicit values if auto-estimation seems off.

  • wavelet (str) – Wavelet type. ‘db2’ (default) is general-purpose. ‘db4’ for finer detail preservation.

  • mode (Literal['soft', 'hard']) – ‘soft’ (default) for smoothness, ‘hard’ for sharper edges with possible noise residue.

  • wavelet_levels (int | None) – Levels. None = max-3 (automatic).

  • convert2ycbcr (bool) – Denoise RGB in YCbCr (True, default) for better color preservation. Only applies when RGB exists.

apply(image: Image, inplace: bool = False) Image#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.correction.ColorCheckerProfile(checker_type: str = 'ColorChecker24 - After November 2014', degree: int = 2, target_illuminant: str = 'D65', median_filter_size: int = 10, stddev_mag_threshold: float = 15.0, border_distance_threshold: float = 12.0, core_fraction: float = 0.5, ridge_lambda: float = 0.001, outlier_sigma: float = 2.0, rois: list[tuple[slice, slice]] | None = None)[source]#

Bases: object

Profile fitted from a colour checker card for root-polynomial correction.

Measures patch colours from one or more ROIs in an image, matches them against published reference values for the chosen checker type, rejects outlier patches, and solves for a root-polynomial colour correction matrix (Finlayson 2015). The resulting matrix can be applied to entire images via ColorCorrector.

Parameters:
  • checker_type (str) – Key in colour.CCS_COLOURCHECKERS. Defaults to the post-2014 X-Rite ColorChecker 24.

  • degree (int) – Root-polynomial degree (1–4). 2 is recommended.

  • target_illuminant (str) – Target whitepoint for the correction (e.g. 'D65').

  • median_filter_size (int) – Kernel size for per-ROI median filtering.

  • stddev_mag_threshold (float) – Column-stddev threshold for border detection during checker centering.

  • border_distance_threshold (float) – Lab Euclidean distance below which a pixel is classified as border rather than swatch.

  • core_fraction (float) – Fraction of centroid-to-boundary distance used to define the reliable core of each patch.

  • ridge_lambda (float) – Ridge-regression regularisation parameter for the root-polynomial fit.

  • outlier_sigma (float) – Patches whose Delta-E 2000 exceeds mean + outlier_sigma * stddev are rejected as outliers.

  • rois (list[tuple[slice, slice]] | None) – List of (row_slice, col_slice) tuples delimiting checker card regions in the source image. Stored for use by fit() and dashboard().

correction_matrix#

Fitted correction matrix once fit() or _fit_from_patch_colors() has been called.

diagnostics#

Per-patch and aggregate quality metrics.

is_fitted#

True after a successful fit.

dashboard(show: bool = True) Any[source]#

Display an interactive Panel dashboard for quality inspection.

Uses the image and ROIs stored during fit(). If fitted via _fit_from_patch_colors(), pipeline and segmentation sections are hidden.

In Jupyter notebooks the dashboard renders inline. In terminals a local web server is launched.

Parameters:

show (bool) – Auto-display the dashboard. Set False in tests or for programmatic use.

Returns:

The Panel layout object.

Raises:
Return type:

Any

fit(image: Image) ColorCheckerProfile[source]#

Fit the profile from checker-card ROIs stored at initialisation.

Parameters:

image (Image) – Source image containing visible checker cards.

Returns:

self for method chaining.

Raises:

ValueError – If no ROIs were provided at initialisation.

Return type:

ColorCheckerProfile

classmethod from_dict(data: dict[str, Any]) ColorCheckerProfile[source]#

Reconstruct a profile from a serialised dictionary.

Parameters:

data (dict[str, Any]) – Dictionary previously produced by to_dict().

Returns:

Reconstructed ColorCheckerProfile instance.

Return type:

ColorCheckerProfile

to_dict() dict[str, Any][source]#

Serialise the profile to a JSON-compatible dictionary.

Returns:

Dictionary containing all parameters and the fitted correction matrix (as a nested list).

Return type:

dict[str, Any]

property correction_matrix: numpy.ndarray#

Root-polynomial correction matrix (shape (3, F)).

property diagnostics: dict[str, Any]#

Diagnostic metrics from the most recent fit.

property is_fitted: bool#

Whether a correction matrix has been fitted.

class phenotypic.correction.ColorCorrector(profile: ColorCheckerProfile, output_illuminant: str = 'D65')[source]#

Bases: ImageCorrector

Apply root-polynomial color correction to an entire image.

Takes a fitted ColorCheckerProfile and applies its correction matrix to every pixel. The pipeline is:

  1. Normalise RGB to [0, 1] float.

  2. Decode sRGB gamma to linear light.

  3. Expand to root-polynomial features (Finlayson 2015).

  4. Multiply by the correction matrix.

  5. Re-encode to sRGB gamma.

  6. Clip and scale back to the original integer dtype.

  7. Recompute grayscale and detect_mat from corrected RGB.

Use cases (agar plates):

  • Standardise plate images captured under different lighting to a common colour space for consistent colony colour measurement.

  • Remove colour casts from scanner or camera illumination so that phenotypic colour differences between strains are comparable across batches.

  • Produce publication-ready images with accurate colour reproduction of dyed or pigmented colonies.

Parameters:
correction_matrix#

The root-polynomial correction matrix stored as a nested list (serialisable).

degree#

Polynomial expansion degree matching the profile.

output_illuminant#

Target illuminant label (informational).

Examples

Correct an image using a pre-fitted profile:

>>> from phenotypic.correction import ColorCheckerProfile, ColorCorrector
>>> import numpy as np
>>> profile = ColorCheckerProfile(rois=[...], degree=2)  
>>> profile.fit(image)  
>>> corrector = ColorCorrector(profile)  
>>> corrected = corrector.apply(image)  
__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(profile: ColorCheckerProfile, output_illuminant: str = 'D65') None[source]#

Initialise the corrector from a fitted profile.

Parameters:
Raises:

ValueError – If profile has not been fitted.

Return type:

None

apply(image: Image, inplace: bool = False) Image#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

dashboard(show: bool = True) Any[source]#

Display an interactive diagnostic dashboard.

Delegates to the underlying profile’s dashboard method.

Parameters:

show (bool) – Auto-display the dashboard.

Returns:

The Panel layout object.

Return type:

Any

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.correction.GridAligner(axis: int = 0, mode: str = 'edge')[source]#

Bases: GridCorrector

Correct grid rotation by aligning colony centroids to row or column axes.

Compute the optimal rotation angle from linear regression of colony centroid positions along the chosen axis, then rotate the entire image to minimize angular misalignment. Re-detection of objects after alignment is strongly recommended because pixel coordinates shift.

For algorithm details, see Grid vs Non-Grid Detection.

Parameters:
  • axis (int) – Alignment axis. 0 aligns rows (row-wise regression on column centroid positions); 1 aligns columns. Default: 0.

  • mode (str) – Edge-fill mode passed to the rotation function. 'edge' replicates border pixels; 'constant' fills with zeros. Default: 'edge'.

Returns:

Input image rotated so that colony centroids align with the specified axis. All image components are transformed.

Return type:

GridImage

Raises:

ValueError – If axis is not 0 or 1.

Best For:
  • Arrayed plates scanned at a slight angle where grid rows or columns are not axis-aligned.

  • High-throughput imaging setups with inconsistent plate orientation between scans.

  • Pre-processing before grid-based measurement to ensure accurate row and column assignment.

Consider Also:
  • ImagePadder to add safety margins before rotation so corner colonies are not clipped.

  • ImageCropper to remove excess background after alignment.

See also

How To: Correct Grid Rotation for a visual walkthrough of grid alignment on real plate images.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

apply(image: GridImage, inplace=False) GridImage#

Calculates the optimal rotation angle and applies it to a grid image for alignment along the specified axis.

The method performs alignment of a GridImage object along either nrows or columns based on the specified axis. It calculates the linear regression slope and intercept for the axis, determines geometric properties of the grid vertices, and computes rotation angles needed to align the image. The optimal angle is found by minimizing the error across all computed angles, and the image is rotated accordingly.

Raises:

ValueError – If the axis is not 0 (row-wise) or 1 (column-wise).

Parameters:

image (ImageGridHandler) – The arr grid image object to be aligned.

Returns:

The rotated grid image object after alignment.

Return type:

ImageGridHandler

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.correction.ImageCropper(left: int | None = None, right: int | None = None, top: int | None = None, bottom: int | None = None)[source]#

Bases: ImageCorrector

Remove pixels from image edges by specifying crop margins.

Crops all image components (rgb, gray, detect_mat, objmask, objmap) together. When applied to a GridImage, the grid structure is preserved and grid positions are recalculated for the cropped dimensions.

Parameters:
  • left (int | None) – Pixels to remove from the left edge. None means no cropping. Default: None.

  • right (int | None) – Pixels to remove from the right edge. Default: None.

  • top (int | None) – Pixels to remove from the top edge. Default: None.

  • bottom (int | None) – Pixels to remove from the bottom edge. Default: None.

Returns:

Input image with all components cropped to the specified margins.

Return type:

Image

Best For:
  • Removing scanner margins or borders outside the agar plate.

  • Eliminating edge artifacts (bent agar, labeling, moisture).

  • Standardizing image dimensions across a batch of plates.

Consider Also:
  • ImagePadder for adding pixels instead of removing them.

  • BorderObjectRemover for removing edge-touching colonies without changing image dimensions.

See also

How To: Crop and Pad Images for Batch Consistency for a visual walkthrough of cropping and padding operations.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(left: int | None = None, right: int | None = None, top: int | None = None, bottom: int | None = None)[source]#

Initialize an ImageCropper with pixel margins to remove from each edge.

Creates a cropper that removes the specified number of pixels from each edge of the image. All parameters are optional and default to None (no cropping from that edge).

Parameters:
  • left (int | None, optional) – Number of pixels to remove from the left edge. Must be non-negative. If None, the left edge is not cropped (equivalent to 0). Defaults to None.

  • right (int | None, optional) – Number of pixels to remove from the right edge. Must be non-negative. If None, the right edge is not cropped (equivalent to 0). Defaults to None.

  • top (int | None, optional) – Number of pixels to remove from the top edge. Must be non-negative. If None, the top edge is not cropped (equivalent to 0). Defaults to None.

  • bottom (int | None, optional) – Number of pixels to remove from the bottom edge. Must be non-negative. If None, the bottom edge is not cropped (equivalent to 0). Defaults to None.

Raises:

ValueError – If any parameter is negative. All crop margins must be non-negative integers (or None).

apply(image: Image, inplace: bool = False) Image#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.correction.ImagePadder(left: int | None = None, right: int | None = None, top: int | None = None, bottom: int | None = None, mode: str = 'constant', constant_value: int | float = 0)[source]#

Bases: ImageCorrector

Extend image dimensions by adding pixels to any combination of edges.

Pad the image on the left, right, top, and/or bottom using a configurable fill mode. All image components (RGB, gray, detect_mat, objmap) are padded in sync; the object map is always zero-padded to preserve label integrity. When applied to a GridImage, grid structure is preserved and positions are recalculated automatically.

For usage context, see How To: Crop and Pad Images for Batch Consistency.

Parameters:
  • left (int | None) – Pixels to add on the left edge. None means no padding. Typical range: 50–200. Default: None.

  • right (int | None) – Pixels to add on the right edge. None means no padding. Typical range: 50–200. Default: None.

  • top (int | None) – Pixels to add on the top edge. None means no padding. Typical range: 50–200. Default: None.

  • bottom (int | None) – Pixels to add on the bottom edge. None means no padding. Typical range: 50–200. Default: None.

  • mode (str) – Fill strategy passed to np.pad. Accepted values: 'constant', 'reflect', 'edge', 'symmetric', 'wrap', 'linear_ramp', 'maximum', 'mean', 'median', 'minimum', 'empty'. 'edge' is safest for colony analysis; 'reflect' reduces convolution boundary artifacts. Default: 'constant'.

  • constant_value (int | float) – Fill value when mode='constant'. 0 for black borders, 255 for white. Default: 0.

Returns:

Input image with all components padded by the specified amounts. GridImage grid positions are recalculated.

Return type:

Image

Raises:
  • ValueError – If any padding value is negative.

  • ValueError – If mode is not a valid np.pad mode.

Best For:
  • Adding safety margins before rotation so corner colonies are not clipped.

  • Standardizing image dimensions across a batch for pipelines that require uniform size.

  • Creating border space when colonies grow near plate edges, improving grid detection accuracy.

Consider Also:
  • ImageCropper when the image needs to be reduced rather than extended.

  • GridAligner for correcting plate rotation after padding.

See also

How To: Crop and Pad Images for Batch Consistency for a visual walkthrough of padding and cropping plate images. How To: Correct Grid Rotation for combining padding with rotation correction.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(left: int | None = None, right: int | None = None, top: int | None = None, bottom: int | None = None, mode: str = 'constant', constant_value: int | float = 0)[source]#

Initialize an ImagePadder with pixel margins to add on each edge.

Creates a padder that adds the specified number of pixels to each edge of the image. All margin parameters are optional and default to None (no padding from that edge).

Parameters:
  • left (int | None, optional) – Pixels to add on left edge. Must be non-negative. If None, no left padding (equivalent to 0). Defaults to None.

  • right (int | None, optional) – Pixels to add on right edge. Must be non-negative. If None, no right padding (equivalent to 0). Defaults to None.

  • top (int | None, optional) – Pixels to add on top edge. Must be non-negative. If None, no top padding (equivalent to 0). Defaults to None.

  • bottom (int | None, optional) – Pixels to add on bottom edge. Must be non-negative. If None, no bottom padding (equivalent to 0). Defaults to None.

  • mode (str, optional) – Padding mode for np.pad. Options include ‘constant’ (uniform value), ‘reflect’ (mirror at boundary), ‘edge’ (replicate edge pixels), ‘symmetric’ (symmetric reflection), ‘wrap’ (periodic), and others. Defaults to ‘constant’.

  • constant_value (int | float, optional) – Value for constant mode padding. Only used when mode=’constant’. Typical values: 0 for black (default), 255 for white. Defaults to 0.

Raises:
  • ValueError – If any padding parameter is negative. All padding margins must be non-negative integers (or None).

  • ValueError – If mode is not a valid np.pad mode.

Examples

Create a padder for symmetric margins:

>>> from phenotypic.correction import ImagePadder
>>> # Add 50 pixels to all four edges
>>> padder = ImagePadder(left=50, right=50, top=50, bottom=50)

Create a padder for asymmetric margins:

>>> from phenotypic.correction import ImagePadder
>>> # Add padding on top and right, keep left and bottom minimal
>>> padder = ImagePadder(top=100, right=75, left=0, bottom=0)

Create a padder with reflection to avoid artifacts:

>>> from phenotypic.correction import ImagePadder
>>> padder = ImagePadder(
...     left=80, right=80, top=80, bottom=80,
...     mode='reflect'
... )
>>> # Reflection preserves edge patterns, good for convolutions
apply(image: Image, inplace: bool = False) Image#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.correction.StableDenoise(block_size: int = 8, stage_arg: Literal['all_stages', 'hard_thresholding'] = 'all_stages', *, gain: float = 1.0, mu: float = 0.0, sigma: float = 0.0, scale_factor: float | None = None)[source]#

Bases: ImageCorrector

Denoise grayscale channels using variance-stabilized BM3D collaborative filtering.

Combine the Generalized Anscombe Transform (GAT) with BM3D denoising in a single corrector step. The GAT stabilizes Poisson-Gaussian noise variance so that BM3D operates optimally, then the inverse GAT restores the original intensity scale. Writing through the gray accessor triggers a detect_mat reset, so downstream reads reflect the denoised result.

For algorithm details, see What Enhancement Actually Does.

Parameters:
  • block_size (int) – BM3D patch side length in pixels. Larger values capture more context but increase computation. Default: 8.

  • stage_arg (Literal['all_stages', 'hard_thresholding']) – Processing stages. 'all_stages' runs hard thresholding followed by Wiener filtering for best quality; 'hard_thresholding' is faster. Default: 'all_stages'.

  • gain (float) – Camera gain in electrons per ADU. Default: 1.0.

  • mu (float) – Read-noise mean (baseline offset). Default: 0.0.

  • sigma (float) – Read-noise standard deviation. 0.0 assumes pure Poisson noise, appropriate for most plate scanners. Default: 0.0.

  • scale_factor (float | None) – Multiplier converting normalized [0, 1] data to photon counts. None auto-detects from image bit depth. Default: None.

Returns:

Input image with grayscale channel denoised via the accessor cascade. RGB is unchanged.

Return type:

Image

Raises:

ValueError – If gain is not positive, sigma is negative, scale_factor is not positive, or stage_arg is not a recognized value.

Best For:
  • Low-light or high-ISO plate images with photon-counting (Poisson-Gaussian) noise.

  • Improving intensity measurement accuracy before colony size or opacity quantification.

  • CCD/CMOS scanned plates where mixed noise models apply.

Consider Also:
  • BayesShrinkCorrector when all components (including RGB) need denoising simultaneously.

  • BM3DDenoiser for enhancer-only BM3D on the detection matrix without modifying grayscale.

  • VisuShrinkCorrector for a faster wavelet-based alternative when Poisson noise modelling is not required.

References

[1] M. Makitalo and A. Foi, “Optimal inversion of the generalized Anscombe transformation for Poisson-Gaussian noise,” IEEE Trans. Image Process., vol. 22, no. 1, pp. 91–103, Jan. 2013.

See also

/how_to/notebooks/correct_color_cast for combining denoising with color correction workflows.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(block_size: int = 8, stage_arg: Literal['all_stages', 'hard_thresholding'] = 'all_stages', *, gain: float = 1.0, mu: float = 0.0, sigma: float = 0.0, scale_factor: float | None = None)[source]#

Initialize GAT-stabilized BM3D corrector for gray and detect_mat.

Parameters:
  • block_size (int) – BM3D patch size. Default 8.

  • stage_arg (Literal["all_stages", "hard_thresholding"]) – Denoising stages. ‘all_stages’ gives best quality; ‘hard_thresholding’ is faster.

  • gain (float) – Camera gain in electrons per ADU. Default 1.0.

  • mu (float) – Read noise mean (baseline offset). Default 0.0.

  • sigma (float) – Read noise standard deviation. Default 0.0 (pure Poisson noise).

  • scale_factor (float | None) – Converts normalized [0,1] data to counts. None (default) auto-detects from image metadata.

apply(image: Image, inplace: bool = False) Image#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.correction.VisuShrinkCorrector(sigma: float | None = None, wavelet: str = 'db2', mode: Literal['soft', 'hard'] = 'soft', wavelet_levels: int | None = None, convert2ycbcr: bool = True)[source]#

Bases: ImageCorrector

Denoise all image components using a universal VisuShrink wavelet threshold.

Apply VisuShrink wavelet denoising to RGB (if present), grayscale, and detection matrix simultaneously. Unlike VisuShrinkEnhancer, which modifies only the detection matrix, this corrector transforms all image representations to maintain cross-component consistency.

For algorithm details, see What Enhancement Actually Does.

Parameters:
  • sigma (float | None) – Noise standard deviation. None auto-estimates from the image. For RGB, internal channel scaling is handled automatically. Default: None.

  • wavelet (str) – Wavelet family name. 'db2' is general-purpose; 'db4' preserves finer detail. Default: 'db2'.

  • mode (Literal['soft', 'hard']) – Thresholding mode. 'soft' produces smoother results; 'hard' retains sharper edges. Default: 'soft'.

  • wavelet_levels (int | None) – Number of decomposition levels. None uses the maximum minus three (automatic). Default: None.

  • convert2ycbcr (bool) – Denoise RGB in YCbCr space so luminance and chrominance are handled separately, preserving colony color. Only applies when RGB data is present. Default: True.

Returns:

Input image with all components (RGB, gray, detect_mat) transformed by VisuShrink wavelet denoising.

Return type:

Image

Best For:
  • Quick, uniform denoising of raw plate scans for archival or publication where a single threshold is acceptable.

  • Removing scanner noise from all image components before downstream multi-channel analysis.

  • Plates with relatively uniform noise where adaptive subband thresholding is not necessary.

Consider Also:
  • BayesShrinkCorrector for adaptive subband thresholds that preserve finer colony detail.

  • StableDenoise for variance-stabilized BM3D denoising when Poisson-Gaussian noise modelling is important.

  • VisuShrinkEnhancer when only the detection matrix should be denoised (non-destructive to RGB and gray).

See also

/how_to/notebooks/correct_color_cast for combining denoising with color correction workflows.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(sigma: float | None = None, wavelet: str = 'db2', mode: Literal['soft', 'hard'] = 'soft', wavelet_levels: int | None = None, convert2ycbcr: bool = True)[source]#

Initialize VisuShrink corrector for all image components.

Parameters:
  • sigma (float | None) – Noise level. None (default) auto-estimates. For RGB, denoise_wavelet handles internal scaling.

  • wavelet (str) – Wavelet type. ‘db2’ (default) is general-purpose.

  • mode (Literal['soft', 'hard']) – ‘soft’ (default) for smoothness.

  • wavelet_levels (int | None) – Levels. None = max-3.

  • convert2ycbcr (bool) – Denoise RGB in YCbCr space (True, default) for better color preservation. Only applies if RGB exists.

apply(image: Image, inplace: bool = False) Image#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.