SimpleITK is a simplified interface to the Insight Toolkit (ITK) for image registration and segmentation
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Filters for working with labeled images where pixel values represent object identities. Includes label statistics, shape analysis, label manipulation, and conversions between label representations.
class LabelShapeStatisticsImageFilter:
"""Compute shape statistics for each label."""
def Execute(self, labelImage):
"""
Compute shape statistics.
Args:
labelImage: Labeled image
"""
def GetNumberOfLabels(self) -> int:
"""Get number of labels."""
def GetLabels(self) -> tuple[int, ...]:
"""Get all label values."""
def GetNumberOfPixels(self, label: int) -> int:
"""Get pixel count for label."""
def GetPhysicalSize(self, label: int) -> float:
"""Get physical size (volume) for label."""
def GetBoundingBox(self, label: int) -> tuple[int, ...]:
"""
Get bounding box for label.
Returns:
Bounding box [x, y, z, width, height, depth]
"""
def GetCentroid(self, label: int) -> tuple[float, ...]:
"""Get centroid in physical space."""
def GetElongation(self, label: int) -> float:
"""Get elongation measure."""
def GetFlatness(self, label: int) -> float:
"""Get flatness measure (3D only)."""
def GetRoundness(self, label: int) -> float:
"""Get roundness measure."""
def GetPerimeter(self, label: int) -> float:
"""Get perimeter (2D) or surface area (3D)."""
def LabelShapeStatistics(labelImage):
"""Procedural: compute shape statistics (returns filter for access)."""
class LabelIntensityStatisticsImageFilter:
"""Compute intensity statistics per label."""
def Execute(self, intensityImage, labelImage):
"""
Compute statistics.
Args:
intensityImage: Intensity image
labelImage: Label image
"""
def GetNumberOfLabels(self) -> int:
"""Get number of labels."""
def GetLabels(self) -> tuple[int, ...]:
"""Get all labels."""
def GetMean(self, label: int) -> float:
"""Get mean intensity for label."""
def GetMedian(self, label: int) -> float:
"""Get median intensity."""
def GetStandardDeviation(self, label: int) -> float:
"""Get standard deviation."""
def GetMinimum(self, label: int) -> float:
"""Get minimum intensity."""
def GetMaximum(self, label: int) -> float:
"""Get maximum intensity."""
def GetVariance(self, label: int) -> float:
"""Get variance."""
def GetSum(self, label: int) -> float:
"""Get sum of intensities."""
def GetNumberOfPixels(self, label: int) -> int:
"""Get pixel count."""
def GetCenterOfGravity(self, label: int) -> tuple[float, ...]:
"""Get center of gravity."""
class LabelOverlapMeasuresImageFilter:
"""Compute overlap measures between two label images."""
def Execute(self, sourceImage, targetImage):
"""
Compute overlap measures.
Args:
sourceImage: First label image
targetImage: Second label image
"""
def GetJaccardCoefficient(self, label: int = -1) -> float:
"""
Get Jaccard coefficient (intersection over union).
Args:
label: Specific label, or -1 for overall
Returns:
Jaccard coefficient
"""
def GetDiceCoefficient(self, label: int = -1) -> float:
"""Get Dice coefficient (2*intersection / sum of sizes)."""
def GetVolumeSimilarity(self, label: int = -1) -> float:
"""Get volume similarity."""
def GetFalseNegativeError(self, label: int = -1) -> float:
"""Get false negative error."""
def GetFalsePositiveError(self, label: int = -1) -> float:
"""Get false positive error."""
def GetLabels(self) -> tuple[int, ...]:
"""Get all labels."""class ChangeLabelImageFilter:
"""Change specific label values."""
def SetChangeMap(self, changeMap: dict) -> None:
"""
Set label change mapping.
Args:
changeMap: Dictionary mapping old to new labels {old: new}
"""
def Execute(self, labelImage):
"""Returns: image with changed labels"""
def ChangeLabel(labelImage, changeMap: dict):
"""Procedural: change labels."""
class RelabelComponentImageFilter:
"""Relabel components by size (largest = 1)."""
def SetMinimumObjectSize(self, size: int) -> None:
"""Set minimum size to keep."""
def SetSortByObjectSize(self, sort: bool) -> None:
"""Sort by size."""
def Execute(self, labelImage):
"""Returns: relabeled image"""
def GetNumberOfObjects(self) -> int:
"""Get number of objects."""
def GetSizeOfObjectsInPixels(self) -> tuple[int, ...]:
"""Get size of each object."""
def RelabelComponent(labelImage, minimumObjectSize: int = 0,
sortByObjectSize: bool = True):
"""Procedural: relabel by size."""class LabelContourImageFilter:
"""Extract label contours (boundaries)."""
def SetFullyConnected(self, fullyConnected: bool) -> None:
"""Use full connectivity."""
def SetBackgroundValue(self, value: float) -> None:
"""Set background value."""
def Execute(self, labelImage):
"""
Extract contours.
Returns:
Label image with only boundaries
"""
def LabelContour(labelImage, fullyConnected: bool = False, backgroundValue: float = 0):
"""Procedural: extract label contours."""class LabelSetDilateImageFilter:
"""Dilate label set (expand each label)."""
def SetKernelRadius(self, radius: int | tuple[int, ...]) -> None:
"""Set dilation radius."""
def SetKernelType(self, kernelType: int) -> None:
"""Set kernel shape."""
def Execute(self, labelImage):
"""Returns: dilated label image"""
class LabelSetErodeImageFilter:
"""Erode label set (shrink each label)."""
def SetKernelRadius(self, radius: int | tuple[int, ...]) -> None:
"""Set erosion radius."""
def SetKernelType(self, kernelType: int) -> None:
"""Set kernel shape."""
def Execute(self, labelImage):
"""Returns: eroded label image"""class BinaryImageToLabelMapFilter:
"""Convert binary image to label map representation."""
def SetInputForegroundValue(self, value: float) -> None:
"""Set foreground value in input."""
def SetOutputBackgroundValue(self, value: float) -> None:
"""Set background value in output."""
def SetFullyConnected(self, fullyConnected: bool) -> None:
"""Use full connectivity for component labeling."""
def Execute(self, binaryImage):
"""Returns: label map"""
class LabelImageToLabelMapFilter:
"""Convert label image to label map representation."""
def SetBackgroundValue(self, value: float) -> None:
"""Set background value."""
def Execute(self, labelImage):
"""Returns: label map"""
class LabelMapToLabelImageFilter:
"""Convert label map to label image."""
def Execute(self, labelMap):
"""Returns: label image"""
class LabelMapToBinaryImageFilter:
"""Convert label map to binary image."""
def SetBackgroundValue(self, value: float) -> None:
"""Set background value."""
def SetForegroundValue(self, value: float) -> None:
"""Set foreground value."""
def Execute(self, labelMap):
"""Returns: binary image"""class AggregateLabelMapFilter:
"""Aggregate overlapping labels in label map."""
def Execute(self, labelMap):
"""Returns: aggregated label map"""
class MergeLabelMapFilter:
"""Merge two label maps."""
def Execute(self, labelMap1, labelMap2):
"""Returns: merged label map"""
class RelabelLabelMapFilter:
"""Relabel label map objects."""
def SetSortBySize(self, sort: bool) -> None:
"""Sort by object size."""
def Execute(self, labelMap):
"""Returns: relabeled label map"""import SimpleITK as sitk
# Label connected components
labeled = sitk.ConnectedComponent(binary_image)
# Compute shape statistics
shape_stats = sitk.LabelShapeStatisticsImageFilter()
shape_stats.Execute(labeled)
# Analyze each object
for label in shape_stats.GetLabels():
size = shape_stats.GetNumberOfPixels(label)
centroid = shape_stats.GetCentroid(label)
bbox = shape_stats.GetBoundingBox(label)
roundness = shape_stats.GetRoundness(label)
print(f"Label {label}: size={size}, centroid={centroid}, roundness={roundness:.3f}")import SimpleITK as sitk
# Label components
labeled = sitk.ConnectedComponent(binary_image)
# Get shape statistics
shape_stats = sitk.LabelShapeStatisticsImageFilter()
shape_stats.Execute(labeled)
# Filter by size and roundness
keep_labels = []
for label in shape_stats.GetLabels():
size = shape_stats.GetNumberOfPixels(label)
roundness = shape_stats.GetRoundness(label)
if size > 100 and roundness > 0.7:
keep_labels.append(label)
# Create change map (keep selected, remove others)
change_map = {label: 0 for label in shape_stats.GetLabels()}
for i, label in enumerate(keep_labels, start=1):
change_map[label] = i
filtered = sitk.ChangeLabel(labeled, change_map)import SimpleITK as sitk
# Compare two segmentations
overlap = sitk.LabelOverlapMeasuresImageFilter()
overlap.Execute(segmentation1, segmentation2)
dice = overlap.GetDiceCoefficient()
jaccard = overlap.GetJaccardCoefficient()
print(f"Dice coefficient: {dice:.3f}")
print(f"Jaccard coefficient: {jaccard:.3f}")import SimpleITK as sitk
# Compute intensity statistics per label
intensity_stats = sitk.LabelIntensityStatisticsImageFilter()
intensity_stats.Execute(image, labeled_regions)
for label in intensity_stats.GetLabels():
mean = intensity_stats.GetMean(label)
std = intensity_stats.GetStandardDeviation(label)
median = intensity_stats.GetMedian(label)
print(f"Region {label}: mean={mean:.2f}, std={std:.2f}, median={median:.2f}")Install with Tessl CLI
npx tessl i tessl/pypi-simpleitk