Install · Quick start · Commands · User guide · Technical reference
Convert medical volumes without changing their image data, extract STL/PLY/OBJ surface meshes, register two segmentations into an editable binary labelmap, or edit a labelmap block by block in Minecraft Java. DICOM series, NIfTI, NRRD, and MetaImage inputs are supported.
Safety:
medsurfaceis not validated for diagnosis, treatment planning, or other clinical decisions. Segmentation, registration, and mesh processing can change or omit anatomy. Review source images and every output independently. See Safety and privacy.
Python 3.11 or newer and uv are required.
uv tool install .First inspect the available volumes:
medsurface list ~/scans/head-ctThen extract the recommended volume's surface:
medsurface extract ~/scans/head-ct -o skull.stlThe default bone preset extracts stored values at or above 300. It is treated
as HU only when DICOM CT metadata supplies sufficient calibration evidence;
other inputs receive a warning. Use the unique integer ID printed by list when
the catalog has no safe automatic choice:
medsurface extract ~/scans/head-ct --volume 1 -o skull.stlA direct .nii, .nii.gz, .nrrd, .nhdr, .mha, or .mhd volume needs no
selector. To change only its storage format, use strict conversion:
medsurface convert scan.mhd -o scan.nrrdconvert preserves loaded voxel values, scalar pixel type, component count,
dimensions, spacing, origin, and direction. It does not threshold, cast,
resample, or reorient the image. Source metadata is retained when the output
format can represent it; add --strip-metadata to remove it while keeping
required format headers.
If another tool already created a segmentation labelmap, start at surface extraction instead of intensity segmentation:
medsurface labelmap extract segmentation.nii.gz -o surface.stl| command | purpose |
|---|---|
medsurface list INPUT |
Show every supported volume and any automatic default |
medsurface presets |
Show the available tissue presets |
medsurface convert INPUT -o VOLUME |
Preserve one image while changing its single-file storage format |
medsurface extract INPUT -o MODEL.stl |
Segment one intensity volume and extract a surface mesh |
medsurface fuse FIXED MOVING -o LABELMAP |
Segment, register, and union two volumes into a binary labelmap |
medsurface labelmap extract MASK -o MODEL.stl |
Extract one surface from all nonzero (or --labels) labels |
medsurface labelmap extract MASK --split DIR |
Extract one validated surface per label |
medsurface labelmap fuse FIXED MOVING... -o LABELMAP |
Register and fuse labelmaps into a binary or --preserve-labels map |
medsurface validate MODEL.stl |
Report mesh quality without changing the file |
medsurface repair MODEL.stl -o FIXED.stl |
Repair an open or non-manifold mesh |
medsurface minecraft to-world MASK -o WORLD |
Build an editable Minecraft Java world, one voxel per block |
medsurface minecraft to-labelmap WORLD -o LABELMAP |
Validate an edited world and export it on the original grid |
medsurface minecraft inspect WORLD |
Show a world's grid, placement, and label palette |
medsurface minecraft validate WORLD |
Check every block in a world's export volume |
medsurface minecraft resample MASK -o LABELMAP |
Write the cubic-block grid to-world --block-mm would build |
medsurface minecraft blocks |
List the 127 supported label blocks with approximate colors |
Run medsurface COMMAND --help for every option and medsurface --version for
the installed version. Mesh destinations are .stl, .ply, or .obj.
Conversion and fusion destinations are atomic single-file .nii, .nii.gz,
.nrrd, or .mha volumes. Detached .nhdr and .mhd remain input-only.
Convert one selected catalog volume and record the operation:
medsurface convert scans/ --volume 2 -o selected.nii.gz \
--json selected-conversion.json.nii is uncompressed, .nii.gz uses gzip, .nrrd uses gzip, and .mha uses
zlib. The volume is written to a temporary sibling, read back, and checked for
exact voxel data, type, components, dimensions, and physical geometry before it
atomically replaces the destination. An unrepresentable core image contract is
an error; metadata preservation remains best effort.
Choose a preset or explicit threshold when producing a mesh:
medsurface extract scans/ --preset teeth -o teeth.stl
medsurface extract scans/ --threshold 250 -o bone-250hu.stl
medsurface extract scan.mha --preset auto -o automatic.stlSurface controls such as --mask-smooth-mm, --mesh-smooth-iters,
--simplify-error-mm, --post-mesh-smooth-iters, --components, and
--destep belong to extract commands only.
CT slice terraces can survive as shallow ripples on smooth anatomy such as a skull dome. Optional final fairing removes them while leaving frozen regions untouched:
medsurface extract scans/ -o skull.stl --destep auto
medsurface labelmap extract skull.nrrd -o skull.stl \
--destep band --destep-axis z --destep-full-mm -555 --destep-frozen-mm -600auto fairs broad surfaces and freezes tightly curved detail such as teeth,
together with its surroundings, band ramps from a frozen coordinate to a fully faired one, and all fairs
every vertex. Each vertex moves at most --destep-max-mm (1 mm by default).
See Reducing stair-step ripples.
Confirm that both scans show the same subject and matching non-deforming anatomy, then create an inspectable binary union before meshing it:
medsurface fuse facial-ct/ sinus-ct/ \
--fixed-volume 1 --moving-volume 1 -o skull-union.nrrd
medsurface labelmap extract skull-union.nrrd -o skull.stlfuse independently segments each input, rigidly registers moving foreground to
fixed foreground, and publishes scalar uint8 values 0 and 1 on an
axis-aligned isotropic grid. It never writes a mesh or applies surface controls.
After success it prints a shell-safe medsurface labelmap extract command hint,
unless normal output is suppressed with --quiet.
Registration-quality checks can refuse unsafe geometry; --force overrides only
those gates and can produce a plausible but incorrect labelmap.
TotalSegmentator and similar tools remain separate optional programs. Every nonzero label is treated as one foreground class:
TotalSegmentator -i scan.nii.gz -o selected.nii.gz \
--ml --roi_subset skull vertebrae_C1
medsurface labelmap extract selected.nii.gz -o selected.stlTo register matching masks from two acquisitions, publish the binary union, optionally edit it, and explicitly extract its surface:
medsurface labelmap fuse fixed-selected.nii.gz moving-selected.nii.gz \
-o fused.mha --json fused.json
# Edit fused.mha if needed.
medsurface labelmap extract fused.mha -o fused.stlDifferent positive source IDs are equivalent and are not preserved. Fusion does
not transfer source metadata or intensity-preset surface settings to the result;
the later labelmap extract uses its normal labelmap defaults.
Select labels, write one mesh per structure, and fuse more than two scans while keeping their label IDs:
medsurface labelmap extract segmentations.nii.gz --labels 25-50,91 \
--split parts/ -o parts/combined.stl
medsurface labelmap fuse head.nii.gz neck.nii.gz chest.nii.gz \
--preserve-labels -o body.nii.gzPer-label files are named from the label table TotalSegmentator embeds in NIfTI
files, or from --label-names names.json. Programs can add --progress json
to any command for JSON-lines progress on stderr. See Using an external
labelmap.
Turn a labelmap into a Minecraft Java 26.2 world, edit it block by block, and export the edited labels on the original grid:
medsurface minecraft to-world segmentations.nii.gz -o ./labels-world
# Copy labels-world into Minecraft's saves directory, edit, and close it.
medsurface minecraft to-labelmap ./labels-world -o edited.nii.gzOne voxel becomes one block and label 0 is air. Add --block-mm auto --orient anatomical for cubic blocks with the anatomy standing upright. See
Minecraft worlds.
Every mesh-producing extraction validates its serialized mesh before atomic publication. Inspect an existing mesh without changing it:
medsurface validate model.stlRepair validates both its in-memory result and serialized temporary file, then atomically publishes a separate output:
medsurface repair broken.stl -o repaired.stlPrimary outputs and optional JSON reports cannot alias each other or any discovered input, including DICOM instances and detached payloads. Conversion and fusion roll their primary destination back if requested report publication fails. A valid mesh or verified volume can still be anatomically wrong; read the input limitations and validation explanation.