Skip to content

tissue_components

Segment background and foreground (cells) components of rgb image.

Parameters:

Name Type Description Default
img ndarray

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

required
label ndarray

The cell mask. Shape (H, W).

required

Returns:

Type Description
Tuple[ndarray, ndarray]

Tuple[np.ndarray, np.ndarray]: The background and dark components. Shapes (H, W).

Source code in src/histolytics/stroma_feats/utils.py
def tissue_components(
    img: np.ndarray, label: np.ndarray
) -> Tuple[np.ndarray, np.ndarray]:
    """Segment background and foreground (cells) components of rgb image.

    Parameters:
        img (np.ndarray):
            The input image. Shape (H, W, 3).
        label (np.ndarray):
            The cell mask. Shape (H, W).

    Returns:
        Tuple[np.ndarray, np.ndarray]:
            The background and dark components. Shapes (H, W).
    """
    # mask out dark pixels
    kmasks = kmeans_img(img, n_clust=3)

    # Determine the mean color of each k-means cluster
    cluster_means = [img[kmasks == i].mean(axis=0) for i in range(1, 4)]

    # Identify the bg, cells, and stroma clusters based on mean color
    bg_label = (
        np.argmin([np.linalg.norm(mean - [255, 255, 255]) for mean in cluster_means])
        + 1
    )
    dark_label = np.argmin([np.linalg.norm(mean) for mean in cluster_means]) + 1
    # stroma_label = 6 - bg_label - dark_label  # Since we have 3 clusters

    # Create masks for each cluster
    bg_mask = kmasks == bg_label
    dark_mask = kmasks == dark_label

    if label is not None:
        dark_mask += label > 0

    bg_mask = rm_objects_mask(erosion(bg_mask, square(3)), min_size=1000)
    dark_mask = rm_objects_mask(dilation(dark_mask, square(3)), min_size=200)
    bg_mask = fill_holes_mask(bg_mask, min_size=500)
    dark_mask = fill_holes_mask(dark_mask, min_size=500)

    return bg_mask, dark_mask