Source code for phenotypic.enhance._opening_subtract_bg

from __future__ import annotations

from typing import Literal, TYPE_CHECKING

import cv2

if TYPE_CHECKING:
    from phenotypic._core._image import Image

from phenotypic.abc_ import ImageEnhancer
from phenotypic.tools_.mixin import FootprintMixin


[docs] class OpeningSubtractBg(ImageEnhancer, FootprintMixin): """Subtract background from ``detect_mat`` via OpenCV-accelerated morphological opening. Computes the white top-hat transform (original minus morphological opening) using OpenCV's C++/SIMD backend, isolating bright foreground structures smaller than the structuring element while removing slow-varying background intensity. Significantly faster than scikit-image equivalents for high-throughput workflows. For algorithm details, see :doc:`/explanation/what_enhancement_does`. Args: shape: Structuring element geometry. ``'disk'`` (default) gives isotropic removal suited to round colonies; ``'square'`` is fastest; ``'diamond'`` is a compromise. width: Diameter of the structuring element in pixels. Must be larger than colony diameter to avoid subtracting colony signal. Typical range: 31--101. Default: 51. n_iter: Number of morphological iterations. Higher values intensify background removal. Default: 1. Returns: Image: Input image with ``detect_mat`` containing only foreground structures smaller than the structuring element. ``rgb`` and ``gray`` are unchanged. Best For: - Fast background subtraction for high-throughput plate screening. - Removing uneven illumination gradients and agar shading before colony detection. - Pipelines where speed matters (large batches, parameter sweeps). - Drop-in performance upgrade over :class:`SubtractRollingBall` when a flat structuring element is acceptable. Consider Also: - :class:`SubtractRollingBall` for parabolic background estimation that handles gradual intensity ramps more accurately. - :class:`SubtractGaussian` for Gaussian-based background subtraction with continuous control over the background scale. - :class:`WhiteTophatEnhance` when you want to keep only the extracted small bright structures. See Also: :doc:`/tutorials/notebooks/03_enhancing_before_detection` for a visual walkthrough of background subtraction on plate images. :doc:`/explanation/what_enhancement_does` for background on morphological background removal strategies. """ def __init__( self, shape: Literal["square", "diamond", "disk"] = "disk", width: int = 51, n_iter: int = 1, ): self.shape = shape self.width = width self.n_iter = n_iter def _operate(self, image: Image) -> Image: image.detect_mat[:] = cv2.morphologyEx( src=image.detect_mat[:], op=cv2.MORPH_TOPHAT, kernel=self._make_footprint(shape=self.shape, width=self.width), iterations=self.n_iter, ) return image