Skip to main content

Module hdbet

Module hdbet 

Source
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):

  1. crop to the bounding box of non-zero voxels;
  2. z-score normalise over the cropped image;
  3. resample to 1 mm with cubic splines (nnU-Net’s “separate z” rule for anisotropic voxels: cubic in-plane, nearest-neighbour through-plane);
  4. 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;
  5. 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 the hd-bet CLI (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, and hd_bet takes 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_tta on CPU (readme.md:100-114). HdBetParams::default is 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_memory does (1.6 GB on a 184×256×128 mm volume). hd_bet_memory_bytes with crate::models::Heap::Wasm32 gives 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§

HdBetParams
HD-BET inference parameters.
Preprocessed 🔒
nnU-Net-preprocessed volume plus what is needed to map predictions back.

Enums§

HdBetInference
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 origin inside 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_logits centres 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_bet on a scan on grid, in bytes, natively or in a wasm32 heap.
hd_bet_network_input
The spatial shape (z, y, x) of the tensor HD-BET’s network sees on a scan on grid: with HdBetInference::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 channels outputs, channel-major C-order (shape [channels, dims...]). patch must be a size the network accepts; tile_step is the stride as a fraction of the patch; mirror_tta averages over the 8 axis mirrorings. Shared with super::rs2net.
preprocess 🔒
Crop to non-zero, z-score, resample to 1 mm. None if the image is entirely zero.
resample_nnunet 🔒
nnU-Net resample_data_or_seg_to_shape for 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 with order and the low-resolution axis with nearest-neighbour.
resampled_dims 🔒
nnU-Net compute_new_shape: the (z, y, x) dims of a dims volume with voxel spacing at 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) along axis of a C-order volume.
window_steps 🔒
nnU-Net compute_steps_for_sliding_window for one axis.