Source code for phenotypic.enhance._bayesshrink_enhancer

from __future__ import annotations

from typing import TYPE_CHECKING, Literal

if TYPE_CHECKING:
    from phenotypic._core._image import Image

from skimage.restoration import denoise_wavelet

from ..abc_ import ImageEnhancer


[docs] class BayesShrinkEnhancer(ImageEnhancer): """Denoise ``detect_mat`` with adaptive BayesShrink wavelet thresholding. Applies wavelet-domain denoising with per-subband adaptive thresholds computed from local statistics. Preserves more fine detail than :class:`VisuShrinkEnhancer` by denoising aggressively only where noise is high and gently where signal dominates. For algorithm details, see :doc:`/explanation/what_enhancement_does`. Args: sigma: Noise standard deviation in [0, 1] scale. ``None`` (default) auto-estimates via MAD. Typical range: 0.01--0.05 for moderate scanner/camera noise. Accurate estimation improves adaptive threshold quality. wavelet: Wavelet family. ``'db2'`` (default) balances smoothness and locality; ``'db4'`` preserves finer details. Must be orthogonal. mode: Thresholding mode. ``'soft'`` (default) produces smoother results; ``'hard'`` preserves edges more aggressively. wavelet_levels: Decomposition depth. ``None`` (default) uses max-3 automatically. Higher values allow finer noise/signal separation. clip: Clip output to [0, 1]. Default: ``True``. Set to ``False`` when using with variance-stabilizing transforms (e.g., GAT). Returns: Image: Input image with ``detect_mat`` denoised via adaptive wavelet thresholding. ``rgb`` and ``gray`` are unchanged. Best For: - Images with spatially varying noise from uneven illumination. - Preserving colony texture and internal morphology during denoising. - Scanner noise and camera artifacts on plates where fine detail matters for downstream measurement. - Pre-filtering before feature extraction or texture analysis. Consider Also: - :class:`VisuShrinkEnhancer` for faster denoising with a universal threshold when spatial noise uniformity is acceptable. - :class:`BM3DDenoiser` for state-of-the-art denoising of structured noise patterns. - :class:`BilateralDenoise` for edge-preserving smoothing without wavelet decomposition. See Also: :doc:`/tutorials/notebooks/03_enhancing_before_detection` for a visual walkthrough of enhancement pipelines on plate images. :doc:`/explanation/what_enhancement_does` for background on wavelet denoising and threshold selection strategies. """
[docs] def __init__( self, sigma: float | None = None, wavelet: str = "db2", mode: Literal["soft", "hard"] = "soft", wavelet_levels: int | None = None, clip: bool = True, ): """Initialize BayesShrink adaptive wavelet denoiser. Parameters: sigma (float | None): Noise standard deviation in [0, 1] scale. None (default) auto-estimates. More accurate sigma improves adaptive thresholding quality. Typical: 0.01-0.05 for moderate noise. wavelet (str): Wavelet type. 'db2' (default) is general-purpose. 'db4' for finer details, 'sym2' for symmetric filters. mode (Literal['soft', 'hard']): 'soft' (default) for smoother denoising, 'hard' for sharper edges with possible noise residue. wavelet_levels (int | None): Decomposition depth. None (default) uses max-3. Increase for very noisy images. clip (bool): Whether to clip output to [0, 1] range. Default True. Set to False when using with variance-stabilizing transforms (e.g., GAT) that require preserving the original scale. """ self.sigma = sigma self.wavelet = wavelet self.mode = mode self.wavelet_levels = wavelet_levels self.clip = clip
def _operate(self, image: Image) -> Image: """Apply BayesShrink adaptive wavelet denoising to detection matrix. Returns: Modified Image with denoised detect_mat """ denoised = denoise_wavelet( image=image.detect_mat[:], sigma=self.sigma, wavelet=self.wavelet, mode=self.mode, wavelet_levels=self.wavelet_levels, method="BayesShrink", channel_axis=None, rescale_sigma=True, ) if self.clip: denoised = denoised.clip(0.0, 1.0) image.detect_mat[:] = denoised return image