Skip to main content

cbct-bone

cbct-bone is an object-oriented, ready-to-use Python package for extracting binary bone masks from 3D images produced by the target intraoperative CBCT scanner. Its default backend is a v5 2.5D U-Net trained from five reviewed cases, including the interpolated slices between annotation keyframes. Users do not need to train a model, configure a network, or download weights manually.

This version is a research tool, not a medical device. A qualified professional must review every automatic result before it is used for diagnosis, surgical planning, or finite-element analysis.

Features

  • Python 3.12 or later is supported, with uv managing the development environment.
  • DICOM, NIfTI, and .ubd.npz reading is delegated exclusively to ct_mri_dicom_nii_reader.
  • The package depends on med-image-seg==0.1.1 from PyPI, so machine-generated annotation JSON can enter the same bilingual GUI and Python annotation workflow. The GUI defaults to English and can switch to Chinese at runtime.
  • The default v5 ONNX model is downloaded automatically from GitHub Releases on first use; the file is approximately 4.2 MiB.
  • Model downloads support .part resume, retries, an interprocess lock, SHA-256 verification, and atomic installation.
  • CPU inference uses ONNX Runtime and does not require PyTorch. Other ONNX Runtime execution backends can be selected with the provider option.
  • A weight-free 3D adaptive-threshold method remains available as an explicit fallback backend.
  • Inputs are normalized to an isotropic LPS grid, and binary masks can be written as NIfTI or .ubd.npz.
  • MedicalVolumeReader, V5CBCTBoneSegmenter, ModelManager, MedicalMaskWriter, MachineAnnotationWriter, and CBCTBoneExtractor can be reused or replaced independently.
  • The annotation GUI lives in the separate med-image-seg project, so this segmentation package does not carry GUI implementation or training dependencies.

Installation

The project requires Python 3.12 or later.

uv sync --frozen

Install it as a dependency:

uv add cbct-bone

Before a PyPI release is available, install directly from GitHub:

uv add "cbct-bone @ git+https://github.com/GGN-2015/cbct-bone.git"

Command line

The smallest invocation is:

uv run cbct-bone path\to\dicom path\to\bone_mask.nii.gz

The first call downloads and verifies the v5 weights. Later calls use the local cache. The neural models require 0.8 mm isotropic input, which matches the CLI default.

A single DICOM file, .nii, .nii.gz, or .ubd.npz file is also accepted:

uv run cbct-bone scan.nii.gz bone_mask.nii.gz --spacing 0.8

Print diagnostics as JSON:

uv run cbct-bone scan.nii.gz bone_mask.nii.gz --json

Also write per-slice polygon JSON that can be edited by med-image-seg:

uv run cbct-bone scan.nii.gz bone_mask.nii.gz --annotation-json

When --annotation-json has no explicit path, NIfTI and UBD inputs use scan.med-image-seg.json, while DICOM uses .med-image-seg.json in the series directory. A destination can be supplied explicitly:

uv run cbct-bone scan.nii.gz bone_mask.nii.gz `
  --annotation-json D:\review\scan.med-image-seg.json

Machine contours are marked as prototype in the JSON. If the target file already exists, the writer replaces old machine contours while preserving manual contours, review state, and forced-empty slices. Machine and manual results on the same slice are combined by union in med-image-seg. Every inferred slice, including an empty slice, is stored as a keyframe, so reviewing a complete model result does not introduce additional interpolation.

Open the generated annotations directly in the standalone review tool:

cd C:\Users\neko\Desktop\github\med-image-seg
uv run med-image-seg --image "D:\images\scan.nii.gz"

Use only an already verified cached model when no network is available:

uv run cbct-bone scan.nii.gz bone_mask.nii.gz --offline

Select a local model, cache directory, or ONNX Runtime provider:

uv run cbct-bone scan.nii.gz bone_mask.nii.gz `
  --model D:\models\cbct-bone-intraoperative-v5.onnx `
  --provider CPUExecutionProvider

The weight-free adaptive backend can be selected explicitly and permits a different processing resolution:

uv run cbct-bone scan.nii.gz bone_mask.nii.gz `
  --backend adaptive --spacing 1.0

The previous published model remains reproducible with --backend v4.

On Windows, the default model cache is %LOCALAPPDATA%\cbct-bone\models; Linux and macOS use their standard user cache directories. Set CBCT_BONE_CACHE_DIR or pass --cache-dir to override it. The registered model size and SHA-256 are fixed in code, and an invalid file never enters the valid cache.

Every model request reads the standard HTTP_PROXY, HTTPS_PROXY, and NO_PROXY environment variables, including their lowercase equivalents. For example:

$env:HTTP_PROXY = "http://127.0.0.1:10808"
$env:HTTPS_PROXY = "http://127.0.0.1:10808"
uv run cbct-bone scan.nii.gz bone_mask.nii.gz

Python's standard library resolves proxy behavior according to the operating system. Proxy addresses and credentials are never written to the model cache.

List all options:

uv run cbct-bone --help

Annotation tool

Polygon annotation, automatic interpolation, immediate JSON persistence, and the GUI have moved to the independent med-image-seg project, which is installed as a runtime dependency of cbct-bone. cbct-bone itself still has no PyTorch or prototype-training dependency.

Python API

The simplest API reads an image, obtains the v5 weights, runs inference, and writes the mask:

from cbct_bone import segment

result = segment(
    "path/to/dicom",
    "bone_mask.nii.gz",
    annotation_path="path/to/dicom/.med-image-seg.json",
)
print(result.mask.shape)
print(result.diagnostics)
print(result.annotation_path)

For composition and dependency injection, use the class interface:

from cbct_bone import (
    CBCTBoneExtractor,
    MedicalMaskWriter,
    MedicalVolumeReader,
    ModelManager,
    NeuralSegmentationConfig,
    V5CBCTBoneSegmenter,
)

reader = MedicalVolumeReader(spacing_mm=0.8)
models = ModelManager()  # download + resume + SHA-256 verification
algorithm = V5CBCTBoneSegmenter(
    NeuralSegmentationConfig(batch_size=8),
    model_manager=models,
    offline=False,
)
extractor = CBCTBoneExtractor(
    reader=reader,
    segmenter=algorithm,
    writer=MedicalMaskWriter(),
)

result = extractor.extract(
    "path/to/dicom",
    "bone_mask.nii.gz",
    annotation_path="path/to/dicom/.med-image-seg.json",
)
print(result.mask.shape)
print(result.diagnostics)

Prepare the weights in advance for fully offline inference:

from cbct_bone import ModelManager

model_path = ModelManager().get()
print(model_path)

Reuse only the model class when a NumPy LPS volume is already available:

from cbct_bone import V5CBCTBoneSegmenter

mask, diagnostics = V5CBCTBoneSegmenter().segment(
    volume,
    spacing_mm=(0.8, 0.8, 0.8),
)

CBCTBoneExtractor uses dependency injection. A custom component only needs methods compatible with the VolumeReader, BoneMaskSegmenter, or MaskWriter protocol to replace that stage.

Algorithm selection

The default v5 model is a compact 2.5D U-Net tuned for the current target intraoperative CBCT scanner. It uses the current axial slice and its two neighbors, applies robust intensity normalization within each volume, and uses the same threshold and 2D connected-component postprocessing as the annotation workflow. Five reviewed studies contributed 1,206 axial training slices after signed-distance interpolation between annotation keyframes. The model must therefore be treated as a scanner-specific annotation aid, not evidence of cross-scanner or whole-body generalization. See MODEL_CARD.md for the full limitations.

The adaptive backend retains a 3D method without anatomical priors:

  1. Three-class multi-Otsu histogram analysis estimates weak-bone and strong-bone thresholds.
  2. Local mean and variance in a millimeter-scale 3D neighborhood suppress soft tissue and artifacts that only resemble bone in global intensity.
  3. 3D hysteresis region growing expands from strong-bone seeds through weak-bone candidates to recover low-density boundaries affected by partial volume.
  4. Physical-scale closing, enclosed-cavity filling, and minimum-component filtering produce the final binary mask.

This fallback follows the adaptive bone-segmentation approach of Zhang et al., combining initial classification, 3D correlation iteration, and region growing with modern multi-Otsu thresholding and 3D morphology. It requires neither training data nor model weights, but it has no learned anatomical semantics.

For scanners with unusual intensity distributions, thresholds can be overridden explicitly:

uv run cbct-bone scan.nii.gz mask.nii.gz --backend adaptive `
  --weak-threshold 180 --strong-threshold 450

The weak threshold must be lower than the strong threshold. Inspect the automatically selected values with --json, then establish scanner-level settings from a small reviewed dataset.

I/O and coordinate conventions

  • Input paths are read only through the public loader in ct_mri_dicom_nii_reader; this project contains no second medical-image reader.
  • Inputs are resampled to an isotropic (L, P, S) array before processing.
  • SimpleITK is used to write NIfTI, but never to read source images.
  • NIfTI output retains the resampled grid spacing and LPS origin, with an identity direction matrix.
  • .ubd.npz does not preserve a physical origin. It is useful for fast internal exchange, but not for cross-application workflows that depend on patient coordinates.

Validation status

The v5 model-selection run used 965 slices for fitting and 241 slices in contiguous, spatially distributed validation blocks across five target-scanner studies. Internal Dice was 0.8733, precision was 0.8735, and recall was 0.8731. The release model was then retrained for the selected 58 epochs on all 1,206 keyframe and interpolated slices. These blocks still come from the same patients, and most labels are interpolation-derived, so the values are development metrics rather than an independent patient-level estimate of clinical generalization.

Automated tests cover model caching, resumed downloads, SHA-256 failure, offline mode, ONNX axis restoration, spacing constraints, NIfTI geometry round trips, CLI behavior, and object-oriented dependency injection. Numerical comparison between the ONNX export and the original PyTorch v5 model found a maximum absolute error of 1.49e-5. A same-case full-volume sanity check against the fifth reviewed project measured Dice 0.9280, precision 0.8967, and recall 0.9616; because that case contributed to training, this is not a generalization result. Synthetic tests prevent algorithm and geometry regressions; they are not clinical validation.

Before use on real scanners, build a manually labeled test set stratified by scanner, anatomy, dose protocol, and metal implants. Report Dice, surface Dice, HD95, sensitivity, and false-positive volume.

Multicenter testing on open SynthRAD2023 pelvic CBCT data showed a substantial scanner-domain shift for the pure-threshold method. The v5 model has likewise not been validated on independent patients, other scanners, knees, or whole-body anatomy. The current automatic algorithm is not clinically validated; future evaluation requires a patient-separated independent test set and the same volumetric and surface metrics.

Model release

  • Release: model-v5.0.0
  • File: cbct-bone-intraoperative-v5.onnx
  • Size: 4,428,425 bytes
  • SHA-256: e0e5711b856fd22fbb9e0dd31d49c3e73d7b4ea15988029e5acff626304f32f7
  • Training grid: 0.8 mm isotropic LPS
  • Segmentation threshold: 0.8

The runtime accepts a model file only when both its registered size and SHA-256 match.

Run the quality checks:

uv run ruff check .
uv run ruff format --check .
uv run pytest --cov=cbct_bone
uv build

References

License

MIT

Metadata

Release files for cbct-bone 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cbct-bone 0.3.0
File Size Uploaded
cbct_bone-0.3.0.tar.gz 125.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cbct-bone 0.3.0
File Interpreter ABI Platform
cbct_bone-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 154.3 kB

Release files / cbct_bone-0.3.0.tar.gz

Download URL cbct_bone-0.3.0.tar.gz
Size 125.0 kB
Tags Source
SHA-256 checksum
How to use checksums
4eeeba16aa189e980e3bc29df8ffce9a82aedc969852a3bcc6e163b8c6219509
BLAKE2b-256 checksum
How to use checksums
0596fe2319cb18d8511c74280f41a36f1bcdc89ace7ec2422d6391d52ce23f0f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.1 CPython/3.14.6 Windows/11

Release files / cbct_bone-0.3.0-py3-none-any.whl

Download URL cbct_bone-0.3.0-py3-none-any.whl
Size 29.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9ec6418992dde7b029c1774d6324a3b17d1cf2df37b481672a896ca04d1a7374
BLAKE2b-256 checksum
How to use checksums
ca12f2180f2675a0bf9539dbb6e240f8bd49a64849e0755bfe4baafd79bcaec6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.1 CPython/3.14.6 Windows/11

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page