Source code for phenotypic.enhance._gray_opening

from __future__ import annotations

from typing import Literal, TYPE_CHECKING

from skimage import morphology

if TYPE_CHECKING:
    from phenotypic._core._image import Image

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


[docs] class GrayOpening(ImageEnhancer, FootprintMixin): """Remove small bright artifacts from ``detect_mat`` via morphological opening. Applies erosion followed by dilation with a structuring element, removing bright features smaller than the element while preserving the shape of larger structures. Effectively suppresses dust particles, small noise speckles, and tiny satellite colonies. For algorithm details, see :doc:`/explanation/what_enhancement_does`. Args: shape: Structuring element geometry. ``'square'`` (default) preserves edges; ``'diamond'`` is more rounded at diagonals; ``'disk'`` provides uniform circular operations. width: Diameter of the structuring element in pixels. Larger values remove larger features. Typical range: 3--15. Default: 5. n_iter: Number of times to apply the opening. Repeated opening with a small element produces smoother results than a single pass with a larger element. Default: 1. Returns: Image: Input image with ``detect_mat`` morphologically opened. ``rgb`` and ``gray`` are unchanged. Best For: - Removing dust particles and small bright noise from plate scans. - Suppressing tiny satellite colonies that interfere with detection of larger colonies. - Smoothing the detection surface before background subtraction. Consider Also: - :class:`WhiteTophatEnhance` when you want to isolate (not remove) small bright structures. - :class:`SubtractWhiteTophat` for subtracting small bright artifacts while retaining the background. - :class:`BilateralDenoise` for noise reduction that preserves edges without morphological assumptions. See Also: :doc:`/tutorials/notebooks/03_enhancing_before_detection` for a visual walkthrough of enhancement pipelines on plate images. """
[docs] def __init__(self, shape: Literal["square", "diamond", "disk"] = "square", width: int = 5, n_iter: int = 1): """ A kernel configuration class for image processing tasks, particularly suited for applications such as analyzing and processing images of microbe colonies on solid media agar. This class enables the definition of a kernel shape and size, which significantly impacts the morphological operations applied to the image (e.g., filtering, dilation, erosion). Adjusting these parameters can enhance or hinder the detection and analysis of colony boundaries, shapes, and distribution. Attributes: shape (Literal["square", "diamond", "disk"]): The geometric shape of the kernel. This attribute governs the pattern and extent of neighboring pixels involved in the processing operation. Choosing "square" results in a uniform rectangular influence, which may be suitable for isotropic features but could introduce angular artifacts in circular features like microbe colonies. The "diamond" shape provides a more angular neighborhood pattern that helps preserve diagonal structures. On the other hand, "disk" introduces a circular pattern that can align well with colony boundaries and reduce distortions in rounded features. width (int): The size (diameter) of the kernel in pixels. A larger width increases the area of influence during image processing, which can smooth out smaller features like noise but potentially merge closely spaced microbe colonies into larger regions. Smaller values offer finer detail and greater distinction between colonies but may leave noise unprocessed or small artifacts unchanged. n_iter (int): Number of times to apply the opening operation. Repeated opening with a small element produces smoother results than a single pass with a larger element. Default: 1. """ self.shape = shape self.width = width self.n_iter = n_iter
def _operate(self, image: Image) -> Image: footprint = self._make_footprint(shape=self.shape, width=self.width) for _ in range(self.n_iter): image.detect_mat[:] = morphology.opening( image=image.detect_mat[:], footprint=footprint, ) return image