Source code for phenotypic.enhance._frangi_vesselness
from __future__ import annotations
from typing import Iterable, TYPE_CHECKING
if TYPE_CHECKING:
from phenotypic._core._image import Image
from skimage.filters import frangi
from phenotypic.abc_ import ImageEnhancer
[docs]
class FrangiVesselness(ImageEnhancer):
"""Enhance tubular structures in detect_mat using Hessian-based vesselness filtering.
Computes the Frangi vesselness measure from Hessian matrix eigenvalues at
multiple scales, producing a response map that highlights elongated features
(hyphae, branches, mycelial networks). The output is a probability-like map
(0--1) that typically requires thresholding before detection.
For algorithm details, see :doc:`/explanation/filamentous_fungi_algorithm`.
Args:
sigmas: Scales (standard deviations) for Hessian computation. Smaller
values detect finer structures; larger values detect thicker ones.
Span the expected range of hyphal widths in pixels. Default:
``(0.5, 1, 1.5)``.
alpha: Blobness sensitivity (0--1). Lower is more permissive.
Default: 0.5.
beta: Structuredness sensitivity (0--1). Lower is more permissive.
Default: 0.5.
gamma: Background suppression threshold. Larger values suppress
low-curvature (flat) regions more aggressively. ``None`` uses
half of the max Hessian norm. Default: ``None``.
black_ridges: If ``True``, detect dark ridges on bright background.
If ``False``, detect bright ridges on dark background.
Default: ``False``.
Returns:
Image: Input image with ``detect_mat`` set to the vesselness response
map. ``rgb`` and ``gray`` are unchanged.
Best For:
- Filamentous fungi (*Neurospora*, *Aspergillus*) with branching hyphae.
- Thin, elongated structures that global thresholding misses.
- Interconnected mycelial networks or biofilm structures.
- Pre-filtering before ``FilamentousFungiDetector``.
Consider Also:
- :class:`MeijeringRidgeFilter` for neurite-like structures with fewer
parameters to tune.
- :class:`SatoRidgeFilter` for ridge detection with different
sensitivity characteristics.
- :class:`PhaseCongruencyEnhancer` for illumination-invariant edge
enhancement of filaments.
References:
[1] A. F. Frangi, W. J. Niessen, K. L. Vincken, and M. A. Viergever,
"Multiscale vessel enhancement filtering," in *MICCAI*, 1998,
pp. 130--137.
See Also:
:doc:`/tutorials/notebooks/10_detecting_filamentous_fungi` for a
visual walkthrough of filamentous fungi detection.
:doc:`/explanation/filamentous_fungi_algorithm` for the theory behind
Hessian-based vesselness filtering.
"""
[docs]
def __init__(
self,
sigmas: Iterable[float] = (0.5, 1, 1.5),
alpha: float = 0.5,
beta: float = 0.5,
gamma: float = None,
black_ridges: bool = False,
):
"""
Parameters:
sigmas (tuple | list): Sequence of standard deviations for Gaussian
derivatives. Smaller values detect finer features, larger values
detect thicker structures. Default (0.5, 1, 1.5).
alpha (float): Vesselness sensitivity to blobness. Lower values are
more permissive. Range: 0 to 1. Default 0.5.
beta (float): Vesselness sensitivity to structuredness. Lower values
are more permissive. Range: 0 to 1. Default is None which uses
half of the max Hessian norm.
gamma (float): Threshold for background suppression. Larger values
suppress low-curvature regions more aggressively. Default 15.
black_ridges (bool): If True, detect dark ridges (colonies) on bright
background. If False, detect bright ridges on dark background.
For agar plates with dark colonies on light background, use True.
Default False.
"""
self.sigmas = sigmas
self.alpha = alpha
self.beta = beta
self.gamma = gamma
self.black_ridges = black_ridges
def __setattr__(self, name: str, value: object) -> None:
if name == "sigmas" and value is not None:
value = tuple(value) # type: ignore[arg-type]
super().__setattr__(name, value)
def _operate(self, image: Image) -> Image:
image.detect_mat[:] = frangi(
image=image.detect_mat[:],
sigmas=self.sigmas,
alpha=self.alpha,
beta=self.beta,
gamma=self.gamma,
black_ridges=self.black_ridges,
)
return image