Expand description
HD-BET deep-learning brain extraction (onnx feature).
HD-BET v2 is an nnU-Net v2 3D U-Net (PlainConvUNet, 1 mm isotropic, 96×192×192 patches)
trained on 11,751 multi-sequence clinical MRIs; it segments the brain from a single magnitude
image. This module is a faithful port of nnU-Net’s inference pipeline around the exported
network (hd-bet.onnx, see crate::models):
- crop to the bounding box of non-zero voxels;
- z-score normalise over the cropped image;
- resample to 1 mm with cubic splines (nnU-Net’s “separate z” rule for anisotropic voxels: cubic in-plane, nearest-neighbour through-plane);
- run the network on the whole resampled volume, zero-padded to a size the network accepts
(
HdBetInference::FullVolume, the default, as HD-BET v1 did), or — as nnU-Net and HD-BET v2 do — pad to at least one patch and run Gaussian-weighted sliding-window inference with 50 % overlap (HdBetInference::SlidingWindow); either optionally with 8-fold mirroring test-time augmentation; - resample the logits back (linear; nearest through-plane for anisotropic voxels), take the argmax and un-crop.
nnU-Net works on SimpleITK arrays in (z, y, x) order, which is exactly the memory layout of
the crate’s column-major (nx, ny, nz) volumes — no transposition is needed.
The input should be a magnitude image (for multi-echo GRE, the root-sum-of-squares over
echoes works well) in roughly standard radiological orientation (axial slices along z), as
HD-BET was trained on MNI-aligned data. HD-BET applies no post-processing; combine with
crate::utils::morphology::fill_holes / erosion refinements as needed.
§Reference pipeline
From the HD-BET repository (MIC-DKFZ/HD-BET 678e44d, v2):
- Contrast. Trained on pre- and post-contrast T1-w, T2-w and FLAIR; “other sequences will
most likely work as well” (
readme.md:25-28,79-80). No GRE was in training, and QSM.rs has no Dice against a reference brain mask on GRE recorded; its validation is agreement with thehd-betCLI (Dice ≥ 0.99998,docs/DL_ONNX_SCOPING.md). - Orientation. “Input images must match the orientation of standard MNI152 template! Use
fslreorient2std upfront” (
readme.md:80-82). Neither HD-BET nor this port reorients: the array is used in its stored voxel order, andhd_bettakes no affine. A host must pass a volume already in that orientation. - Resolution. Any; nnU-Net resamples to 1 mm (step 3 above), so the network’s memory
follows the field of view in mm (
hd_bet_memory_bytes). - Inference. The v2 CLI uses nnU-Net’s sliding window (
tile_step_size=0.5, Gaussian) with mirroring test-time augmentation on unless--disable_tta(HD_BET/hd_bet_prediction.py:28-35,HD_BET/entry_point.py:30,48); the readme recommends--disable_ttaon CPU (readme.md:100-114).HdBetParams::defaultis whole-volume without TTA. - WASM. On a 32-bit WASM heap (4 GiB) the whole-volume default does not fit a typical head
scan;
HdBetParams::low_memorydoes (1.6 GB on a 184×256×128 mm volume).hd_bet_memory_byteswithcrate::models::Heap::Wasm32gives the peak for a grid and setting.
Reference: Isensee, F., Schell, M., Pflueger, I., et al. (2019). “Automated brain extraction of multisequence MRI using artificial neural networks.” Human Brain Mapping, 40(17):4952-4964. https://doi.org/10.1002/hbm.24750
Reference implementation: https://github.com/MIC-DKFZ/HD-BET (Apache-2.0; weights CC-BY-NC-4.0).
§Agreement with the original
tests/models_onnx/separation.rs runs it on the 2 mm root-sum-of-squares magnitude of QSM-CI’s
128×160×96 case (tests/data/dl_head_small.bin; a whole head, which HD-BET needs) against its
original’s verified QSM-CI entry, HD-BET 2.0.1 (hd-bet-qsmci) (QSMxT/QSM-CI#316; the fixture
is regenerated in Actions by tests/data/dl_hdbet_qsmci_small.py): with
HdBetInference::SLIDING_WINDOW and no mirroring, as the original’s hd-bet --disable_tta
runs, the masks are identical (Dice 1.0, 187,055 voxels; measured 2026-10-30).
§Pipeline rules
The facts above that a configuration can depart from are published as rules in
crate::pipeline::rules::RULES (each with its strength, basis, reason and source): hd-bet.wasm-heap.
Structs§
- HdBet
Params - HD-BET inference parameters.
- Preprocessed 🔒
- nnU-Net-preprocessed volume plus what is needed to map predictions back.
Enums§
- HdBet
Inference - How the network is applied to the preprocessed (cropped, 1 mm) volume.
Constants§
- PATCH_
DIVISOR 🔒 - Required divisibility of the patch in nnU-Net
(z, y, x)order (5 down-samplings, the last one in-plane only). - TARGET_
SPACING 🔒 - nnU-Net target spacing for HD-BET (mm).
Functions§
- flip3 🔒
- Mirror a C-order patch along the flagged axes (an involution).
- for_
each_ 🔒patch_ row - Visit the rows of a patch at
origininside a volume:f(volume_row_start, patch_row_start). - for_
each_ 🔒slice - Apply
f(slice_index_along_axis, &mut value)to every voxel of a C-order volume. - full_
volume_ 🔒patch - The single “patch” covering a whole
(z, y, x)volume: each axis rounded up to the network’s divisor.predict_logitscentres the volume in it and runs one window. - gaussian_
importance 🔒 - nnU-Net
compute_gaussian(tile, sigma_scale=1/8, value_scaling_factor=10): a Gaussian centred on the patch (σ = tile/8 per axis), peak 10. - hd_bet
- Brain mask via HD-BET.
- hd_
bet_ memory_ bytes - Peak heap of
hd_beton a scan ongrid, in bytes, natively or in awasm32heap. - hd_
bet_ network_ input - The spatial shape
(z, y, x)of the tensor HD-BET’s network sees on a scan ongrid: withHdBetInference::FullVolume, the field of view resampled to 1 mm and padded to multiples of 16×32×32; with a sliding window, its patch. - nonzero_
bbox 🔒 - Bounding box
[start, end)of the non-zero voxels of a C-order(z, y, x)volume. - postprocess 🔒
- Resample logits back to the cropped grid, argmax, un-crop. Returns the column-major mask.
- predict_
logits 🔒 - Gaussian-weighted sliding-window logits of an nnU-Net-style network with
channelsoutputs, channel-major C-order (shape[channels, dims...]).patchmust be a size the network accepts;tile_stepis the stride as a fraction of the patch;mirror_ttaaverages over the 8 axis mirrorings. Shared withsuper::rs2net. - preprocess 🔒
- Crop to non-zero, z-score, resample to 1 mm.
Noneif the image is entirely zero. - resample_
nnunet 🔒 - nnU-Net
resample_data_or_seg_to_shapefor one channel (non-segmentation,order_z = 0,force_separate_z = None): a plain 3D spline resize, unless the voxels are anisotropic (max/min spacing > 3), in which case each slice is resized in-plane withorderand the low-resolution axis with nearest-neighbour. - resampled_
dims 🔒 - nnU-Net
compute_new_shape: the(z, y, x)dims of adimsvolume with voxelspacingat 1 mm,round(spacing / target · dims)with Python’s rounding (half to even). - separate_
z_ 🔒axis - nnU-Net
determine_do_sep_z_and_axis(force_separate_z=None, ...): the low-resolution axis if either spacing is anisotropic by more than 3×, and that axis is unique. - slice_
ranges 🔒 - Per-slice
(min, max)alongaxisof a C-order volume. - window_
steps 🔒 - nnU-Net
compute_steps_for_sliding_windowfor one axis.