Skip to content

extract_collagen_fibers

Extract collagen fibers from a H&E image.

Parameters:

Name Type Description Default
img ndarray

The input image. Shape (H, W, 3).

required
label ndarray

Nuclei binary or label mask. Shape (H, W). This is used to mask out the nuclei when extracting collagen fibers. If None, the entire image is used.

None
sigma float

The sigma parameter for the Canny edge detector.

2.5
min_size float

Minimum size of the edges to keep.

25
rm_bg bool

Whether to remove the background component from the edges.

False
rm_fg bool

Whether to remove the foreground component from the edges.

False
mask ndarray

Binary mask to restrict the region of interest. Shape (H, W). For example, it can be used to mask out tissues that are not of interest.

None
device str

Device to use for computation. Options are 'cpu' or 'cuda'. If set to 'cuda', CuPy and cucim will be used for GPU acceleration.

'cpu'

Returns:

Type Description
ndarray

np.ndarray: The collagen fibers binary mask. Shape (H, W).

Examples:

>>> from histolytics.data import hgsc_stroma_he
>>> from histolytics.stroma_feats.collagen import extract_collagen_fibers
>>> from skimage.measure import label
>>> from skimage.color import label2rgb
>>> import matplotlib.pyplot as plt
>>>
>>> im = hgsc_stroma_he()
>>> collagen = extract_collagen_fibers(im, label=None, rm_bg=False, rm_fg=False)
>>>
>>> fig, ax = plt.subplots(1, 2, figsize=(8, 4))
>>> ax[0].imshow(label2rgb(label(collagen), bg_label=0))
>>> ax[0].set_axis_off()
>>> ax[1].imshow(im)
>>> ax[1].set_axis_off()
>>> fig.tight_layout()

out

Source code in src/histolytics/stroma_feats/collagen.py
def extract_collagen_fibers(
    img: np.ndarray,
    label: np.ndarray = None,
    sigma: float = 2.5,
    min_size: int = 25,
    rm_bg: bool = False,
    rm_fg: bool = False,
    mask: np.ndarray = None,
    device: str = "cpu",
) -> np.ndarray:
    """Extract collagen fibers from a H&E image.

    Parameters:
        img (np.ndarray):
            The input image. Shape (H, W, 3).
        label (np.ndarray):
            Nuclei binary or label mask. Shape (H, W). This is used to mask out the
            nuclei when extracting collagen fibers. If None, the entire image is used.
        sigma (float):
            The sigma parameter for the Canny edge detector.
        min_size (float):
            Minimum size of the edges to keep.
        rm_bg (bool):
            Whether to remove the background component from the edges.
        rm_fg (bool):
            Whether to remove the foreground component from the edges.
        mask (np.ndarray):
            Binary mask to restrict the region of interest. Shape (H, W). For example,
            it can be used to mask out tissues that are not of interest.
        device (str):
            Device to use for computation. Options are 'cpu' or 'cuda'. If set to 'cuda',
            CuPy and cucim will be used for GPU acceleration.

    Returns:
        np.ndarray: The collagen fibers binary mask. Shape (H, W).

    Examples:
        >>> from histolytics.data import hgsc_stroma_he
        >>> from histolytics.stroma_feats.collagen import extract_collagen_fibers
        >>> from skimage.measure import label
        >>> from skimage.color import label2rgb
        >>> import matplotlib.pyplot as plt
        >>>
        >>> im = hgsc_stroma_he()
        >>> collagen = extract_collagen_fibers(im, label=None, rm_bg=False, rm_fg=False)
        >>>
        >>> fig, ax = plt.subplots(1, 2, figsize=(8, 4))
        >>> ax[0].imshow(label2rgb(label(collagen), bg_label=0))
        >>> ax[0].set_axis_off()
        >>> ax[1].imshow(im)
        >>> ax[1].set_axis_off()
        >>> fig.tight_layout()
    ![out](../../img/collagen_fiber.png)
    """
    if label is not None and img.shape[:2] != label.shape:
        raise ValueError(
            f"Shape mismatch: img has shape {img.shape}, but label has shape {label.shape}."
        )

    if mask is not None:
        if label is not None and mask.shape != label.shape:
            raise ValueError(
                f"Shape mismatch: mask has shape {mask.shape}, but label has shape {label.shape}."
            )
        elif label is None and mask.shape != img.shape[:2]:
            raise ValueError(
                f"Shape mismatch: mask has shape {mask.shape}, but img has shape {img.shape[:2]}."
            )

    if _has_cp and device == "cuda":
        edges = canny(rgb2gray_cp(cp.array(img)).get(), sigma=sigma, mode="nearest")
    else:
        edges = canny(rgb2gray(img), sigma=sigma, mode="nearest")

    if rm_bg or rm_fg:
        if label is not None:
            label = dilation(label, footprint_rectangle((5, 5)))
            edges[label > 0] = 0

        bg_mask, dark_mask = tissue_components(img, label, device=device)
        if rm_bg and rm_fg:
            edges[bg_mask | dark_mask] = 0
        elif rm_bg:
            edges[bg_mask] = 0
        elif rm_fg:
            edges[dark_mask] = 0
    else:
        if label is not None:
            edges[label > 0] = 0

    if _has_cp and device == "cuda":
        edges = remove_small_objects_cp(
            cp.array(edges), min_size=min_size, connectivity=2
        ).get()
    else:
        edges = remove_small_objects(edges, min_size=min_size, connectivity=2)

    if mask is not None:
        edges = edges & mask

    return edges