Label image refinement#

Similar to refining binary images it is also possible to refine label images. This notebook shows how to do this.

See also

import pyclesperanto_prototype as cle
from skimage.data import cells3d
import matplotlib.pyplot as plt
from skimage.morphology import closing, disk
from skimage.io import imread
from skimage.filters.rank import maximum
from skimage.segmentation import expand_labels
from skimage.measure import label
import numpy as np

As a starting point, let’s assume an algorithm produced this label image.

label_image = cle.asarray(imread("../../data/membrane_2d_labels.tif")).astype(np.uint32)
label_image
cle._ image
shape(256, 256)
dtypeuint32
size256.0 kB
min1.0
max25.0

Morphological opening labels#

Similar to morphological opening on binary images, we can also modify this label image. Note: this operation introduces gaps between labels if the radius is large neough.

opened_labels = cle.opening_labels(label_image, radius=5)
opened_labels
cle._ image
shape(256, 256)
dtypeuint32
size256.0 kB
min0.0
max25.0

Smoothing labels#

If these introduced gaps are not wanted, the alternative is to use this function:

smoothed_labels = cle.smooth_labels(label_image, radius = 5)
smoothed_labels
cle._ image
shape(256, 256)
dtypeuint32
size256.0 kB
min1.0
max25.0

To get a better understanding of what the algorithm does, it may make sense to tune the radius parameter interactively. This will not work in the github-rendering of this notebook, you need to run it in Jupyter lab and have stackview installed.

import stackview
stackview.interact(cle.smooth_labels, label_image, continuous_update=True)

Eroding and dilating labels#

Under the hood, the functions shown above use label erosion and dilation. These operations are defined analogously to binary erosion and dilation with the difference that labels cannot overwrite each other.

eroded_labels = cle.erode_labels(label_image, radius=5)
eroded_labels
cle._ image
shape(256, 256)
dtypeuint32
size256.0 kB
min0.0
max25.0
dilated_eroded_labels = cle.dilate_labels(eroded_labels, radius=5)
dilated_eroded_labels
cle._ image
shape(256, 256)
dtypeuint32
size256.0 kB
min0.0
max25.0

Exercise#

Use labeling post-processing operations to modify this labeling result. Goal: Make small objects disappear while all other objects more or less keep their size and shape:

blobs_labels = cle.asarray(imread("../../data/blobs_labels.tif")).astype(np.uint32)
blobs_labels
cle._ image
shape(254, 256)
dtypeuint32
size254.0 kB
min0.0
max64.0