0
# Segmentation Algorithms
1
2
Advanced segmentation methods for extracting anatomical structures, regions of interest, and meaningful objects from medical and scientific images. ITK provides comprehensive segmentation tools including level sets, region growing, clustering, watershed algorithms, and active contour methods with both modern functional interfaces and traditional implementations.
3
4
## Capabilities
5
6
### Region Growing Methods
7
8
Seed-driven segmentation algorithms that grow regions based on homogeneity criteria.
9
10
```python { .api }
11
# Connected threshold segmentation
12
def connected_threshold_image_filter(input_image, seed_points: Sequence,
13
lower: float, upper: float,
14
replace_value: float = 255) -> Image:
15
"""
16
Segment connected regions with pixel values within specified thresholds.
17
18
Parameters:
19
- input_image: Input grayscale image
20
- seed_points: List of seed point coordinates [(x,y), (x,y,z), ...]
21
- lower: Lower threshold for region growing
22
- upper: Upper threshold for region growing
23
- replace_value: Value assigned to segmented pixels
24
25
Returns:
26
- Binary segmentation mask
27
"""
28
29
# Confidence connected segmentation
30
def confidence_connected_image_filter(input_image, seed_points: Sequence,
31
multiplier: float = 2.5,
32
iterations: int = 5,
33
initial_neighborhood_radius: int = 1,
34
replace_value: float = 255) -> Image:
35
"""
36
Segment regions using confidence-based connectivity with automatic threshold estimation.
37
38
Parameters:
39
- input_image: Input grayscale image
40
- seed_points: List of seed point coordinates
41
- multiplier: Confidence interval multiplier for threshold estimation
42
- iterations: Number of iterations for threshold refinement
43
- initial_neighborhood_radius: Radius for initial statistics computation
44
- replace_value: Value assigned to segmented pixels
45
46
Returns:
47
- Binary segmentation mask with automatically determined thresholds
48
"""
49
50
# Neighborhood connected segmentation
51
def neighborhood_connected_image_filter(input_image, seed_points: Sequence,
52
lower: float, upper: float,
53
radius: Sequence[int]) -> Image: ...
54
55
# Vector connected threshold (for multi-channel images)
56
def vector_connected_threshold_image_filter(input_image, seed_points: Sequence,
57
lower: Sequence[float],
58
upper: Sequence[float]) -> Image: ...
59
```
60
61
### Watershed Segmentation
62
63
Morphological watershed algorithms for segmenting touching objects and complex shapes.
64
65
```python { .api }
66
# Basic watershed segmentation
67
def watershed_image_filter(input_image, threshold: float = 0.01,
68
level: float = 0.3, fully_connected: bool = False) -> Image:
69
"""
70
Perform watershed segmentation using morphological approach.
71
72
Parameters:
73
- input_image: Input grayscale or gradient magnitude image
74
- threshold: Threshold for eliminating spurious minima
75
- level: Water level for flooding simulation
76
- fully_connected: Use 26-connectivity (3D) or 8-connectivity (2D)
77
78
Returns:
79
- Label image with watershed segments
80
"""
81
82
# Morphological watershed with markers
83
def morphological_watershed_image_filter(input_image, marker_image=None,
84
mark_watershed_line: bool = True,
85
fully_connected: bool = False) -> Image: ...
86
87
# Watershed from markers
88
def watershed_from_markers_image_filter(input_image, marker_image,
89
connectivity_type: str = 'face') -> Image: ...
90
```
91
92
### Level Set Methods
93
94
PDE-based active contour methods for precise boundary extraction and shape evolution.
95
96
```python { .api }
97
# Geodesic active contours
98
def geodesic_active_contour_level_set_image_filter(input_image, feature_image,
99
initial_level_set,
100
propagation_scaling: float = 1.0,
101
curvature_scaling: float = 1.0,
102
advection_scaling: float = 1.0,
103
max_rms_error: float = 0.02,
104
number_of_iterations: int = 100) -> Image:
105
"""
106
Segment objects using geodesic active contours with level set evolution.
107
108
Parameters:
109
- input_image: Input grayscale image
110
- feature_image: Edge/feature map (typically gradient magnitude)
111
- initial_level_set: Initial contour as signed distance map
112
- propagation_scaling: Weight for balloon/expansion force
113
- curvature_scaling: Weight for curvature-based smoothing
114
- advection_scaling: Weight for edge-based attraction force
115
- max_rms_error: Convergence criterion
116
- number_of_iterations: Maximum number of iterations
117
118
Returns:
119
- Final level set segmentation as signed distance map
120
"""
121
122
# Shape detection level sets
123
def shape_detection_level_set_image_filter(input_image, feature_image,
124
initial_level_set,
125
propagation_scaling: float = 1.0,
126
curvature_scaling: float = 1.0) -> Image: ...
127
128
# Chan and Vese level sets (region-based)
129
def chan_and_vese_dense_level_set_image_filter(input_image,
130
max_rms_error: float = 0.02,
131
number_of_iterations: int = 100,
132
lambda1: float = 1.0,
133
lambda2: float = 1.0,
134
mu: float = 0.25,
135
nu: float = 0.0,
136
epsilon: float = 1.0) -> Image: ...
137
138
# Fast marching for level set initialization
139
def fast_marching_image_filter(input_image, trial_points: Sequence,
140
stopping_value: float = 100.0) -> Image: ...
141
```
142
143
### Clustering-Based Segmentation
144
145
Statistical approaches using pixel similarity and clustering algorithms.
146
147
```python { .api }
148
# K-means clustering
149
def scalar_image_kmeans_image_filter(input_image, number_of_classes: int,
150
use_non_contiguous_labels: bool = False) -> Image:
151
"""
152
Segment image using K-means clustering of pixel intensities.
153
154
Parameters:
155
- input_image: Input grayscale image
156
- number_of_classes: Number of clusters/segments
157
- use_non_contiguous_labels: Allow non-contiguous cluster labels
158
159
Returns:
160
- Label image with K-means clusters
161
"""
162
163
# Vector image K-means (for multi-channel images)
164
def vector_image_kmeans_image_filter(input_image, number_of_classes: int) -> Image: ...
165
166
# Expectation-maximization segmentation
167
def bayesian_classifier_image_filter(input_image, membership_functions,
168
decision_rule: str = 'minimum_error') -> Image: ...
169
```
170
171
### Morphological Segmentation
172
173
Shape-based segmentation using mathematical morphology operations.
174
175
```python { .api }
176
# H-maxima segmentation (eliminate local maxima)
177
def h_maxima_image_filter(input_image, height: float,
178
fully_connected: bool = False) -> Image: ...
179
180
# H-minima segmentation (eliminate local minima)
181
def h_minima_image_filter(input_image, height: float,
182
fully_connected: bool = False) -> Image: ...
183
184
# Regional maxima/minima
185
def regional_maxima_image_filter(input_image, fully_connected: bool = False) -> Image: ...
186
def regional_minima_image_filter(input_image, fully_connected: bool = False) -> Image: ...
187
188
# Morphological opening/closing by attribute
189
def attribute_opening_image_filter(input_image, attribute_type: str = 'area',
190
threshold: float = 100.0) -> Image: ...
191
def attribute_closing_image_filter(input_image, attribute_type: str = 'area',
192
threshold: float = 100.0) -> Image: ...
193
```
194
195
### Traditional Object-Oriented Interface
196
197
Classical ITK segmentation filters for advanced parameter control.
198
199
```python { .api }
200
class ConnectedThresholdImageFilter[TInputImage, TOutputImage]:
201
"""Connected component segmentation with threshold criteria."""
202
def SetSeed(self, seed: Index) -> None: ...
203
def AddSeed(self, seed: Index) -> None: ...
204
def ClearSeeds(self) -> None: ...
205
def SetLower(self, threshold: PixelType) -> None: ...
206
def SetUpper(self, threshold: PixelType) -> None: ...
207
def SetReplaceValue(self, value: OutputPixelType) -> None: ...
208
def GetLower(self) -> PixelType: ...
209
def GetUpper(self) -> PixelType: ...
210
211
class GeodesicActiveContourLevelSetImageFilter[TInputImage, TFeatureImage, TOutputImage]:
212
"""Geodesic active contour level set segmentation."""
213
def SetFeatureImage(self, image: TFeatureImage) -> None: ...
214
def SetAdvectionScaling(self, scaling: ScalarValueType) -> None: ...
215
def SetCurvatureScaling(self, scaling: ScalarValueType) -> None: ...
216
def SetPropagationScaling(self, scaling: ScalarValueType) -> None: ...
217
def SetMaximumRMSError(self, error: ScalarValueType) -> None: ...
218
def SetNumberOfIterations(self, iterations: int) -> None: ...
219
def GetRMSChange(self) -> ScalarValueType: ...
220
def GetElapsedIterations(self) -> int: ...
221
222
class WatershedImageFilter[TInputImage]:
223
"""Watershed segmentation with morphological approach."""
224
def SetThreshold(self, threshold: double) -> None: ...
225
def SetLevel(self, level: double) -> None: ...
226
def SetFullyConnected(self, connected: bool) -> None: ...
227
def SetMarkWatershedLine(self, mark: bool) -> None: ...
228
def GetThreshold(self) -> double: ...
229
def GetLevel(self) -> double: ...
230
231
class FastMarchingImageFilter[TLevelSet, TSpeedImage]:
232
"""Fast marching method for level set initialization."""
233
def SetTrialPoints(self, points: NodeContainer) -> None: ...
234
def SetSpeedImage(self, image: TSpeedImage) -> None: ...
235
def SetStoppingValue(self, value: double) -> None: ...
236
def SetNormalizationFactor(self, factor: double) -> None: ...
237
def GetLargestPossibleRegion(self) -> RegionType: ...
238
```
239
240
## Usage Examples
241
242
### Basic Region Growing Segmentation
243
244
```python
245
import itk
246
import numpy as np
247
248
# Load medical image
249
image = itk.imread('brain_mri.nii.gz')
250
251
# Define seed points (can be interactive or automatic)
252
seed_points = [(120, 150, 80), (130, 155, 85)] # Example coordinates
253
254
# Perform connected threshold segmentation
255
segmentation = itk.connected_threshold_image_filter(
256
image,
257
seed_points=seed_points,
258
lower=100,
259
upper=200,
260
replace_value=255
261
)
262
263
# Save segmentation result
264
itk.imwrite(segmentation, 'brain_segmentation.nii.gz')
265
266
# Optionally, create overlay for visualization
267
overlay = itk.label_overlay_image_filter(image, segmentation, opacity=0.5)
268
itk.imwrite(overlay, 'brain_overlay.nii.gz')
269
```
270
271
### Watershed Segmentation for Cell Counting
272
273
```python
274
import itk
275
276
def segment_cells(image, min_distance=10, threshold_factor=0.1):
277
"""Segment individual cells using watershed algorithm."""
278
279
# Preprocessing: smooth and enhance contrast
280
smoothed = itk.gaussian_blur_image_filter(image, variance=1.0)
281
282
# Compute gradient magnitude for watershed
283
gradient = itk.gradient_magnitude_image_filter(smoothed)
284
285
# Find local maxima as seed points (cell centers)
286
h_maxima = itk.h_maxima_image_filter(smoothed, height=threshold_factor * 255)
287
288
# Apply watershed segmentation
289
watershed = itk.watershed_image_filter(
290
gradient,
291
threshold=0.01,
292
level=0.3,
293
fully_connected=False
294
)
295
296
return watershed
297
298
# Usage
299
cell_image = itk.imread('cells.tif')
300
cell_segments = segment_cells(cell_image)
301
itk.imwrite(cell_segments, 'cell_segments.tif')
302
303
# Count number of cells
304
array = itk.array_from_image(cell_segments)
305
num_cells = np.max(array)
306
print(f"Detected {num_cells} cells")
307
```
308
309
### Level Set Segmentation Pipeline
310
311
```python
312
import itk
313
314
def level_set_segmentation(image, seed_points, iterations=100):
315
"""Complete level set segmentation pipeline."""
316
317
# Step 1: Create feature image (edge map)
318
smoothed = itk.gaussian_blur_image_filter(image, variance=1.0)
319
gradient = itk.gradient_magnitude_image_filter(smoothed)
320
321
# Sigmoid transformation to create feature map
322
sigmoid = itk.sigmoid_image_filter(
323
gradient,
324
output_minimum=0.0,
325
output_maximum=1.0,
326
alpha=-1.0, # Negative alpha inverts gradient
327
beta=50.0 # Beta controls transition steepness
328
)
329
330
# Step 2: Initialize level set using fast marching
331
# Convert seed points to proper format
332
trial_points = []
333
for point in seed_points:
334
trial_point = itk.LevelSetNode[itk.F, 3]()
335
trial_point.SetIndex(point)
336
trial_point.SetValue(0.0)
337
trial_points.append(trial_point)
338
339
fast_marching = itk.FastMarchingImageFilter[itk.Image[itk.F, 3], itk.Image[itk.F, 3]].New()
340
fast_marching.SetInput(sigmoid)
341
fast_marching.SetTrialPoints(trial_points)
342
fast_marching.SetStoppingValue(50.0)
343
fast_marching.Update()
344
345
initial_level_set = fast_marching.GetOutput()
346
347
# Step 3: Apply geodesic active contour
348
segmentation = itk.geodesic_active_contour_level_set_image_filter(
349
input_image=image,
350
feature_image=sigmoid,
351
initial_level_set=initial_level_set,
352
propagation_scaling=2.0,
353
curvature_scaling=1.0,
354
advection_scaling=1.0,
355
max_rms_error=0.02,
356
number_of_iterations=iterations
357
)
358
359
# Step 4: Threshold level set to get binary mask
360
binary_mask = itk.binary_threshold_image_filter(
361
segmentation,
362
lower_threshold=-1000.0,
363
upper_threshold=0.0,
364
inside_value=255,
365
outside_value=0
366
)
367
368
return binary_mask, segmentation
369
370
# Usage
371
vessel_image = itk.imread('vessels.nii.gz')
372
seed_points = [(100, 120, 50)] # Starting point inside vessel
373
374
binary_result, level_set = level_set_segmentation(vessel_image, seed_points)
375
376
itk.imwrite(binary_result, 'vessel_segmentation.nii.gz')
377
itk.imwrite(level_set, 'level_set_evolution.nii.gz')
378
```
379
380
### Multi-Class K-means Segmentation
381
382
```python
383
import itk
384
import numpy as np
385
386
def tissue_segmentation_kmeans(image, num_tissues=4):
387
"""Segment brain tissues using K-means clustering."""
388
389
# Preprocessing: bias field correction and normalization
390
bias_corrected = itk.n4_bias_field_correction_image_filter(image)
391
392
# Normalize intensity range
393
normalized = itk.rescale_intensity_image_filter(
394
bias_corrected,
395
output_minimum=0,
396
output_maximum=255
397
)
398
399
# Apply K-means segmentation
400
kmeans = itk.scalar_image_kmeans_image_filter(
401
normalized,
402
number_of_classes=num_tissues,
403
use_non_contiguous_labels=False
404
)
405
406
return kmeans
407
408
def post_process_segmentation(segmentation, min_size=100):
409
"""Clean up segmentation by removing small components."""
410
411
# Label connected components
412
connected = itk.connected_component_image_filter(segmentation)
413
414
# Remove small components
415
cleaned = itk.label_size_opening_image_filter(
416
connected,
417
lambda_threshold=min_size
418
)
419
420
# Relabel components sequentially
421
relabeled = itk.relabel_component_image_filter(cleaned)
422
423
return relabeled
424
425
# Usage
426
brain_image = itk.imread('brain_t1.nii.gz')
427
428
# Segment into tissues (background, CSF, gray matter, white matter)
429
tissue_labels = tissue_segmentation_kmeans(brain_image, num_tissues=4)
430
431
# Clean up segmentation
432
cleaned_labels = post_process_segmentation(tissue_labels, min_size=50)
433
434
# Save results
435
itk.imwrite(cleaned_labels, 'brain_tissues.nii.gz')
436
437
# Create color overlay
438
overlay = itk.label_to_rgb_image_filter(cleaned_labels)
439
itk.imwrite(overlay, 'brain_tissues_color.nii.gz')
440
441
# Extract individual tissue masks
442
array = itk.array_from_image(cleaned_labels)
443
for tissue_id in range(1, 5): # Assuming 4 tissue types
444
mask = (array == tissue_id).astype(np.uint8) * 255
445
mask_image = itk.image_from_array(mask, is_vector=False)
446
mask_image.CopyInformation(brain_image)
447
itk.imwrite(mask_image, f'tissue_{tissue_id}.nii.gz')
448
```
449
450
### Interactive Segmentation Workflow
451
452
```python
453
import itk
454
455
class InteractiveSegmentation:
456
"""Interactive segmentation using multiple methods."""
457
458
def __init__(self, image):
459
self.image = image
460
self.seeds = []
461
self.current_segmentation = None
462
463
def add_seed(self, point):
464
"""Add seed point for region growing."""
465
self.seeds.append(point)
466
467
def confidence_connected_segment(self, multiplier=2.5):
468
"""Segment using confidence connected filter."""
469
if not self.seeds:
470
raise ValueError("No seed points defined")
471
472
self.current_segmentation = itk.confidence_connected_image_filter(
473
self.image,
474
seed_points=self.seeds,
475
multiplier=multiplier,
476
iterations=5
477
)
478
return self.current_segmentation
479
480
def refine_with_morphology(self, operation='opening', radius=2):
481
"""Refine segmentation with morphological operations."""
482
if self.current_segmentation is None:
483
raise ValueError("No segmentation to refine")
484
485
if operation == 'opening':
486
refined = itk.binary_opening_image_filter(
487
self.current_segmentation,
488
kernel_radius=radius
489
)
490
elif operation == 'closing':
491
refined = itk.binary_closing_image_filter(
492
self.current_segmentation,
493
kernel_radius=radius
494
)
495
elif operation == 'erosion':
496
refined = itk.binary_erode_image_filter(
497
self.current_segmentation,
498
kernel_radius=radius
499
)
500
elif operation == 'dilation':
501
refined = itk.binary_dilate_image_filter(
502
self.current_segmentation,
503
kernel_radius=radius
504
)
505
506
self.current_segmentation = refined
507
return refined
508
509
def get_segmentation_statistics(self):
510
"""Compute statistics about current segmentation."""
511
if self.current_segmentation is None:
512
return None
513
514
# Convert to arrays for analysis
515
image_array = itk.array_from_image(self.image)
516
mask_array = itk.array_from_image(self.current_segmentation)
517
518
# Extract segmented pixels
519
segmented_pixels = image_array[mask_array > 0]
520
521
stats = {
522
'volume_pixels': np.sum(mask_array > 0),
523
'mean_intensity': np.mean(segmented_pixels),
524
'std_intensity': np.std(segmented_pixels),
525
'min_intensity': np.min(segmented_pixels),
526
'max_intensity': np.max(segmented_pixels)
527
}
528
529
return stats
530
531
# Usage example
532
# tumor_image = itk.imread('tumor.nii.gz')
533
# segmenter = InteractiveSegmentation(tumor_image)
534
# segmenter.add_seed((150, 200, 100)) # Add seed in tumor center
535
# initial_seg = segmenter.confidence_connected_segment(multiplier=3.0)
536
# refined_seg = segmenter.refine_with_morphology('closing', radius=3)
537
# stats = segmenter.get_segmentation_statistics()
538
# print(f"Tumor volume: {stats['volume_pixels']} pixels")
539
```