Morphology Features API
The IBSI reference manual defines these features in Morphological features. See Definitions.
pictologics.features.morphology
Morphology Feature Extraction Module
This module provides functions for calculating Morphological (Shape and Size) features from medical images. It implements the Image Biomarker Standardisation Initiative (IBSI) compliant algorithms.
Key Features:
- Voxel-based: Volume (voxel counting).
- Mesh-based: Surface Area, Volume (mesh), Compactness, Sphericity.
- PCA-based: Major/Minor/Least Axis Length, Elongation, Flatness.
- Convex Hull: Volume, Area, Max 3D Diameter.
- Bounding Box: Oriented (OMBB) and Axis-Aligned (AABB) Bounding Boxes.
- Minimum Volume Enclosing Ellipsoid (MVEE): Volume, Area.
- Intensity-Weighted: Center of Mass Shift, Integrated Intensity.
Optimization:
Uses numba kernels for the area and the volume of the marching cubes mesh (from its
corner cases, without the mesh), the moments, the exact convex hull and its candidates,
the oriented bounding box and the Khachiyan algorithm of the MVEE.
Example
Calculate morphology features from a mask:
import numpy as np
from pictologics.loader import Image
from pictologics.features.morphology import calculate_morphology_features
# Create dummy mask
mask_arr = np.zeros((50, 50, 50), dtype=np.uint8)
mask_arr[10:40, 10:40, 10:40] = 1
mask = Image(mask_arr, spacing=(1.0, 1.0, 1.0), origin=(0,0,0))
# Calculate features
features = calculate_morphology_features(mask)
print(features["volume_voxel_counting_YEKZ"])
calculate_morphology_features(mask, image=None, intensity_mask=None, roi_bbox=None, grid_offset=None)
Calculate morphological features from the ROI mask. Includes both voxel-based and mesh-based features (IBSI compliant).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mask
|
Image
|
Image object containing the morphological mask. Nonzero values are treated as ROI membership. |
required |
image
|
Optional[Image]
|
Optional Image object containing intensity data (required for some features). |
None
|
intensity_mask
|
Optional[Image]
|
Optional Image object containing the intensity mask (e.g. after outlier filtering).
If provided, used for intensity-weighted features (99N0, KLMA).
If None, defaults to |
None
|
roi_bbox
|
Optional[tuple[slice, slice, slice]]
|
Optional precomputed tight bounding box of the mask's nonzero voxels (tuple of slices, as returned by an internal bbox scan). Skips rescanning the full mask volume. If None, computed internally. |
None
|
grid_offset
|
Optional[tuple[int, int, int]]
|
Optional index of the first voxel of the arrays in a larger grid, when they hold a region of it. The mesh is then made in the index frame of that grid, so the features are those of the whole grid bit for bit (the MVEE fit depends on the frame at about 1e-5). |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, float]
|
Dictionary of calculated features. |
Example
import numpy as np
from pictologics.loader import Image
from pictologics.features.morphology import calculate_morphology_features
mask_arr = np.zeros((50, 50, 50), dtype=np.uint8)
mask_arr[10:40, 10:40, 10:40] = 1
mask = Image(array=mask_arr, spacing=(1.0, 1.0, 1.0), origin=(0.0, 0.0, 0.0))
features = calculate_morphology_features(mask)
print(round(features["volume_voxel_counting_YEKZ"], 1))
# 27000.0
print(round(features["sphericity_QCFX"], 2))
# 0.82