VictorButoi commited on
Commit
aabdc18
·
verified ·
1 Parent(s): 8502bd5

Write the flagship model card: ensemble members, TTA recipe, data release link

Browse files
Files changed (2) hide show
  1. README.md +217 -18
  2. checksums.json +1 -1
README.md CHANGED
@@ -1,47 +1,246 @@
1
  ---
2
  license: cc-by-nc-4.0
3
  library_name: pytorch
 
 
 
4
  tags:
5
  - medical-image-segmentation
6
  - x-ray
 
 
7
  - flexray
8
  ---
9
 
10
- # VictorButoi/flexray-base
11
 
12
- This is a FleXray segmentation model bundle. Fill in the public release details
13
- before upload.
 
 
 
14
 
15
- ## Intended Use
 
 
 
 
16
 
17
- Describe the intended research use, input image requirements, output labels, and
18
- medical-use limitations. This model is not cleared for clinical diagnosis or
19
- patient-care decisions.
 
20
 
21
- ## Training Data
22
 
23
- Document every training dataset, source modality, license, preprocessing step,
24
- and inclusion or exclusion criterion.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
  ## Evaluation
27
 
28
- Report evaluation datasets, metrics, confidence intervals where available, and
29
- known failure modes.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
  ## Files
32
 
33
  - `model.safetensors`: exported model weights.
34
- - `config.yml`: model architecture config.
35
  - `label_schema.json`: ordered output labels.
36
  - `preprocessing.json`: public preprocessing contract.
37
- - `checksums.json`: SHA256 checksums.
 
 
 
38
 
39
  ## Licenses
40
 
41
- Code license: MIT
42
-
43
- Weights license: CC-BY-NC-4.0
44
 
45
  ## Citation
46
 
47
- Cite FleXray and any datasets used to train this model.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  license: cc-by-nc-4.0
3
  library_name: pytorch
4
+ pipeline_tag: image-segmentation
5
+ datasets:
6
+ - VictorButoi/flexray-data
7
  tags:
8
  - medical-image-segmentation
9
  - x-ray
10
+ - radiograph
11
+ - anatomy
12
  - flexray
13
  ---
14
 
15
+ # FleXray: `flexray-base`
16
 
17
+ - Website and in-browser demo: [victorbutoi.github.io/FleXray](https://victorbutoi.github.io/FleXray/)
18
+ - Code: [github.com/VictorButoi/FleXray](https://github.com/VictorButoi/FleXray)
19
+ - Data: [`VictorButoi/flexray-data`](https://huggingface.co/datasets/VictorButoi/flexray-data)
20
+ - Tutorial: [Colab notebook](https://colab.research.google.com/drive/1MNIeN9LN-tY8wAifWSolxmFZi3Q0BlVX)
21
+ - Paper: *FleXray: Flexible Full-Body X-ray Segmentation* (coming soon)
22
 
23
+ `flexray-base` is the **flagship FleXray model**: a single 2D UNet that segments
24
+ anatomy from standard radiographs across body regions, projections, and
25
+ acquisition settings. It predicts 60 anatomical structures (plus background) as
26
+ independent sigmoid channels at 256 x 256 resolution and is the default bundle
27
+ loaded by `flexify` and `FleXraySegmenter.from_pretrained`.
28
 
29
+ It is also one member of a five-model ensemble; see
30
+ [The FleXray ensemble](#the-flexray-ensemble) for the other four and
31
+ [Test-time augmentation](#test-time-augmentation) for the inference recipe we
32
+ use for reported results.
33
 
34
+ ## Quick start
35
 
36
+ ```bash
37
+ python -m pip install flexray
38
+ flexify --input ./image.png --output-dir ./predictions
39
+ ```
40
+
41
+ ```python
42
+ from fxr.inference import FleXraySegmenter
43
+
44
+ segmenter = FleXraySegmenter.from_pretrained("VictorButoi/flexray-base")
45
+ prediction = segmenter.predict("./image.png", threshold=0.5)
46
+ prediction.masks # uint8, CxHxW thresholded masks
47
+ prediction.probabilities # float32, CxHxW sigmoid probabilities
48
+ prediction.logits # float32, CxHxW raw scores
49
+ ```
50
+
51
+ `flexify` writes `<name>_masks.npy`, `<name>_probabilities.npy`, and
52
+ `<name>_logits.npy` per image. Channel order follows `label_schema.json`.
53
+ Pass `--binary LABEL` (for example `--binary femurs`) to write one label. See
54
+ [docs/inference.md](https://github.com/VictorButoi/FleXray/blob/main/docs/inference.md)
55
+ for the full CLI and Python API.
56
+
57
+ ## The FleXray ensemble
58
+
59
+ The flagship was trained with a 0.375 FluXray proportion in the training mix.
60
+ Four sibling models share its architecture, label schema, preprocessing, and
61
+ training recipe and differ only in that proportion:
62
+
63
+ | Model ID | FluXray proportion | Role |
64
+ | --- | --- | --- |
65
+ | `VictorButoi/flexray-base-flux000` | 0.0 | ensemble member |
66
+ | `VictorButoi/flexray-base-flux025` | 0.25 | ensemble member |
67
+ | **`VictorButoi/flexray-base`** | **0.375** | **flagship (this repository)** |
68
+ | `VictorButoi/flexray-base-flux050` | 0.5 | ensemble member |
69
+ | `VictorButoi/flexray-base-flux075` | 0.75 | ensemble member |
70
+
71
+ Because the members share one output space, any subset can be averaged in
72
+ probability space:
73
+
74
+ ```bash
75
+ flexify --model-id VictorButoi/flexray-base \
76
+ --model-id VictorButoi/flexray-base-flux000 \
77
+ --model-id VictorButoi/flexray-base-flux025 \
78
+ --model-id VictorButoi/flexray-base-flux050 \
79
+ --model-id VictorButoi/flexray-base-flux075 \
80
+ --tta-samples 16 --input ./image.png --output-dir ./predictions
81
+ ```
82
+
83
+ ```python
84
+ segmenter = FleXraySegmenter.from_pretrained([
85
+ "VictorButoi/flexray-base",
86
+ "VictorButoi/flexray-base-flux000",
87
+ "VictorButoi/flexray-base-flux025",
88
+ "VictorButoi/flexray-base-flux050",
89
+ "VictorButoi/flexray-base-flux075",
90
+ ])
91
+ prediction = segmenter.predict("./image.png", tta_samples=16)
92
+ ```
93
+
94
+ The website demo exposes the same choices as quality modes: **Low** runs the
95
+ flagship once, **Normal** runs the flagship with 16-pass TTA, **High** runs the
96
+ five-model ensemble once, and **X-High** runs the ensemble with 16-pass TTA.
97
+ Release status of each member is tracked in
98
+ [MODEL_ZOO.md](https://github.com/VictorButoi/FleXray/blob/main/MODEL_ZOO.md).
99
+
100
+ ## Test-time augmentation
101
+
102
+ We typically run FleXray with test-time augmentation (TTA) rather than a single
103
+ forward pass; `--tta-samples 16` (or `predict(..., tta_samples=16)`) is the
104
+ setting behind reported results and the demo's Normal / X-High modes.
105
+
106
+ `tta_samples=N` runs one un-augmented pass plus `N - 1` randomly augmented
107
+ passes and averages them in probability space (mean of sigmoid outputs, then
108
+ converted back to logits). The augmentation chain is fixed in
109
+ [`fxr.inference.tta`](https://github.com/VictorButoi/FleXray/blob/main/src/fxr/inference/tta.py)
110
+ and the browser demo mirrors it exactly:
111
+
112
+ | Transform | Probability | Range |
113
+ | --- | --- | --- |
114
+ | Horizontal flip (exactly inverted on the logits before merging) | 0.5 | - |
115
+ | Gamma | 0.5 | gamma 0.9-1.1, gain 0.9-1.1 |
116
+ | Intensity scale (additive) | 0.5 | -0.1 to 0.1 |
117
+ | Brightness | 0.5 | 0.8-1.2 |
118
+ | Sharpness | 0.5 | 0.6-1.4 |
119
+ | Invert | 0.5 | - |
120
+ | Contrast | 0.5 | 0.7-1.3 |
121
+
122
+ The flip is the only geometric transform; intensity transforms do not move
123
+ pixels and are not inverted. Augmented views are drawn from the global torch
124
+ RNG (`torch.manual_seed` for reproducibility). With an ensemble, every view is
125
+ drawn once and run through every member, so `M` members with `tta_samples=N`
126
+ cost `M x N` forward passes (80 for the full ensemble at N=16). `tta_samples<=1`
127
+ reproduces the plain single pass.
128
+
129
+ ## Input contract
130
+
131
+ `preprocessing.json` is applied automatically by the public loaders:
132
+
133
+ - grayscale input (RGB is converted), any 8-bit or 16-bit PNG / JPEG / TIFF / BMP
134
+ - per-image percentile min-max normalization to `[0, 1]` (0.5th / 99.5th
135
+ percentiles, `eps = 1e-8`)
136
+ - zero-pad to a square, then resize to 256 x 256
137
+ - outputs are `multilabel` sigmoid probabilities; masks use threshold 0.5
138
+
139
+ Outputs are at the 256 x 256 model resolution; the CLI and Python API do not
140
+ resample back to the original image size.
141
+
142
+ ## Output labels
143
+
144
+ 61 channels: `background` at index 0, then 60 anatomical structures in the
145
+ order stored in `label_schema.json` (protocol `all_structures_flexray_v4`):
146
+
147
+ - **Skull / shoulder girdle:** skull, scapulae, clavicles
148
+ - **Upper limb:** humeri, radii, ulnae, carpals, metacarpals, phalanges
149
+ - **Lower limb:** femurs, patellae, tibiae, fibulae, tarsals, metatarsals, toes
150
+ - **Thorax:** rib_1 - rib_12, sternum
151
+ - **Spine:** vertebra_c1 - c7, t1 - t12, l1 - l5, sacrum
152
+ - **Pelvis:** hips
153
+ - **Soft tissue:** lungs, heart, liver, spleen, kidneys
154
+
155
+ Paired structures are merged (for example `femurs` covers both sides);
156
+ laterality is not predicted.
157
+
158
+ ## Architecture
159
+
160
+ `fxr.models.UNet`, 2D, 1 input channel, 61 output channels; filters
161
+ `[64, 128, 256, 512, 512, 720, 1024]`, 3 convolutions per block, residual
162
+ blocks with instance norm, `align_corners=True` upsampling. The full
163
+ architecture is in `config.yml`.
164
+
165
+ ## Training data
166
+
167
+ The model was trained on three source types unified under the FleXray label
168
+ protocol (mixing proportions in parentheses):
169
+
170
+ - **Real X-ray masks:** HandBones (0.01), FootBones (0.01), MURA forearm
171
+ (0.01) and MURA humerus (0.01) with our own annotations.
172
+ - **Generated FluXray images (0.375):** digitally reconstructed radiographs from
173
+ the MOOSE CTs, generatively edited toward real X-ray appearance, with exact
174
+ overlapping masks for every protocol structure.
175
+ - **Online CT->DRR rendering:** MOOSE / ENHANCE-PET 1.6k (0.375), Shoulder-CT
176
+ (0.05), HaN-Seg (0.05), PedsCT (0.04), RSNA cervical-spine fracture CTs
177
+ (0.04), and ElbowCT (0.03), rendered to DRRs at random poses during training
178
+ with per-label attenuation jitter.
179
+
180
+ Training used AdamW (lr 3e-4, cosine schedule), a Dice + binary cross-entropy
181
+ loss routed per dataset (partially labeled sources ignore unlabeled channels),
182
+ and separate augmentation presets for CT-derived and X-ray inputs. The exact
183
+ recipe is `fxr/configs/training/base.yml` in the code release.
184
+
185
+ Every dataset's license, redistribution status, and download pointer is
186
+ documented in the
187
+ [`VictorButoi/flexray-data`](https://huggingface.co/datasets/VictorButoi/flexray-data)
188
+ card. That repository ships the real X-ray sources whose licenses permit
189
+ redistribution, already packed in the FleXray protocol, plus the MURA masks;
190
+ the FluXray database is released alongside it.
191
 
192
  ## Evaluation
193
 
194
+ FleXray was evaluated on nine real-radiograph datasets held out from training
195
+ (ElbowLat, HipRay, LowerLimbs, MendeleyCXR, MTDDH, DarwinCVD19, DeepFluoro,
196
+ RAM-W600, VinDr-Rib), spanning lungs, ribs, peripheral bones, spine, and
197
+ pelvis. Against generalist baselines (FluoroSAM, TotalSegmentator2D, PAXray)
198
+ it achieves the highest macro Dice in every comparison (9 of 9). Per-dataset
199
+ numbers and confidence intervals are in the paper; the benchmark figure is on
200
+ the [project website](https://victorbutoi.github.io/FleXray/#results).
201
+ Evaluation ignores ground-truth labels covering less than 0.1% of the image.
202
+
203
+ ## Intended use and limitations
204
+
205
+ Research use only. FleXray is **not a medical device** and is not cleared for
206
+ clinical diagnosis, treatment planning, or patient-care decisions.
207
+
208
+ - Targets conventional radiographs; dental and mammographic images are out of
209
+ scope.
210
+ - Predicts anatomy, not pathology.
211
+ - No laterality (left/right) and no uncertainty estimates.
212
+ - Performance on acquisition settings, views, or populations far from the
213
+ training sources has not been validated.
214
 
215
  ## Files
216
 
217
  - `model.safetensors`: exported model weights.
218
+ - `config.yml`: architecture and protocol config consumed by `from_pretrained`.
219
  - `label_schema.json`: ordered output labels.
220
  - `preprocessing.json`: public preprocessing contract.
221
+ - `checksums.json`: SHA256 checksums of the bundle files.
222
+ - `onnx/flexray-base-256-fp16.onnx`: fp16 ONNX export (opset 18, sigmoid
223
+ baked in) used by the in-browser demo; parity-checked against the PyTorch
224
+ weights by `tools/export_web_demo.py`.
225
 
226
  ## Licenses
227
 
228
+ - Code: MIT
229
+ - Weights: CC-BY-NC-4.0
 
230
 
231
  ## Citation
232
 
233
+ ```bibtex
234
+ @software{butoi2026flexray,
235
+ title = {FleXray: Flexible Full-Body X-ray Segmentation},
236
+ author = {Butoi, Victor Ion and Gopalakrishnan, Vivek and
237
+ Guttag, John V. and Dalca, Adrian V. and Dey, Neel},
238
+ year = {2026},
239
+ license = {MIT},
240
+ url = {https://github.com/VictorButoi/FleXray}
241
+ }
242
+ ```
243
+
244
+ Please also cite the source datasets listed in the
245
+ [`flexray-data`](https://huggingface.co/datasets/VictorButoi/flexray-data) card
246
+ for any dataset you use.
checksums.json CHANGED
@@ -1,7 +1,7 @@
1
  {
2
  "algorithm": "sha256",
3
  "files": {
4
- "README.md": "59f705f7ab0923400d9b89bbfb91527e61e39883ab31655e44d6be017e3a00ef",
5
  "config.yml": "7c7d52b2404d5e3cb5347036feac994ab8b8a18dd6bef5cfa47b749077af727a",
6
  "label_schema.json": "c8fa61b6585fc4043e2c51ba1f53271f9313cdae8d812479449b8a2a0ba12d7a",
7
  "model.safetensors": "716ce3a8fb2a6abe22b2f2188fd596ddc4642b273fb0d336d629448154fc6d24",
 
1
  {
2
  "algorithm": "sha256",
3
  "files": {
4
+ "README.md": "e6e5c17b8ece40c296e1fd40d92774a44d6bb6fb1e5452b94f00533ebddf694f",
5
  "config.yml": "7c7d52b2404d5e3cb5347036feac994ab8b8a18dd6bef5cfa47b749077af727a",
6
  "label_schema.json": "c8fa61b6585fc4043e2c51ba1f53271f9313cdae8d812479449b8a2a0ba12d7a",
7
  "model.safetensors": "716ce3a8fb2a6abe22b2f2188fd596ddc4642b273fb0d336d629448154fc6d24",