Two-part coursework project on CT-scan segmentation using classical image-processing techniques (no deep learning) — automatic bone segmentation and multi-seed region-growing liver segmentation.
Automatic threshold-based skeleton segmentation from contrast CT scans.
- Searches 26 candidate intensity thresholds (150–500 HU) and selects the optimal one via connected-component analysis, identifying local minima in a connectivity curve
- Applies adaptive post-processing: morphological dilation/closing for sparse/fragmented structures, opening for dense/contaminated structures
- Connects nearby components (e.g., ribs to spine) using KD-tree nearest-neighbor search and 3D line-bridging, preserving anatomical structure better than morphology alone
- Evaluated across 10 CT cases (5 standard, 5 hard cases) with connectivity/fragmentation visualizations
from bones_segmentation import skeleton_th_finder
best_min = skeleton_th_finder("MIP-data/CaseX.nii.gz")Or run the file directly (python bones_segmentation.py) to process all 10 cases via its __main__ block.
| Case1 | Case2 |
|---|---|
![]() |
![]() |
Automatic liver segmentation using anatomical priors and multi-seed region growing (MSRG).
- Determines liver side and diaphragm dome location from lung-lobe segmentation to place a seed ROI anatomically inside the liver
- Runs MSRG with intensity, distance, and Z-axis constraints, iteratively growing from seed points
- Post-processes via largest-component selection and axis-wise 2D propagation from the seed slice outward
- Evaluated via Dice coefficient and Volume Overlap Difference (VOD) across 10 CT cases
from liver_segmentation import segment_liver
segment_liver("MIP-data/CaseX.nii.gz", "MIP-data/CaseX_lower_lobes_seg.nii.gz", "MIP-data/CaseX_my_liver_seg.nii.gz")Or run python liver_segmentation.py directly to process all 10 cases end-to-end, printing Dice/VOD and saving only the final mask.
| Case4 | HardCase3 |
|---|---|
![]() |
![]() |
Results: Dice scores of 0.89–0.94 across 9/10 cases. One case (HardCase1) scored lower (0.43) due to a ground-truth annotation containing two disconnected components, while the algorithm correctly segmented only the anatomically valid main liver component — a ground-truth mismatch rather than a segmentation failure.
numpy, nibabel, scipy (ndimage, spatial), matplotlib, scikit-image (measure, draw)
pip install numpy nibabel matplotlib scipy scikit-imageEach case requires the following files in the MIP-data/ folder:
{CaseName}.nii.gz— CT scan (NIfTI){CaseName}_lower_lobes_seg.nii.gz— lower lung lobes segmentation (for Part 2){CaseName}_liver_seg.nii.gz— ground truth (optional, for evaluation)
Saved to the results/ folder:
{CaseName}_SkeletonSegmentation.nii.gz— bone segmentation (Part 1){CaseName}_threshold_analysis.png— connectivity/threshold plot (Part 1){CaseName}_my_liver_seg.nii.gz— liver segmentation (Part 2)



