Source code for phenotypic.refine._skeletonize

from __future__ import annotations

from typing import Literal, TYPE_CHECKING

if TYPE_CHECKING:
    from phenotypic._core._image import Image

from skimage.morphology import skeletonize

from phenotypic.abc_ import ObjectRefiner


[docs] class Skeletonize(ObjectRefiner): """Reduce object masks to single-pixel-wide skeletons via medial-axis thinning. Compresses each detected region to its medial axis (centerline), preserving topological connectivity while discarding all interior and boundary pixels. The result captures the branching structure and elongation of each colony without the area contribution of filled masks. For a comparison of morphological refinement methods, see :doc:`/explanation/refinement_strategies`. Best For: - Extracting colony centerlines for elongation or orientation analysis. - Analyzing branching patterns in filamentous fungi or spreading bacterial phenotypes. - Simplifying masks before spatial graph analysis or hyphal network tracing. - Reducing boundary noise before measuring advanced morphological features such as tortuosity or branch count. Consider Also: - :class:`Thinning` for iterative boundary peeling with explicit control over the number of thinning steps. - :class:`MaskGradient` when boundary outlines are needed rather than medial axes. - :class:`MaskErosion` for uniform inward shrinking that preserves filled object interiors. Args: method: Skeletonization algorithm. ``"zhang"`` applies Zhang--Suen fast parallel thinning for 2-D binary masks. ``"lee"`` uses Lee's octree-based algorithm, which also supports 3-D arrays. ``None`` selects automatically based on array dimensionality. Default: None. Returns: Image: Input image with ``objmask`` replaced by the single-pixel-wide medial-axis skeleton. Assigning ``objmask`` rebuilds ``objmap`` from the skeleton mask. Raises: ValueError: If ``method`` is not ``"zhang"``, ``"lee"``, or ``None``. See Also: :doc:`/how_to/notebooks/refine_noisy_boundaries` for skeleton-based analysis workflows on real plate images. :doc:`/explanation/refinement_strategies` for a comparison of morphological refinement methods. """ method: Literal["zhang", "lee"] | None = None def _operate(self, image: Image) -> Image: image.objmask[:] = skeletonize(image.objmask.copy(), method=self.method) return image