Skip to content

Pretrained 3D medical image segmentation models: nnU-Net and friends in Python

What ships today, and what is coming

Today: prepare_nnunet_dataset.py: any pardesline dataset written in the nnU-Net v2 raw layout, plus the guide to the model families that win the public benchmarks. No weights are shipped and there is no inference API: the scripts are reference implementations that read any pardesline dataset.

Coming: one-line model access. The same registry pattern as datasets, a model manifest (source, weights URI, licence, input type, task, memory needs, provenance) and pl.load_model(...) / pl.run(model, dataset). This page keeps its URL. Follow and vote on the model registry tracking issue; model manifests can be contributed now from templates/new_model/.

Reference scripts: prepare_nnunet_dataset.py (shipped in the wheel under pardesline/skills/medical-segmentation-models/scripts/, served by the MCP tool get_skill).

Learned segmentation of medical volumes

Which model (2026)

Need Choose Why
A new organ / lesion task with 20-500 labelled volumes nnU-Net v2 (3d_fullres, + 3d_lowres cascade for large FOV) self-configures spacing, patch size, batch size, normalisation from the dataset fingerprint; still the strongest baseline on MSD, AMOS, KiTS
117 body structures on CT without training TotalSegmentator (its dataset totalsegmentator_ct is CC BY 4.0; the weights carry their own non-commercial terms, check before shipping) one command, nnU-Net inside
Transformer backbone, large data Swin-UNETR / UNETR (MONAI), SegResNet gains appear above ~1 000 volumes or with self-supervised pretraining
Interactive / few labels MedSAM, SAM-Med3D, nnInteractive prompt with boxes or clicks; validate per case
Many sources, foundation-model style BiomedSegFM-type challenge models, STU-Net pretrain on pooled datasets (hf_biomedsegfm_3d_val shows the pooled format)

Every one of them is a voxel network: the label lives in the voxel grid (see 3d-representations).

Data: from a pardesline dataset to a training set

import pardesline as pl

ds = pl.load("msd_task09_spleen").filter(split="Tr")  # 41 labelled CTs, licence attached
train, val = ds.split(by="id", fractions=(0.8, 0.2), seed=0)  # patient-level split, no leakage
ds.export("./spleen_std")  # NIfTI + sidecars + manifest if you want local files

scripts/prepare_nnunet_dataset.py writes the nnU-Net raw layout (imagesTr/CASE_0000.nii.gz, labelsTr/CASE.nii.gz, dataset.json) from any pardesline dataset with an image role and a labels role, including multi-channel inputs (MSD brain tumour: 4 modalities = _0000..._0003), DICOM series (materialised to NIfTI) and TotalSegmentator's one-mask-per-organ layout (merged into one label map with a class table).

Rules: - Split by patient (pairing key); never by slice. - Keep the licence: nnU-Net models trained on NC data (KiTS23, TotalSegmentator MRI, BiomedSegFM) inherit the restriction; say so in the model card. - Record spacing and orientation per case; nnU-Net resamples to the median spacing (or the 10th percentile along the low-res axis) and crops to the foreground.

Preprocessing that matters

Step CT MRI PET
Resampling isotropic or dataset-median spacing, image linear / labels nearest same same
Intensity clip to the 0.5-99.5 percentile of foreground HU, z-score with global mean/std (nnU-Net "CT" scheme) per-volume z-score (scanner-dependent intensities), optional N4 bias correction SUV normalisation
Orientation reorient to a canonical frame (RAS or LPS) consistently; pardesline volumes are LPS same same
Cropping to the non-zero / body region brain extraction optional
Patches 128^3 (fullres) or anisotropic (e.g. 40 x 224 x 224) when spacing is anisotropic; oversample patches containing foreground (33 %)

Training recipe (nnU-Net defaults, the ones worth knowing)

  • Loss: Dice + cross-entropy, deep supervision at 3-4 decoder scales (weights 1, 1/2, 1/4...).
  • Optimizer: SGD momentum 0.99, Nesterov, lr 1e-2 with poly decay, 1 000 epochs x 250 iterations, batch 2; mixed precision.
  • Augmentation on the fly: rotation, scaling, elastic (light), Gaussian noise and blur, brightness / contrast, gamma, mirroring along anatomically valid axes only (never left-right if laterality matters: kidneys, lungs).
  • 5-fold cross-validation; ensemble folds at inference.
  • Budget: 1 fold of 3d_fullres ~ 1-2 GPU-days on a 24 GB card at 128^3; a "quick look" at 100 epochs tells whether the task is learnable.

Inference

Sliding window with 50 % overlap and a Gaussian importance map (centre of the patch trusted more), test-time augmentation by flips, argmax, then post-processing: keep the largest connected component per class when the anatomy is a single object (spleen, liver), not for lesions or vessels. Resample the prediction back to the original grid with nearest-neighbour and write it with the original header. In pardesline:

pred = pl.load("pred_case07.nii.gz").as_labels({1: "spleen"})  # LabelMap in LPS mm
surf = pred.to_mesh(label=1)  # exact surface for review
pred.save("case07_pred.nii.gz")  # + sidecar with labels and provenance

Evaluation

Per class and per case: Dice, HD95 (mm), NSD at 1-3 mm, volume error; median and IQR; worst cases shown. evaluation-metrics-3d/scripts/metrics3d.py implements them; metrics3d.py --dataset liver_tumor_patient01 prints the inter-observer agreement of three radiologists, the ceiling any model should be compared with.

Common failures

Symptom Cause Fix
Dice fine, HD95 huge isolated false positives far away largest-component post-processing, lower-res cascade for context
Collapses on small structures class imbalance foreground oversampling, Dice loss already helps, patch size covering the structure
Works on one scanner only intensity shift per-volume normalisation (MRI), intensity augmentation, more centres
Laterality swap mirroring augmentation on left/right classes disable left-right flips
Looks good in 2D, striped in 3D 2D model on anisotropic data 3D model or 2.5D with neighbouring slices
Train/val gap leakage by slice or by patient with several scans split by patient id

Datasets to practise on

MSD tasks (msd_task01_braintumour ... msd_task10_colon), amos22 (15 organs CT/MRI), totalsegmentator_ct / totalsegmentator_mri, hf_kits23, verse19_spine, spider_lumbar_mri, hf_nsclc_radiomics, hf_biomedsegfm_3d_val (pooled npz), luna16 (detection), tcia_lidc_idri (DICOM + SEG).

Source: skills/medical-segmentation-models/SKILL.md, published on 2026-10-14.