ct-segmentation-toolkit 0.2.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/NOTICE +2 -1
- ct_segmentation_toolkit-0.2.1/PKG-INFO +216 -0
- ct_segmentation_toolkit-0.2.1/README.md +165 -0
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/__init__.py +1 -1
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/denoise/__init__.py +8 -7
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/denoise/data.py +2 -1
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/denoise/denoise_slice.py +2 -1
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/denoise/denoise_volume.py +2 -1
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/denoise/eval.py +2 -1
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/denoise/loss.py +2 -1
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/denoise/model.py +2 -1
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/denoise/tiffs.py +2 -1
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/denoise/train.py +2 -1
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/denoise/utils.py +2 -1
- ct_segmentation_toolkit-0.2.1/ct_segmentation_toolkit.egg-info/PKG-INFO +216 -0
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_segmentation_toolkit.egg-info/requires.txt +3 -3
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/pyproject.toml +4 -2
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/tests/test_model.py +1 -1
- ct_segmentation_toolkit-0.2.0/PKG-INFO +0 -156
- ct_segmentation_toolkit-0.2.0/README.md +0 -107
- ct_segmentation_toolkit-0.2.0/ct_segmentation_toolkit.egg-info/PKG-INFO +0 -156
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/LICENSE +0 -0
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/labeling.py +0 -0
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/model.py +0 -0
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/segment.py +0 -0
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/som_bands.py +0 -0
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/tracking.py +0 -0
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/train.py +0 -0
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/viewer.py +0 -0
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_segmentation_toolkit.egg-info/SOURCES.txt +0 -0
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_segmentation_toolkit.egg-info/dependency_links.txt +0 -0
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_segmentation_toolkit.egg-info/top_level.txt +0 -0
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/setup.cfg +0 -0
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/tests/test_denoise.py +0 -0
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/tests/test_segment.py +0 -0
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/tests/test_som_bands.py +0 -0
- {ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/tests/test_tracking.py +0 -0
|
@@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
15
|
|
|
16
|
-
This product includes `ct_seg.denoise`,
|
|
16
|
+
This product includes `ct_seg.denoise`, developed together by Austin Yunker (Argonne
|
|
17
|
+
National Laboratory) and Cameron B. Renteria, implementing the Noise2Inverse framework
|
|
17
18
|
(Hendriksen, Pelt & Batenburg, IEEE Transactions on Computational Imaging, 2020;
|
|
18
19
|
https://github.com/ahendriksen/noise2inverse). See ct_seg/denoise/ACKNOWLEDGMENTS.md.
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ct-segmentation-toolkit
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Supervised (U-Net), unsupervised (Otsu/k-means/GMM), and label-free spectral-spatial (SOM) segmentation of scientific image stacks.
|
|
5
|
+
Author-email: "Cameron B. Renteria" <crentb@uw.edu>
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/crentb/ct-segmentation-toolkit
|
|
8
|
+
Project-URL: Issues, https://github.com/crentb/ct-segmentation-toolkit/issues
|
|
9
|
+
Keywords: image segmentation,computed tomography,U-Net,self-organizing map,unsupervised,feature extraction,hyperspectral,scientific imaging
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Image Processing
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
License-File: NOTICE
|
|
25
|
+
Requires-Dist: numpy>=1.24
|
|
26
|
+
Requires-Dist: scipy>=1.10
|
|
27
|
+
Requires-Dist: scikit-learn>=1.3
|
|
28
|
+
Requires-Dist: scikit-image>=0.21
|
|
29
|
+
Requires-Dist: tifffile>=2023.1
|
|
30
|
+
Requires-Dist: minisom>=2.3
|
|
31
|
+
Requires-Dist: tqdm>=4.65
|
|
32
|
+
Requires-Dist: Pillow>=9.0
|
|
33
|
+
Requires-Dist: matplotlib>=3.7
|
|
34
|
+
Requires-Dist: torch>=2.0
|
|
35
|
+
Provides-Extra: viz
|
|
36
|
+
Requires-Dist: napari[all]>=0.4; extra == "viz"
|
|
37
|
+
Requires-Dist: pyvista>=0.43; extra == "viz"
|
|
38
|
+
Provides-Extra: mlops
|
|
39
|
+
Requires-Dist: mlflow>=2.0; extra == "mlops"
|
|
40
|
+
Provides-Extra: denoise
|
|
41
|
+
Requires-Dist: albumentations>=1.3; extra == "denoise"
|
|
42
|
+
Requires-Dist: PyYAML>=6.0; extra == "denoise"
|
|
43
|
+
Provides-Extra: dev
|
|
44
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
45
|
+
Requires-Dist: pytest-cov>=4.1; extra == "dev"
|
|
46
|
+
Requires-Dist: ruff==0.16.8; extra == "dev"
|
|
47
|
+
Requires-Dist: black==26.5.1; extra == "dev"
|
|
48
|
+
Requires-Dist: mypy==2.3.1; extra == "dev"
|
|
49
|
+
Requires-Dist: pre-commit>=3.7; extra == "dev"
|
|
50
|
+
Dynamic: license-file
|
|
51
|
+
|
|
52
|
+
# ct-segmentation-toolkit
|
|
53
|
+
|
|
54
|
+
Segmentation of scientific image stacks across the full supervision spectrum, from no labels to fully labeled masks, in one tested Python package.
|
|
55
|
+
|
|
56
|
+
[](https://github.com/crentb/ct-segmentation-toolkit/actions/workflows/ci.yml)
|
|
57
|
+
[](https://pypi.org/project/ct-segmentation-toolkit/)
|
|
58
|
+
[](https://github.com/crentb/ct-segmentation-toolkit/blob/main/pyproject.toml)
|
|
59
|
+
[](https://doi.org/10.5281/zenodo.21148567)
|
|
60
|
+
[](https://github.com/crentb/ct-segmentation-toolkit/blob/main/LICENSE)
|
|
61
|
+
|
|
62
|
+

|
|
63
|
+
|
|
64
|
+
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](https://github.com/crentb/ct-segmentation-toolkit/blob/main/docs/ct_segmentation_pipeline.pdf).
|
|
65
|
+
|
|
66
|
+
**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](https://doi.org/10.2139/ssrn.6805001).
|
|
67
|
+
|
|
68
|
+
## Methods
|
|
69
|
+
|
|
70
|
+
| Route | Labels needed | Method | Entry point |
|
|
71
|
+
|---|---|---|---|
|
|
72
|
+
| Unsupervised | none | Multi-Otsu thresholding, k-means, or a Gaussian mixture model (GMM) on intensity | `segment_otsu`, `segment_kmeans`, `segment_gmm` |
|
|
73
|
+
| 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` |
|
|
74
|
+
| Supervised | annotated masks | U-Net with training and inference | `UNetSegmentation`, `python -m ct_seg.train` |
|
|
75
|
+
| 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` |
|
|
76
|
+
|
|
77
|
+
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](https://github.com/crentb/ct-segmentation-toolkit/blob/main/ct_seg/denoise/ACKNOWLEDGMENTS.md).
|
|
78
|
+
|
|
79
|
+
## Installation
|
|
80
|
+
|
|
81
|
+
From PyPI:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pip install ct-segmentation-toolkit # classical, SOM, and U-Net segmentation
|
|
85
|
+
pip install "ct-segmentation-toolkit[denoise]" # + Noise2Inverse training (albumentations, PyYAML)
|
|
86
|
+
pip install "ct-segmentation-toolkit[viz]" # + napari labeling and the PyVista viewer
|
|
87
|
+
pip install "ct-segmentation-toolkit[mlops]" # + MLflow experiment tracking
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
As a signed container image:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
docker pull ghcr.io/crentb/ct-segmentation-toolkit:v0.2.0
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
From source, for development:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
git clone https://github.com/crentb/ct-segmentation-toolkit.git
|
|
100
|
+
cd ct-segmentation-toolkit
|
|
101
|
+
python -m pip install -e ".[dev]" # core + pytest, ruff, black, mypy, pre-commit
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Quick start
|
|
105
|
+
|
|
106
|
+
Python API:
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
import numpy as np
|
|
110
|
+
from ct_seg import segment_kmeans, som_segment, UNetSegmentation
|
|
111
|
+
|
|
112
|
+
volume = np.random.rand(16, 256, 256).astype("float32") # (slices, H, W) in [0, 1]
|
|
113
|
+
|
|
114
|
+
# Unsupervised intensity segmentation (no labels)
|
|
115
|
+
labels, info = segment_kmeans(volume, num_classes=4)
|
|
116
|
+
|
|
117
|
+
# Label-free spectral-spatial segmentation of a single slice
|
|
118
|
+
band_map = som_segment(volume[0], n_clusters=4)
|
|
119
|
+
|
|
120
|
+
# Supervised U-Net
|
|
121
|
+
model = UNetSegmentation(in_channels=1, num_classes=4)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Command line:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# Unsupervised (otsu | kmeans | gmm)
|
|
128
|
+
python -m ct_seg.segment --input /path/to/tiffs --method kmeans --num_classes 4 --save_overlay
|
|
129
|
+
|
|
130
|
+
# Train a U-Net, then segment with it
|
|
131
|
+
python -m ct_seg.train --images /path/to/tiffs --masks /path/to/masks --num_classes 4
|
|
132
|
+
python -m ct_seg.segment --input /path/to/tiffs --method unet --model SegOutput/best_model.pth --num_classes 4
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
The interactive tools `ct_seg.labeling` (napari) and `ct_seg.viewer` (napari and PyVista) require the `[viz]` extra.
|
|
136
|
+
|
|
137
|
+
## Experiment tracking and profiling
|
|
138
|
+
|
|
139
|
+
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.
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
pip install "ct-segmentation-toolkit[mlops]"
|
|
143
|
+
python -m ct_seg.train --images ... --masks ... --num_classes 4 # logs to ./mlruns
|
|
144
|
+
mlflow ui # browse runs
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
A reproducible performance profile (forward and training-step latency, throughput, and peak GPU memory) is in [docs/PERF.md](https://github.com/crentb/ct-segmentation-toolkit/blob/main/docs/PERF.md):
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
python scripts/profile_unet.py --device cuda --sizes 256 512
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Repository layout
|
|
154
|
+
|
|
155
|
+
```text
|
|
156
|
+
ct_seg/
|
|
157
|
+
segment.py classical (Otsu, k-means, GMM) and U-Net segmentation; command line
|
|
158
|
+
som_bands.py spectral-spatial features and SOM segmentation
|
|
159
|
+
model.py U-Net model
|
|
160
|
+
train.py U-Net training command line, with optional MLflow logging
|
|
161
|
+
tracking.py optional MLflow experiment tracking (no-op when MLflow is absent)
|
|
162
|
+
labeling.py napari labeling tool [viz]
|
|
163
|
+
viewer.py napari / PyVista volume viewer [viz]
|
|
164
|
+
denoise/ 2.5D Noise2Inverse: model, loss, training, inference, evaluation
|
|
165
|
+
docs/ overview figure (PNG, PDF, LaTeX source), performance profile, flame graphs
|
|
166
|
+
scripts/ profiling utilities
|
|
167
|
+
tests/ fast CPU test suite; slow tests are marked
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Testing and continuous integration
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
pytest -m "not slow" # fast suite (what CI runs)
|
|
174
|
+
pytest # everything
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Every push and pull request runs one gate, defined in [ci.yml](https://github.com/crentb/ct-segmentation-toolkit/blob/main/.github/workflows/ci.yml):
|
|
178
|
+
|
|
179
|
+
- **Quality:** ruff, black, mypy (advisory), and pytest with coverage on Python 3.10 to 3.14.
|
|
180
|
+
- **Security (blocking):** gitleaks secret detection over the full history, bandit static analysis at medium severity and above, and pip-audit against known vulnerabilities.
|
|
181
|
+
- **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.
|
|
182
|
+
|
|
183
|
+
The same gate re-runs weekly on `main` ([scheduled-scan.yml](https://github.com/crentb/ct-segmentation-toolkit/blob/main/.github/workflows/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](https://github.com/crentb/ct-segmentation-toolkit/blob/main/.github/workflows/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:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
cosign verify ghcr.io/crentb/ct-segmentation-toolkit:v0.2.0 \
|
|
187
|
+
--certificate-identity-regexp 'github.com/crentb/' \
|
|
188
|
+
--certificate-oidc-issuer https://token.actions.githubusercontent.com
|
|
189
|
+
gh attestation verify oci://ghcr.io/crentb/ct-segmentation-toolkit:v0.2.0 --owner crentb
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
To report a vulnerability, see [SECURITY.md](https://github.com/crentb/ct-segmentation-toolkit/blob/main/SECURITY.md).
|
|
193
|
+
|
|
194
|
+
## Citation
|
|
195
|
+
|
|
196
|
+
Please cite the software and the associated preprint. GitHub's "Cite this repository" button reads [CITATION.cff](https://github.com/crentb/ct-segmentation-toolkit/blob/main/CITATION.cff).
|
|
197
|
+
|
|
198
|
+
```bibtex
|
|
199
|
+
@software{renteria_ct_segmentation_toolkit,
|
|
200
|
+
author = {Renteria, Cameron B.},
|
|
201
|
+
title = {ct-segmentation-toolkit},
|
|
202
|
+
version = {0.2.0},
|
|
203
|
+
year = {2026},
|
|
204
|
+
publisher = {Zenodo},
|
|
205
|
+
doi = {10.5281/zenodo.21148567},
|
|
206
|
+
url = {https://github.com/crentb/ct-segmentation-toolkit}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Acknowledgments
|
|
211
|
+
|
|
212
|
+
`ct_seg.denoise` implements the Noise2Inverse framework of Hendriksen, Pelt, and Batenburg (*IEEE Transactions on Computational Imaging*, 2020; [original code](https://github.com/ahendriksen/noise2inverse)). See [ct_seg/denoise/ACKNOWLEDGMENTS.md](https://github.com/crentb/ct-segmentation-toolkit/blob/main/ct_seg/denoise/ACKNOWLEDGMENTS.md).
|
|
213
|
+
|
|
214
|
+
## License
|
|
215
|
+
|
|
216
|
+
Apache-2.0. See [LICENSE](https://github.com/crentb/ct-segmentation-toolkit/blob/main/LICENSE) and [NOTICE](https://github.com/crentb/ct-segmentation-toolkit/blob/main/NOTICE).
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# ct-segmentation-toolkit
|
|
2
|
+
|
|
3
|
+
Segmentation of scientific image stacks across the full supervision spectrum, from no labels to fully labeled masks, in one tested Python package.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/crentb/ct-segmentation-toolkit/actions/workflows/ci.yml)
|
|
6
|
+
[](https://pypi.org/project/ct-segmentation-toolkit/)
|
|
7
|
+
[](https://github.com/crentb/ct-segmentation-toolkit/blob/main/pyproject.toml)
|
|
8
|
+
[](https://doi.org/10.5281/zenodo.21148567)
|
|
9
|
+
[](https://github.com/crentb/ct-segmentation-toolkit/blob/main/LICENSE)
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
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](https://github.com/crentb/ct-segmentation-toolkit/blob/main/docs/ct_segmentation_pipeline.pdf).
|
|
14
|
+
|
|
15
|
+
**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](https://doi.org/10.2139/ssrn.6805001).
|
|
16
|
+
|
|
17
|
+
## Methods
|
|
18
|
+
|
|
19
|
+
| Route | Labels needed | Method | Entry point |
|
|
20
|
+
|---|---|---|---|
|
|
21
|
+
| Unsupervised | none | Multi-Otsu thresholding, k-means, or a Gaussian mixture model (GMM) on intensity | `segment_otsu`, `segment_kmeans`, `segment_gmm` |
|
|
22
|
+
| 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` |
|
|
23
|
+
| Supervised | annotated masks | U-Net with training and inference | `UNetSegmentation`, `python -m ct_seg.train` |
|
|
24
|
+
| 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` |
|
|
25
|
+
|
|
26
|
+
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](https://github.com/crentb/ct-segmentation-toolkit/blob/main/ct_seg/denoise/ACKNOWLEDGMENTS.md).
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
From PyPI:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install ct-segmentation-toolkit # classical, SOM, and U-Net segmentation
|
|
34
|
+
pip install "ct-segmentation-toolkit[denoise]" # + Noise2Inverse training (albumentations, PyYAML)
|
|
35
|
+
pip install "ct-segmentation-toolkit[viz]" # + napari labeling and the PyVista viewer
|
|
36
|
+
pip install "ct-segmentation-toolkit[mlops]" # + MLflow experiment tracking
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
As a signed container image:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
docker pull ghcr.io/crentb/ct-segmentation-toolkit:v0.2.0
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
From source, for development:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
git clone https://github.com/crentb/ct-segmentation-toolkit.git
|
|
49
|
+
cd ct-segmentation-toolkit
|
|
50
|
+
python -m pip install -e ".[dev]" # core + pytest, ruff, black, mypy, pre-commit
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Quick start
|
|
54
|
+
|
|
55
|
+
Python API:
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
import numpy as np
|
|
59
|
+
from ct_seg import segment_kmeans, som_segment, UNetSegmentation
|
|
60
|
+
|
|
61
|
+
volume = np.random.rand(16, 256, 256).astype("float32") # (slices, H, W) in [0, 1]
|
|
62
|
+
|
|
63
|
+
# Unsupervised intensity segmentation (no labels)
|
|
64
|
+
labels, info = segment_kmeans(volume, num_classes=4)
|
|
65
|
+
|
|
66
|
+
# Label-free spectral-spatial segmentation of a single slice
|
|
67
|
+
band_map = som_segment(volume[0], n_clusters=4)
|
|
68
|
+
|
|
69
|
+
# Supervised U-Net
|
|
70
|
+
model = UNetSegmentation(in_channels=1, num_classes=4)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Command line:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Unsupervised (otsu | kmeans | gmm)
|
|
77
|
+
python -m ct_seg.segment --input /path/to/tiffs --method kmeans --num_classes 4 --save_overlay
|
|
78
|
+
|
|
79
|
+
# Train a U-Net, then segment with it
|
|
80
|
+
python -m ct_seg.train --images /path/to/tiffs --masks /path/to/masks --num_classes 4
|
|
81
|
+
python -m ct_seg.segment --input /path/to/tiffs --method unet --model SegOutput/best_model.pth --num_classes 4
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The interactive tools `ct_seg.labeling` (napari) and `ct_seg.viewer` (napari and PyVista) require the `[viz]` extra.
|
|
85
|
+
|
|
86
|
+
## Experiment tracking and profiling
|
|
87
|
+
|
|
88
|
+
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.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
pip install "ct-segmentation-toolkit[mlops]"
|
|
92
|
+
python -m ct_seg.train --images ... --masks ... --num_classes 4 # logs to ./mlruns
|
|
93
|
+
mlflow ui # browse runs
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
A reproducible performance profile (forward and training-step latency, throughput, and peak GPU memory) is in [docs/PERF.md](https://github.com/crentb/ct-segmentation-toolkit/blob/main/docs/PERF.md):
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
python scripts/profile_unet.py --device cuda --sizes 256 512
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Repository layout
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
ct_seg/
|
|
106
|
+
segment.py classical (Otsu, k-means, GMM) and U-Net segmentation; command line
|
|
107
|
+
som_bands.py spectral-spatial features and SOM segmentation
|
|
108
|
+
model.py U-Net model
|
|
109
|
+
train.py U-Net training command line, with optional MLflow logging
|
|
110
|
+
tracking.py optional MLflow experiment tracking (no-op when MLflow is absent)
|
|
111
|
+
labeling.py napari labeling tool [viz]
|
|
112
|
+
viewer.py napari / PyVista volume viewer [viz]
|
|
113
|
+
denoise/ 2.5D Noise2Inverse: model, loss, training, inference, evaluation
|
|
114
|
+
docs/ overview figure (PNG, PDF, LaTeX source), performance profile, flame graphs
|
|
115
|
+
scripts/ profiling utilities
|
|
116
|
+
tests/ fast CPU test suite; slow tests are marked
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Testing and continuous integration
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
pytest -m "not slow" # fast suite (what CI runs)
|
|
123
|
+
pytest # everything
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Every push and pull request runs one gate, defined in [ci.yml](https://github.com/crentb/ct-segmentation-toolkit/blob/main/.github/workflows/ci.yml):
|
|
127
|
+
|
|
128
|
+
- **Quality:** ruff, black, mypy (advisory), and pytest with coverage on Python 3.10 to 3.14.
|
|
129
|
+
- **Security (blocking):** gitleaks secret detection over the full history, bandit static analysis at medium severity and above, and pip-audit against known vulnerabilities.
|
|
130
|
+
- **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.
|
|
131
|
+
|
|
132
|
+
The same gate re-runs weekly on `main` ([scheduled-scan.yml](https://github.com/crentb/ct-segmentation-toolkit/blob/main/.github/workflows/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](https://github.com/crentb/ct-segmentation-toolkit/blob/main/.github/workflows/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:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
cosign verify ghcr.io/crentb/ct-segmentation-toolkit:v0.2.0 \
|
|
136
|
+
--certificate-identity-regexp 'github.com/crentb/' \
|
|
137
|
+
--certificate-oidc-issuer https://token.actions.githubusercontent.com
|
|
138
|
+
gh attestation verify oci://ghcr.io/crentb/ct-segmentation-toolkit:v0.2.0 --owner crentb
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
To report a vulnerability, see [SECURITY.md](https://github.com/crentb/ct-segmentation-toolkit/blob/main/SECURITY.md).
|
|
142
|
+
|
|
143
|
+
## Citation
|
|
144
|
+
|
|
145
|
+
Please cite the software and the associated preprint. GitHub's "Cite this repository" button reads [CITATION.cff](https://github.com/crentb/ct-segmentation-toolkit/blob/main/CITATION.cff).
|
|
146
|
+
|
|
147
|
+
```bibtex
|
|
148
|
+
@software{renteria_ct_segmentation_toolkit,
|
|
149
|
+
author = {Renteria, Cameron B.},
|
|
150
|
+
title = {ct-segmentation-toolkit},
|
|
151
|
+
version = {0.2.0},
|
|
152
|
+
year = {2026},
|
|
153
|
+
publisher = {Zenodo},
|
|
154
|
+
doi = {10.5281/zenodo.21148567},
|
|
155
|
+
url = {https://github.com/crentb/ct-segmentation-toolkit}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Acknowledgments
|
|
160
|
+
|
|
161
|
+
`ct_seg.denoise` implements the Noise2Inverse framework of Hendriksen, Pelt, and Batenburg (*IEEE Transactions on Computational Imaging*, 2020; [original code](https://github.com/ahendriksen/noise2inverse)). See [ct_seg/denoise/ACKNOWLEDGMENTS.md](https://github.com/crentb/ct-segmentation-toolkit/blob/main/ct_seg/denoise/ACKNOWLEDGMENTS.md).
|
|
162
|
+
|
|
163
|
+
## License
|
|
164
|
+
|
|
165
|
+
Apache-2.0. See [LICENSE](https://github.com/crentb/ct-segmentation-toolkit/blob/main/LICENSE) and [NOTICE](https://github.com/crentb/ct-segmentation-toolkit/blob/main/NOTICE).
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
"""
|
|
2
2
|
ct_seg.denoise — self-supervised CT denoising (2.5D Noise2Inverse).
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
Developed together by Austin Yunker (Argonne National Laboratory) and Cameron B. Renteria.
|
|
5
|
+
An implementation of the Noise2Inverse (N2I) self-supervised tomography-denoising
|
|
6
|
+
framework: a no-skip U-Net (Group Normalization, LeakyReLU) trained to map one
|
|
7
|
+
sub-reconstruction (e.g. even-angle) to another (odd-angle), so it needs no clean
|
|
8
|
+
reference image. Additions over the base method include a 2.5D adjacent-slice input, a
|
|
9
|
+
Laplacian Contrast Loss (LCL) for edge preservation, edge-aware model selection, and
|
|
10
|
+
automatic GPU batch-size optimization.
|
|
10
11
|
|
|
11
12
|
Upstream method (credited): Noise2Inverse - Hendriksen, Pelt & Batenburg, IEEE Transactions
|
|
12
13
|
on Computational Imaging 6 (2020); original code https://github.com/ahendriksen/noise2inverse
|
|
13
|
-
(see ACKNOWLEDGMENTS.md). This subpackage is
|
|
14
|
+
(see ACKNOWLEDGMENTS.md). This subpackage is licensed Apache-2.0.
|
|
14
15
|
|
|
15
16
|
Only the lightweight building blocks (model, loss, edge score) are exported here. The
|
|
16
17
|
training/inference CLIs and dataset (`ct_seg.denoise.train`, `denoise_volume`,
|
|
@@ -14,7 +14,8 @@ inference pipelines:
|
|
|
14
14
|
* InferenceBatchSizeOptimizer - binary-search the largest batch size that fits
|
|
15
15
|
in GPU memory to avoid out-of-memory errors.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Authors: Austin Yunker (Argonne National Laboratory),
|
|
18
|
+
Cameron B. Renteria <crentb23@gmail.com>
|
|
18
19
|
License: Apache-2.0 (see LICENSE)
|
|
19
20
|
"""
|
|
20
21
|
|
{ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/denoise/denoise_slice.py
RENAMED
|
@@ -19,7 +19,8 @@ Usage:
|
|
|
19
19
|
python denoise_slice.py -gpus=0 -config=/path/to/config.yaml -slice_number=500
|
|
20
20
|
(normally launched via denoise_slice.sh)
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
Authors: Austin Yunker (Argonne National Laboratory),
|
|
23
|
+
Cameron B. Renteria <crentb23@gmail.com>
|
|
23
24
|
License: Apache-2.0 (see LICENSE)
|
|
24
25
|
"""
|
|
25
26
|
|
{ct_segmentation_toolkit-0.2.0 → ct_segmentation_toolkit-0.2.1}/ct_seg/denoise/denoise_volume.py
RENAMED
|
@@ -21,7 +21,8 @@ Usage:
|
|
|
21
21
|
python denoise_volume.py -gpus=0 -config=/path/to/config.yaml -start_slice=500 -end_slice=600
|
|
22
22
|
(normally launched via denoise_volume.sh; omit the range to denoise everything)
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
Authors: Austin Yunker (Argonne National Laboratory),
|
|
25
|
+
Cameron B. Renteria <crentb23@gmail.com>
|
|
25
26
|
License: Apache-2.0 (see LICENSE)
|
|
26
27
|
"""
|
|
27
28
|
|
|
@@ -8,7 +8,8 @@ flat images (low Laplacian-histogram entropy) it instead rewards smoothness. A
|
|
|
8
8
|
higher score means sharper, better-resolved edges, and main.py keeps the
|
|
9
9
|
checkpoint with the highest score (best_edge_model.pth).
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Authors: Austin Yunker (Argonne National Laboratory),
|
|
12
|
+
Cameron B. Renteria <crentb23@gmail.com>
|
|
12
13
|
License: Apache-2.0 (see LICENSE)
|
|
13
14
|
"""
|
|
14
15
|
|
|
@@ -8,7 +8,8 @@ this ratio pushes the network to keep edges sharp (high Laplacian) while smoothi
|
|
|
8
8
|
flat regions (low Laplacian), counteracting the over-smoothing that plain L1
|
|
9
9
|
denoising tends to produce.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Authors: Austin Yunker (Argonne National Laboratory),
|
|
12
|
+
Cameron B. Renteria <crentb23@gmail.com>
|
|
12
13
|
License: Apache-2.0 (see LICENSE)
|
|
13
14
|
"""
|
|
14
15
|
|
|
@@ -15,7 +15,8 @@ setup) and outputs a single denoised slice. Helper modules:
|
|
|
15
15
|
unet_up - nearest-neighbour 2x upsampling
|
|
16
16
|
unet_ns_gn - the full encoder/bottleneck/decoder network
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Authors: Austin Yunker (Argonne National Laboratory),
|
|
19
|
+
Cameron B. Renteria <crentb23@gmail.com>
|
|
19
20
|
License: Apache-2.0 (see LICENSE)
|
|
20
21
|
"""
|
|
21
22
|
|
|
@@ -6,7 +6,8 @@ reconstruction: natural (human) sorting of filenames, loading a directory of TIF
|
|
|
6
6
|
into a NumPy volume, globbing a directory for TIFFs, saving a volume back out as
|
|
7
7
|
numbered TIFFs, and loading a stack as a sinogram.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Authors: Austin Yunker (Argonne National Laboratory),
|
|
10
|
+
Cameron B. Renteria <crentb23@gmail.com>
|
|
10
11
|
License: Apache-2.0 (see LICENSE)
|
|
11
12
|
"""
|
|
12
13
|
|
|
@@ -27,7 +27,8 @@ Usage:
|
|
|
27
27
|
python main.py -gpus=0 -config=/path/to/config.yaml
|
|
28
28
|
(normally launched via train.sh)
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
Authors: Austin Yunker (Argonne National Laboratory),
|
|
31
|
+
Cameron B. Renteria <crentb23@gmail.com>
|
|
31
32
|
License: Apache-2.0 (see LICENSE)
|
|
32
33
|
"""
|
|
33
34
|
|
|
@@ -5,7 +5,8 @@ Helpers shared across the project: write an array to a TIFF or 8-bit PNG preview
|
|
|
5
5
|
(`save2img`), save an RGB preview (`save2img_rgb`), rescale an array to uint8
|
|
6
6
|
(`scale2uint8`), and parse boolean command-line strings (`str2bool`).
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Authors: Austin Yunker (Argonne National Laboratory),
|
|
9
|
+
Cameron B. Renteria <crentb23@gmail.com>
|
|
9
10
|
License: Apache-2.0 (see LICENSE)
|
|
10
11
|
"""
|
|
11
12
|
|