Preventing leaking labels#

A common problem when segmenting cells in images with membrane staining is leaking labels. When using algorithms such as the seeded watershed these leakes can be prevented by filtering the image, e.g. using a local maximum filter.

import napari_segment_blobs_and_things_with_membranes as nsbatwm
from skimage.data import cells3d
import stackview
import pyclesperanto_prototype as cle
import matplotlib.pyplot as plt

For demonstration purposes we use the cells3d example image from scikit-image.

image = cells3d()[:,0]
image.shape
(60, 256, 256)

We look at a slice of it in a Z-Y. For code-simplicity we leave out the plot axis labels after this figure.

cle.imshow(image[:,:,128], max_display_intensity=20000, continue_drawing=True)
plt.xlabel("Y")
plt.ylabel("Z")
Text(0, 0.5, 'Z')
../_images/5fa45f5ed25d6df1d1d1e5eca0e881b1d47ca58bbe1cca0c5add0ba00cfe573f.png

When applying the seeded-watershed algorithm to this dataset (in 3D), we can see that some labels leak in Z. They merge with the region outside the tissue layer.

reference_labels = nsbatwm.local_minima_seeded_watershed(image, spot_sigma=9)

cle.imshow(reference_labels[:,:,128], labels=True)
../_images/f6048e2e232798c17a508da020dd352d4bc6c7b3785fb2a528f5f348534b9479.png

The problem can be reduced by applying a maximum-filter to the raw image. It will lead to thicker membranes, and thus to a lower chance that the watershed algorithm can leak through holes in the membrane.

thicker_membranes = nsbatwm.maximum_filter(image, radius=2)

cle.imshow(thicker_membranes[:,:,128], max_display_intensity=20000)
../_images/350917ec65b360445b829ffa2025ab5b612030518b175a660309156e1218c0d6.png

The resulting label image has less leaking labels, but also lost accuracy of the label borders in all directions.

labels1 = nsbatwm.local_minima_seeded_watershed(thicker_membranes, spot_sigma=9)

cle.imshow(labels1[:,:,128], labels=True)
../_images/37f206a6b54e091a596eec8ea4dfe63181e0ae2526100a4a2271d53b901bde9b.png

The leaks often appear to happen in the Z-direction only which is an effect of the point-spread-function of common microscopy techniques. It is typically anisotropic and thus, the microscope cannot capture the membrans in Z as good as in X and Y.

To deal with this leaking-labels issue in X and Y only and save some of the accuracy in Z, we need to apply a maximum filter where we can specify different radii in X,Y and Z.

thinker_membranes_in_x_y = cle.maximum_sphere(image, radius_x=2, radius_y=2, radius_z=0)

cle.imshow(thinker_membranes_in_x_y[:,:,128], max_display_intensity=20000)
../_images/fbb9a54a49579cffa51f659276b4c70ee612eaac0b78c38ae138127c87e25226.png
labels2 = nsbatwm.local_minima_seeded_watershed(thinker_membranes_in_x_y, spot_sigma=9)

cle.imshow(labels2[:,:,128], labels=True)
../_images/18b2d6c94b8606c09c4827620fb1eb9d050a74b02dc569d5475a4e844feeef5d.png

Excluding labels on image edges in Z#

Images of single tissue layers are commonly acquired in a way that we see some pixels and later segmented labels out of the tissue top and bottom (in Z). We can remove those labels while keeping those which touch the image border in X and Y explicitly.

corrected_labels = cle.exclude_labels_on_edges(labels2, 
                                               exclude_in_x=False, 
                                               exclude_in_y=False, 
                                               exclude_in_z=True)

cle.imshow(corrected_labels[:,:,128], labels=True)
../_images/49246fbac963a5fa880bde0c3bbc0426bf6b7e1673588e7c8adf41a3fc4d9951.png

Obviously, we still loose one cell that was leaking in the area below the tissue. It might be impossible to retrieve a picture-perfect result though.