Skip to main content

ct-segmentation-toolkit

Segmentation of scientific image stacks across the full supervision spectrum, from no labels to fully labeled masks, in one tested Python package.

CI PyPI Python DOI License: Apache-2.0

Pipeline overview: an image stack, optional self-supervised denoising, three segmentation routes chosen by label availability, and per-pixel labels

The toolkit segments volumetric images such as synchrotron and laboratory micro-computed tomography (micro-CT) stacks. It is organized around one practical question: how many labels exist? The unsupervised and label-free routes need none, and the U-Net needs annotated masks. An optional self-supervised denoiser raises the signal-to-noise ratio before any of them. Vector schematic: docs/ct_segmentation_pipeline.pdf.

Associated preprint: C. Renteria et al., "Deep learning segmentation of enamel rod architecture from synchrotron computed tomography for bioinspired material design," SSRN (2026), doi:10.2139/ssrn.6805001.

Methods

Route Labels needed Method Entry point
Unsupervised none Multi-Otsu thresholding, k-means, or a Gaussian mixture model (GMM) on intensity segment_otsu, segment_kmeans, segment_gmm
Label-free spectral-spatial none A Self-Organizing Map (SOM) over per-pixel features (multi-scale density, structure-tensor orientation and coherence, a Gabor filter bank, local variance), followed by clustering of the SOM nodes; the same features transfer to hyperspectral cubes som_segment
Supervised annotated masks U-Net with training and inference UNetSegmentation, python -m ct_seg.train
Denoising (optional) none 2.5D Noise2Inverse: a no-skip U-Net trained from one noisy reconstruction, with no clean reference, using a Laplacian Contrast Loss and edge-aware model selection ct_seg.denoise

The denoising subpackage was developed together by Austin Yunker (Argonne National Laboratory) and Cameron B. Renteria; upstream credit is in ct_seg/denoise/ACKNOWLEDGMENTS.md.

Installation

From PyPI:

pip install ct-segmentation-toolkit                  # classical, SOM, and U-Net segmentation
pip install "ct-segmentation-toolkit[denoise]"       # + Noise2Inverse training (albumentations, PyYAML)
pip install "ct-segmentation-toolkit[viz]"           # + napari labeling and the PyVista viewer
pip install "ct-segmentation-toolkit[mlops]"         # + MLflow experiment tracking

As a signed container image:

docker pull ghcr.io/crentb/ct-segmentation-toolkit:v0.2.0

From source, for development:

git clone https://github.com/crentb/ct-segmentation-toolkit.git
cd ct-segmentation-toolkit
python -m pip install -e ".[dev]"       # core + pytest, ruff, black, mypy, pre-commit

Quick start

Python API:

import numpy as np
from ct_seg import segment_kmeans, som_segment, UNetSegmentation

volume = np.random.rand(16, 256, 256).astype("float32")   # (slices, H, W) in [0, 1]

# Unsupervised intensity segmentation (no labels)
labels, info = segment_kmeans(volume, num_classes=4)

# Label-free spectral-spatial segmentation of a single slice
band_map = som_segment(volume[0], n_clusters=4)

# Supervised U-Net
model = UNetSegmentation(in_channels=1, num_classes=4)

Command line:

# Unsupervised (otsu | kmeans | gmm)
python -m ct_seg.segment --input /path/to/tiffs --method kmeans --num_classes 4 --save_overlay

# Train a U-Net, then segment with it
python -m ct_seg.train   --images /path/to/tiffs --masks /path/to/masks --num_classes 4
python -m ct_seg.segment --input /path/to/tiffs --method unet --model SegOutput/best_model.pth --num_classes 4

The interactive tools ct_seg.labeling (napari) and ct_seg.viewer (napari and PyVista) require the [viz] extra.

Experiment tracking and profiling

Training integrates optional MLflow logging of run parameters, per-epoch loss and mean intersection-over-union, and the best checkpoint. With the extra installed it logs automatically; without MLflow, tracking is a no-op and training is unaffected.

pip install "ct-segmentation-toolkit[mlops]"
python -m ct_seg.train --images ... --masks ... --num_classes 4   # logs to ./mlruns
mlflow ui                                                          # browse runs

A reproducible performance profile (forward and training-step latency, throughput, and peak GPU memory) is in docs/PERF.md:

python scripts/profile_unet.py --device cuda --sizes 256 512

Repository layout

ct_seg/
  segment.py      classical (Otsu, k-means, GMM) and U-Net segmentation; command line
  som_bands.py    spectral-spatial features and SOM segmentation
  model.py        U-Net model
  train.py        U-Net training command line, with optional MLflow logging
  tracking.py     optional MLflow experiment tracking (no-op when MLflow is absent)
  labeling.py     napari labeling tool                         [viz]
  viewer.py       napari / PyVista volume viewer               [viz]
  denoise/        2.5D Noise2Inverse: model, loss, training, inference, evaluation
docs/             overview figure (PNG, PDF, LaTeX source), performance profile, flame graphs
scripts/          profiling utilities
tests/            fast CPU test suite; slow tests are marked

Testing and continuous integration

pytest -m "not slow"    # fast suite (what CI runs)
pytest                  # everything

Every push and pull request runs one gate, defined in ci.yml:

  • Quality: ruff, black, mypy (advisory), and pytest with coverage on Python 3.10 to 3.14.
  • Security (blocking): gitleaks secret detection over the full history, bandit static analysis at medium severity and above, and pip-audit against known vulnerabilities.
  • Container: image build, a trivy scan that blocks on fixable critical and high findings, the test suite run inside the image, and an SPDX software bill of materials signed keylessly with cosign.

The same gate re-runs weekly on main (scheduled-scan.yml), so a newly published vulnerability surfaces without a code change. A version tag re-runs it on the tagged commit before release.yml publishes to PyPI through Trusted Publishing (no stored tokens) and pushes a scanned, cosign-signed image with SLSA build provenance to the GitHub Container Registry. To verify a published image:

cosign verify ghcr.io/crentb/ct-segmentation-toolkit:v0.2.0 \
  --certificate-identity-regexp 'github.com/crentb/' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com
gh attestation verify oci://ghcr.io/crentb/ct-segmentation-toolkit:v0.2.0 --owner crentb

To report a vulnerability, see SECURITY.md.

Citation

Please cite the software and the associated preprint. GitHub's "Cite this repository" button reads CITATION.cff.

@software{renteria_ct_segmentation_toolkit,
  author    = {Renteria, Cameron B.},
  title     = {ct-segmentation-toolkit},
  version   = {0.2.0},
  year      = {2026},
  publisher = {Zenodo},
  doi       = {10.5281/zenodo.21148567},
  url       = {https://github.com/crentb/ct-segmentation-toolkit}
}

Acknowledgments

ct_seg.denoise implements the Noise2Inverse framework of Hendriksen, Pelt, and Batenburg (IEEE Transactions on Computational Imaging, 2020; original code). See ct_seg/denoise/ACKNOWLEDGMENTS.md.

License

Apache-2.0. See LICENSE and NOTICE.

Metadata

Release files for ct-segmentation-toolkit 0.2.1

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

Source distribution (sdist)

Source distribution for ct-segmentation-toolkit 0.2.1
File Size Uploaded
ct_segmentation_toolkit-0.2.1.tar.gz 48.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ct-segmentation-toolkit 0.2.1
File Interpreter ABI Platform
ct_segmentation_toolkit-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 102.9 kB

Release files / ct_segmentation_toolkit-0.2.1.tar.gz

Download URL ct_segmentation_toolkit-0.2.1.tar.gz
Size 48.8 kB
Tags Source
SHA-256 checksum
How to use checksums
f058807e9479ec4f2fec8de6c2fcbcc5ce4bcdafef82c1ed314fa539efad376c
BLAKE2b-256 checksum
How to use checksums
c48927d9c46ab8a8576420c1442ddf5de824ac5f1b0fb9c7d62144d0cb96c4e1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.

Transparency log

Release files / ct_segmentation_toolkit-0.2.1-py3-none-any.whl

Download URL ct_segmentation_toolkit-0.2.1-py3-none-any.whl
Size 54.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6b049b9734c96458f8c0edcc79b854207a18bf9d3a5fbe3f0c1e74b8c6d26504
BLAKE2b-256 checksum
How to use checksums
5b11b654edf2c5bd1938ffd418d72bc18544cdd55694327a317c92f378c25d6a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.1 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