Written and maintained by CASRAI Editorial Board
Last updated
Image segmentation is the process of dividing an image into regions, each assigned a label, so that pixels (or voxels) belonging to the same object, tissue or structure can be measured together. This guide is for researchers who need to pick a segmentation method, run one reproducibly in Python or an interactive tool, and check the result with an overlap score. It was checked against the scikit-image and 3D Slicer documentation on 2026-11-07.
What image segmentation is used for in research
Segmentation turns an image into measurable objects. The output is a label image: an array the same shape as the input in which each pixel holds an integer identifying the region it belongs to. Once regions exist you can count them, measure their size and shape, or extract intensity values inside each one. In research this is the step between acquiring an image and reporting a number from it, for example counting nuclei in a microscopy field (see the Cellpose guide and CellProfiler guide), outlining a structure in a CT or MRI volume (see the 3D Slicer guide), or delineating tissue regions in a whole-slide image (see the QuPath guide). For the imaging context, see what is medical imaging.
There are two practical routes. Automatic or semi-automatic algorithms compute the labels from the pixel data, usually with a few parameters. Manual or assisted segmentation lets a person draw or grow regions on screen, which is the usual route for 3D scans.
Install or access
The examples below use scikit-image, an open-source Python library. Its installation page states that it needs Python 3.11 or newer and gives these commands (read 2026-11-07):
python -m pip install -U pippython -m pip install -U scikit-image
or, inside a conda environment:
conda install scikit-image
For interactive 3D work, 3D Slicer provides a Segment Editor module; it is distributed through the 3D Slicer project at slicer.org, and its documentation is at slicer.readthedocs.io.
Step by step: segment an image with scikit-image
This example uses SLIC superpixels, one of the algorithms demonstrated in the scikit-image segmentation gallery, with the parameter values used in that example.
- Load an image. The bundled sample image works for a first run:
from skimage import data, segmentation; img = data.astronaut() - Run the algorithm:
labels = segmentation.slic(img, n_segments=250, compactness=10, sigma=1, start_label=1) - Inspect the result:
print(labels.shape, labels.min(), labels.max()).labelsis the label image. - Draw the region boundaries over the original to check them by eye:
overlay = segmentation.mark_boundaries(img, labels) - Change one parameter at a time (for example
n_segmentsorcompactness) and compare the overlays before settling on values.
Which parameter controls what
| Function | Approach (per scikit-image gallery) | Example values | Parameter that shapes the result |
|---|---|---|---|
felzenszwalb |
Fast 2D graph-based segmentation | scale=100, sigma=0.5, min_size=50 | scale is the main parameter and affects segment size |
quickshift |
Mode-seeking over colour and location | kernel_size=3, max_dist=6, ratio=0.5 | max_dist selects the hierarchy level; ratio balances colour against image distance |
slic |
k-means clustering in colour and location | n_segments=250, compactness=10, sigma=1, start_label=1 | compactness balances colour similarity against proximity; the gallery notes it should be run in Lab colour space |
watershed |
Floods a grayscale gradient image from markers | markers=250, compactness=0.001 | compactness gives more regular regions |
The same module also provides random_walker (seeded, random-walk diffusion), chan_vese (level-set method for objects without clear edges), clear_border (removes labels touching the image border), find_boundaries (boolean boundary mask) and expand_labels.
Manual and assisted segmentation in 3D Slicer
The Segment Editor module specifies segments in 2D, 3D and 4D images and edits 3D voxel arrays; segments may overlap. Its documented effects are Threshold, Paint, Draw, Erase, Level Tracing, Grow from seeds, Fill between slices, Margin, Hollow, Smoothing, Scissors, Islands, Logical operators and Mask volume. Segment Editor does not edit labelmap volumes or models directly; conversion to a labelmap or model is done in the Import/Export section of the Segmentations module.
Output and how to read it
A label image assigns one integer per pixel. Conventionally one value marks background and each further integer marks one region, but check the function you used: with slic, the start_label argument sets the first label number. To judge quality, compare your segmentation with a reference mask (a manual annotation) using an overlap score.
- Dice coefficient = 2|A∩B| / (|A| + |B|), where A is the predicted region and B the reference.
- Intersection over Union (IoU, Jaccard index) = |A∩B| / |A∪B|.
- The two are related by Dice = 2 × IoU / (1 + IoU), so ranking methods by one ranks them the same way by the other. Report which you used.
Both range from 0 (no overlap) to 1 (identical masks). Worked example: if the predicted region has 100 pixels, the reference has 120, and 90 pixels are shared, then the union is 100 + 120 − 90 = 130, so IoU = 90/130 ≈ 0.69 and Dice = 180/220 ≈ 0.82, consistent with 2 × 0.69 / 1.69 ≈ 0.82.
Semantic segmentation labels every pixel by class; instance segmentation separates individual objects of the same class. Tools such as Cellpose are built for the instance case, which matters when you need per-cell counts.
Troubleshooting
- Regions are too many or too small. Lower
n_segments(SLIC) or raisescale(Felzenszwalb), the parameters the gallery identifies as controlling segment size. - Regions are ragged rather than compact. Raise
compactnessinslicorwatershed; the documentation describes it as the control for how regular regions are. - Watershed returns a poor result. Watershed floods from markers, so the number and placement of markers drive the outcome; revisit them before changing anything else.
- Objects cut by the image edge distort measurements. Use
clear_borderto drop labels that touch the border. - The object has no clear edge. Try
chan_vese, which the API describes as a level-set method for such objects.
Free alternatives
| Tool | Best matched to | Guide |
|---|---|---|
| scikit-image | Scripted 2D classical segmentation in Python | This page |
| 3D Slicer (Segment Editor) | Manual and assisted segmentation of 3D medical image volumes | 3D Slicer |
| Cellpose | Instance segmentation of cells | Cellpose |
| QuPath | Whole-slide image analysis | QuPath |
| CellProfiler | Pipeline-based microscopy image analysis | CellProfiler |
FAQ
What is image segmentation?
It is the division of an image into labelled regions so each object or structure can be measured separately. The result is a label image with one integer per pixel.
Which scikit-image function should I start with?
slic and felzenszwalb need no markers, so they are the simplest to run on a new image. watershed and random_walker need markers or seeds that you supply.
How do I measure whether a segmentation is good?
Compare it with a manual reference mask using Dice or IoU, as described above, and state which one you report.
Can I segment 3D scans with scikit-image?
The gallery example documented here is 2D. For 3D medical volumes, the Segment Editor in 3D Slicer is documented for 2D, 3D and 4D images.
Sources
- scikit-image, “Comparison of segmentation and superpixel algorithms”: https://scikit-image.org/docs/stable/auto_examples/segmentation/plot_segmentations.html (read 2026-11-07)
- scikit-image API,
skimage.segmentation: https://scikit-image.org/docs/stable/api/skimage.segmentation.html (read 2026-11-07) - scikit-image installation: https://scikit-image.org/docs/stable/user_guide/install.html (read 2026-11-07)
- 3D Slicer documentation, Segment Editor: https://slicer.readthedocs.io/en/latest/user_guide/modules/segmenteditor.html (read 2026-11-07)







