Source code for phenotypic.detect._mean_detector
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from phenotypic._core._image import Image
from skimage.filters import threshold_mean
from skimage.segmentation import clear_border
from ..abc_ import ThresholdDetector
[docs]
class MeanDetector(ThresholdDetector):
"""Detect colonies by thresholding at the arithmetic mean pixel intensity.
Use the arithmetic mean of all pixel intensities as the classification
boundary, assigning pixels above the mean to colony foreground. This
parameter-free baseline is fast, deterministic, and requires no histogram
assumptions, making it a reliable fallback when adaptive methods produce
unexpected results. For a full comparison of detection strategies see
:doc:`/explanation/detection_strategies_compared`.
Best For:
- Quick baseline detection requiring no parameter tuning.
- Sanity-checking preprocessing steps before applying a more
specialised detector.
- Plates where colony and background areas are roughly equal in size,
placing the mean near the natural separation point.
- Debugging pipelines where a simple, predictable threshold is needed.
Consider Also:
- :class:`OtsuDetector` for a statistically optimal threshold that
adapts to the histogram shape.
- :class:`TriangleDetector` when colonies are sparse and the histogram
is strongly skewed toward the background.
- :class:`IsodataDetector` for an iterative refinement that converges
to a class-mean midpoint more robustly than the global mean.
Args:
ignore_zeros: Exclude zero-intensity pixels from the mean calculation
before computing the threshold. Enable for plates with black
borders or masked regions. Default: False.
ignore_borders: Remove colonies touching image edges via
``clear_border()``. Recommended for grid-based colony counting
to eliminate partial colonies at plate boundaries. Default: True.
Returns:
Image: Input image with ``objmask`` set to the binary colony mask and
``objmap`` set to labeled connected components.
Raises:
ValueError: If all pixels share the same intensity value, making
threshold computation degenerate.
See Also:
:doc:`/tutorials/notebooks/02_detecting_colonies` for a step-by-step
tutorial on basic colony detection.
:doc:`/how_to/notebooks/choose_detection_algorithm` for guidance on
selecting the right detector for your plate images.
:doc:`/explanation/detection_strategies_compared` for an in-depth
comparison of all thresholding strategies.
"""
ignore_zeros: bool = False
ignore_borders: bool = True
def _operate(self, image: Image) -> Image:
"""Binarizes the given image matrix using the Mean threshold method.
This function modifies the arr image by applying a binary mask to
its enhanced matrix (`detect_mat`). The binarization threshold is
automatically determined using Mean method. The resulting binary
mask is stored in the image's `objmask` attribute.
Args:
image (Image): The arr image object. It must have an `detect_mat`
attribute, which is used as the basis for creating the binary mask.
Returns:
Image: The arr image object with its `objmask` attribute updated
to the computed binary mask other_image.
"""
enh_matrix = image.detect_mat[:]
mask = image.detect_mat[:] >= threshold_mean(
enh_matrix[enh_matrix != 0] if self.ignore_zeros else enh_matrix
)
mask = clear_border(mask) if self.ignore_borders else mask
image.objmask = mask
return image
# Set the docstring so that it appears in the sphinx documentation
MeanDetector.apply.__doc__ = MeanDetector._operate.__doc__