Splitting touching objects#

A common use-case for the watershed algorithm is splitting touching objects. In this notebook we will split objects in binary images that have a roundish shape and touch each other.

from skimage.io import imread
import napari_segment_blobs_and_things_with_membranes as nsbatwm
import napari_simpleitk_image_processing as nsitk
import stackview

Starting point for this is a binary image, e.g. made using thresholding.

nuclei = imread('../../data/mitosis_mod.tif')

stackview.insight(nuclei)
shape(70, 70)
dtypeuint8
size4.8 kB
min8
max255
binary = nsbatwm.threshold_otsu(nuclei).astype(bool)

binary
<__array_function__ internals>:180: RuntimeWarning: Converting input from bool to <class 'numpy.uint8'> for compatibility.
nsbatwm made image
shape(70, 70)
dtypebool
size4.8 kB
minFalse
maxTrue

We can then split the touching object by only taking the binary image into account. The underlying algorithm aims to produce similar results to ImageJ’s binary watershed algorithm and the implementation here also works in 3D.

split_objects = nsbatwm.split_touching_objects(binary)
split_objects
nsbatwm made image
shape(70, 70)
dtypebool
size4.8 kB
minFalse
maxTrue

The split_touching_objects function also has a parameter sigma that allows controlling how aggressive objects should be split. To make more splits, enter a smaller number than 3.5 which is the default.

split_objects2 = nsbatwm.split_touching_objects(binary, sigma=2)
split_objects2
nsbatwm made image
shape(70, 70)
dtypebool
size4.8 kB
minFalse
maxTrue

It is also possible to retrieve a label image as result. Note that in this case, the black line/gap between objects will not be present.

touching_labels = nsitk.touching_objects_labeling(binary)
touching_labels
n-sitk made image
shape(70, 70)
dtypeuint32
size19.1 kB
min0
max13