This notebook may contain text, code and images generated by artificial intelligence. Used model: claude-sonnet-4-6, vision model: claude-sonnet-4-6, fast_model: None, endpoint: None, bia-bob version: 0.35.0.. It is good scientific practice to check the code and results it produces carefully.
Read more about code generation using bia-bob
Cell Segmentation Using the Watershed Algorithm
In this notebook, we will segment cells from a 2D membrane image using the watershed algorithm. The watershed algorithm treats the image as a topographic map and floods it from local minima, creating segmentation boundaries where the flooding from different sources meets.
Step 1: Load the Image
We load the 2D membrane image from disk and inspect it.
|
| shape | (256, 256) |
| dtype | uint16 |
| size | 128.0 kB |
| min | 277 | | max | 44092 |
|
Step 2: Top-Hat Background Removal
We apply a white top-hat filter using skimage.morphology.white_tophat with a disk-shaped structuring element of radius 15. This replaces the pyclesperanto cle.top_hat call and removes uneven background illumination by subtracting the morphological opening from the original image, enhancing bright membrane structures.
|
| shape | (256, 256) |
| dtype | uint16 |
| size | 128.0 kB |
| min | 0 | | max | 42398 |
|
Step 3: Preprocess the Image
We apply a Gaussian blur to reduce noise in the background-corrected membrane image. This helps improve the quality of subsequent thresholding and distance transform steps.
|
| shape | (256, 256) |
| dtype | float64 |
| size | 512.0 kB |
| min | 97.52161880577154 | | max | 10807.295376916061 |
|
Step 4: Threshold the Image to Create a Binary Mask
We threshold to separate cell interiors from membranes. Since membranes appear bright, the cell interiors will be the dark regions (below the threshold). We invert the binary image so that cell interiors are True.
C:\structure\code\embl-bia-2026\.venv\Lib\site-packages\stackview\_static_view.py:107: RuntimeWarning: Converting input from bool to <class 'numpy.uint8'> for compatibility.
h, _ = np.histogram(self, bins=num_bins)
|
| shape | (256, 256) |
| dtype | bool |
| size | 64.0 kB |
| min | False | | max | True |
|
Step 6: Detect Local Maxima as Seed Points (Markers)
We find local maxima in the distance map. These correspond to the centers of the cells and will serve as seed points (markers) for the watershed algorithm.
Number of detected seed points (cells): 27
|
| shape | (256, 256) |
| dtype | int32 |
| size | 256.0 kB |
| min | 0 | | max | 27 | | n labels | 27 |
|
Step 7: Apply the Watershed Algorithm
We apply the watershed algorithm on the inverted distance map (so that peaks become valleys), using the detected markers as seeds and the binary mask to constrain segmentation to cell regions.
Number of segmented cells: 27
|
| shape | (256, 256) |
| dtype | int32 |
| size | 256.0 kB |
| min | 1 | | max | 27 | | n labels | 27 |
|
Step 8: Visualize the Result with stackview.animate_curtain
We use stackview.animate_curtain to display the original membrane image alongside the segmentation label image. This animated curtain view allows us to interactively compare the raw image with the segmented cells.
Exercise
Modify the threshold and the Gaussian blur sigma to improve the segmentation result.