caideface 0.3.1__tar.gz → 0.3.3__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.
- {caideface-0.3.1 → caideface-0.3.3}/PKG-INFO +63 -20
- {caideface-0.3.1 → caideface-0.3.3}/README.md +62 -19
- {caideface-0.3.1 → caideface-0.3.3}/pyproject.toml +1 -1
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/__init__.py +1 -1
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/cli.py +2 -3
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/data/ct_face_mask.nii.gz +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/pipeline.py +2 -3
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/reorient.py +12 -22
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/skull_strip.py +17 -7
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface.egg-info/PKG-INFO +63 -20
- {caideface-0.3.1 → caideface-0.3.3}/tests/test_reorient.py +5 -5
- {caideface-0.3.1 → caideface-0.3.3}/setup.cfg +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/anonymize.py +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/background.py +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/data/mni_icbm152_t1_tal_nlin_sym_55_ext_brain_only.nii.gz +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/data/ner_model/config.cfg +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/data/ner_model/meta.json +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/data/ner_model/ner/cfg +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/data/ner_model/ner/model +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/data/ner_model/ner/moves +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/data/ner_model/tok2vec/cfg +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/data/ner_model/tok2vec/model +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/data/ner_model/tokenizer +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/data/ner_model/vocab/key2row +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/data/ner_model/vocab/lookups.bin +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/data/ner_model/vocab/strings.json +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/data/ner_model/vocab/vectors +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/data/ner_model/vocab/vectors.cfg +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/data/t1_mask.nii.gz +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface/register.py +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface.egg-info/SOURCES.txt +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface.egg-info/dependency_links.txt +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface.egg-info/entry_points.txt +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface.egg-info/requires.txt +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/src/caideface.egg-info/top_level.txt +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/tests/test_anonymize.py +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/tests/test_background.py +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/tests/test_register.py +0 -0
- {caideface-0.3.1 → caideface-0.3.3}/tests/test_skull_strip.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: caideface
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: MRI defacing pipeline with skull-stripping and affine registration from cai4cai
|
|
5
5
|
Author-email: Lorena Garcia-Foncillas <lorenagarfon00@gmail.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -31,28 +31,35 @@ Requires-Dist: TotalSegmentator; extra == "ct"
|
|
|
31
31
|
|
|
32
32
|
# caideface
|
|
33
33
|
|
|
34
|
-
**MRI defacing and text anonymisation toolkit** from the [cai4cai](https://cai4cai.ml/) research group (Contextual Artificial Intelligence for Computer Assisted Interventions).
|
|
34
|
+
**MRI and CT defacing and text anonymisation toolkit** from the [cai4cai](https://cai4cai.ml/) research group (Contextual Artificial Intelligence for Computer Assisted Interventions).
|
|
35
35
|
|
|
36
36
|
This package provides two complementary anonymisation capabilities:
|
|
37
37
|
|
|
38
|
-
- **Image defacing** -- removes facial features from head MRI scans while preserving brain structures
|
|
39
|
-
- **Text anonymisation** -- detects personal names in medical reports using a trained spaCy NER model and replaces them with realistic fake names (Hiding in Plain Sight / HIPS technique).
|
|
38
|
+
- **Image defacing** -- removes facial features from head MRI and CT scans while preserving brain structures. The MRI pipeline is described in the paper *"A Generalisable Head MRI Defacing Pipeline: Evaluation on 2,566 Meningioma Scans"* ([arXiv:2505.12999](https://arxiv.org/abs/2505.12999)).
|
|
39
|
+
- **Text anonymisation** -- detects personal names in medical reports using a trained spaCy NER model and replaces them with realistic fake names (Hiding in Plain Sight / HIPS technique), as described in *"Evaluation of Named Entity Recognition for Automated Extraction of Present Tumor Size and Personal Names from Radiology Reports Using Spacy"* ([DOI:10.1055/s-0045-1803715](https://doi.org/10.1055/s-0045-1803715)).
|
|
40
40
|
|
|
41
41
|
## Pipeline overview
|
|
42
42
|
|
|
43
43
|
### Image defacing pipeline
|
|
44
44
|
|
|
45
|
-
The defacing pipeline consists of three steps:
|
|
45
|
+
The defacing pipeline supports both **MRI** and **CT** modalities, selected via the required `--modality {mri,ct}` flag. The pipeline consists of three steps, with modality-specific backends:
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
| Step | MRI | CT |
|
|
48
|
+
|------|-----|-----|
|
|
49
|
+
| 1. Reorientation | → RAS | → RAS |
|
|
50
|
+
| 2. Brain extraction | [HD-BET](https://github.com/MIC-DKFZ/HD-BET) | [TotalSegmentator](https://github.com/wasserth/TotalSegmentator) |
|
|
51
|
+
| 3. Registration template | MNI152 T1 (bundled) | CT brain atlas (from TotalSegmentator) |
|
|
52
|
+
| Background value | Always 0 | Auto-detected per volume |
|
|
53
|
+
|
|
54
|
+
1. **Reorientation** -- Aligns NIfTI scans to RAS canonical orientation (MNI152 standard) using nibabel, equivalent to FSL's `fslreorient2std`.
|
|
55
|
+
2. **Skull-stripping** -- Extracts brain masks, then applies dynamic dilation to preserve peripheral brain structures. MRI uses [HD-BET](https://github.com/MIC-DKFZ/HD-BET); CT uses [TotalSegmentator](https://github.com/wasserth/TotalSegmentator) (brain class from the total segmentation task).
|
|
56
|
+
3. **Registration & Defacing** -- Registers each scan to a modality-matched template using BRAINSFit (affine), warps a face mask into the scan's space, and applies it to remove facial features. For CT, the background fill value is automatically detected from the volume histogram (~-1000 HU for native encoding).
|
|
50
57
|
|
|
51
58
|
### Text anonymisation (NER + HIPS)
|
|
52
59
|
|
|
53
60
|
The text anonymisation module uses a trained spaCy Named Entity Recognition (NER) model to identify personal names (`PER` entities) in `.txt` files and replaces them with realistic fake names generated by the [Faker](https://faker.readthedocs.io/) library. This "Hiding in Plain Sight" (HIPS) approach produces anonymised reports that remain naturally readable. Consistent name mapping ensures that the same real name is always replaced with the same fake name within a document.
|
|
54
61
|
|
|
55
|
-
All required models and data are **bundled with the package
|
|
62
|
+
All required models and data for MRI defacing and text anonymisation are **bundled with the package**. CT defacing requires installing the optional `[ct]` extra (see [Installation](#installation)).
|
|
56
63
|
|
|
57
64
|
## Requirements
|
|
58
65
|
|
|
@@ -66,7 +73,7 @@ All required models and data are **bundled with the package**, so no additional
|
|
|
66
73
|
|------|---------|---------|
|
|
67
74
|
| **BRAINSFit** & **BRAINSResample** | Step 3 | Bundled with [3D Slicer](https://www.slicer.org/) |
|
|
68
75
|
|
|
69
|
-
> **Note:** Step 1 (reorientation) no longer requires FSL -- it uses nibabel's orientation tools to reorient scans to
|
|
76
|
+
> **Note:** Step 1 (reorientation) no longer requires FSL -- it uses nibabel's orientation tools to reorient scans to RAS (equivalent to `fslreorient2std`).
|
|
70
77
|
|
|
71
78
|
#### Finding BRAINSFit and BRAINSResample
|
|
72
79
|
|
|
@@ -96,13 +103,21 @@ We recommend using a conda environment:
|
|
|
96
103
|
```bash
|
|
97
104
|
conda create -n caideface python=3.10 -y
|
|
98
105
|
conda activate caideface
|
|
106
|
+
|
|
107
|
+
# MRI defacing only
|
|
99
108
|
pip install caideface
|
|
109
|
+
|
|
110
|
+
# MRI + CT defacing (includes TotalSegmentator)
|
|
111
|
+
pip install caideface[ct]
|
|
100
112
|
```
|
|
101
113
|
|
|
102
114
|
Or install from GitHub:
|
|
103
115
|
|
|
104
116
|
```bash
|
|
105
117
|
pip install "caideface @ git+https://github.com/cai4cai/defacing_pipeline.git#subdirectory=caideface"
|
|
118
|
+
|
|
119
|
+
# With CT support
|
|
120
|
+
pip install "caideface[ct] @ git+https://github.com/cai4cai/defacing_pipeline.git#subdirectory=caideface"
|
|
106
121
|
```
|
|
107
122
|
|
|
108
123
|
Or install from source:
|
|
@@ -110,10 +125,13 @@ Or install from source:
|
|
|
110
125
|
```bash
|
|
111
126
|
git clone https://github.com/cai4cai/defacing_pipeline.git
|
|
112
127
|
cd defacing_pipeline/caideface
|
|
113
|
-
pip install -e .
|
|
128
|
+
pip install -e . # MRI only
|
|
129
|
+
pip install -e ".[ct]" # MRI + CT
|
|
114
130
|
```
|
|
115
131
|
|
|
116
132
|
> **Note:** caideface requires `numpy<2` (enforced automatically). Some dependencies (HD-BET / nnU-Net) are not yet compatible with NumPy 2.x.
|
|
133
|
+
>
|
|
134
|
+
> **Note:** CT support requires [TotalSegmentator](https://github.com/wasserth/TotalSegmentator), which downloads model weights (~1.5 GB) on first use to `~/.totalsegmentator/`. All inference runs locally -- no scan data is sent externally.
|
|
117
135
|
|
|
118
136
|
## Usage
|
|
119
137
|
|
|
@@ -122,7 +140,15 @@ pip install -e .
|
|
|
122
140
|
Run all three steps in one command:
|
|
123
141
|
|
|
124
142
|
```bash
|
|
143
|
+
# MRI
|
|
125
144
|
caideface run ./input_nifti ./output \
|
|
145
|
+
--modality mri \
|
|
146
|
+
--brainsfit /path/to/BRAINSFit \
|
|
147
|
+
--brainsresample /path/to/BRAINSResample
|
|
148
|
+
|
|
149
|
+
# CT
|
|
150
|
+
caideface run ./input_nifti ./output \
|
|
151
|
+
--modality ct \
|
|
126
152
|
--brainsfit /path/to/BRAINSFit \
|
|
127
153
|
--brainsresample /path/to/BRAINSResample
|
|
128
154
|
```
|
|
@@ -136,12 +162,13 @@ This creates three subdirectories under `./output`:
|
|
|
136
162
|
|
|
137
163
|
| Flag | Default | Description |
|
|
138
164
|
|------|---------|-------------|
|
|
139
|
-
| `--
|
|
140
|
-
| `--
|
|
165
|
+
| `--modality` | *required* | Image modality: `mri` or `ct` |
|
|
166
|
+
| `--device` | auto-detected | `cpu` or `cuda` for brain extraction |
|
|
167
|
+
| `--no-tta` | on | Disable HD-BET test-time augmentation (MRI only) |
|
|
141
168
|
| `--dilation-mm` | `14.0` | Brain mask dilation in mm |
|
|
142
|
-
| `--background` |
|
|
143
|
-
| `--template` | bundled | Custom
|
|
144
|
-
| `--face-mask` | bundled | Custom face mask in
|
|
169
|
+
| `--background` | auto-detected | Background fill value (auto-detected per volume; override with explicit value) |
|
|
170
|
+
| `--template` | bundled | Custom skull-stripped template |
|
|
171
|
+
| `--face-mask` | bundled | Custom face mask in template space |
|
|
145
172
|
| `--steps` | `all` | Run specific steps: `reorient`, `skull_strip`, `deface` (comma-separated) |
|
|
146
173
|
| `-v` | off | Verbose/debug logging |
|
|
147
174
|
|
|
@@ -151,13 +178,14 @@ Run each step separately for more control:
|
|
|
151
178
|
|
|
152
179
|
```bash
|
|
153
180
|
# Step 1: Reorientation
|
|
154
|
-
caideface reorient ./raw_nifti ./reoriented
|
|
181
|
+
caideface reorient ./raw_nifti ./reoriented --modality mri
|
|
155
182
|
|
|
156
183
|
# Step 2: Skull-stripping
|
|
157
|
-
caideface skull-strip ./reoriented ./hdbet --device cpu
|
|
184
|
+
caideface skull-strip ./reoriented ./hdbet --modality mri --device cpu
|
|
158
185
|
|
|
159
186
|
# Step 3: Registration & Defacing
|
|
160
187
|
caideface deface ./reoriented ./hdbet ./defaced \
|
|
188
|
+
--modality mri \
|
|
161
189
|
--brainsfit /path/to/BRAINSFit \
|
|
162
190
|
--brainsresample /path/to/BRAINSResample
|
|
163
191
|
```
|
|
@@ -249,6 +277,7 @@ from caideface import (
|
|
|
249
277
|
anonymize_batch, # Text anonymisation (batch)
|
|
250
278
|
anonymize_single, # Text anonymisation (single file)
|
|
251
279
|
default_ner_model_path, # Path to bundled NER model
|
|
280
|
+
detect_background_value, # CT/MRI background detection
|
|
252
281
|
)
|
|
253
282
|
```
|
|
254
283
|
|
|
@@ -299,7 +328,21 @@ If you use this tool, please cite:
|
|
|
299
328
|
}
|
|
300
329
|
```
|
|
301
330
|
|
|
302
|
-
If you use
|
|
331
|
+
If you use CT defacing (TotalSegmentator, Step 2), please also cite:
|
|
332
|
+
|
|
333
|
+
```bibtex
|
|
334
|
+
@article{Wasserthal2023,
|
|
335
|
+
author={Wasserthal, Jakob and Breit, Hanns-Christian and Meyer, Manfred T. and Pradella, Maurice and Hinck, Daniel and Sauter, Alexander W. and Heye, Tobias and Boll, Daniel T. and Cyriac, Joshy and Yang, Shan and Bach, Michael and Segeroth, Martin},
|
|
336
|
+
title={TotalSegmentator: Robust Segmentation of 104 Anatomic Structures in CT Images},
|
|
337
|
+
journal={Radiology: Artificial Intelligence},
|
|
338
|
+
volume={5},
|
|
339
|
+
number={5},
|
|
340
|
+
year={2023},
|
|
341
|
+
doi={10.1148/ryai.230024}
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
If you use HD-BET (MRI skull-stripping, Step 2), please also cite:
|
|
303
346
|
|
|
304
347
|
```bibtex
|
|
305
348
|
@article{Isensee2019,
|
|
@@ -330,4 +373,4 @@ If you use the text anonymisation (NER + HIPS), please also cite:
|
|
|
330
373
|
|
|
331
374
|
## License
|
|
332
375
|
|
|
333
|
-
This project is licensed under the Apache License 2.0 -- see the [LICENSE](
|
|
376
|
+
This project is licensed under the Apache License 2.0 -- see the [LICENSE](https://github.com/cai4cai/defacing_pipeline/blob/main/LICENSE) file for details.
|
|
@@ -1,27 +1,34 @@
|
|
|
1
1
|
# caideface
|
|
2
2
|
|
|
3
|
-
**MRI defacing and text anonymisation toolkit** from the [cai4cai](https://cai4cai.ml/) research group (Contextual Artificial Intelligence for Computer Assisted Interventions).
|
|
3
|
+
**MRI and CT defacing and text anonymisation toolkit** from the [cai4cai](https://cai4cai.ml/) research group (Contextual Artificial Intelligence for Computer Assisted Interventions).
|
|
4
4
|
|
|
5
5
|
This package provides two complementary anonymisation capabilities:
|
|
6
6
|
|
|
7
|
-
- **Image defacing** -- removes facial features from head MRI scans while preserving brain structures
|
|
8
|
-
- **Text anonymisation** -- detects personal names in medical reports using a trained spaCy NER model and replaces them with realistic fake names (Hiding in Plain Sight / HIPS technique).
|
|
7
|
+
- **Image defacing** -- removes facial features from head MRI and CT scans while preserving brain structures. The MRI pipeline is described in the paper *"A Generalisable Head MRI Defacing Pipeline: Evaluation on 2,566 Meningioma Scans"* ([arXiv:2505.12999](https://arxiv.org/abs/2505.12999)).
|
|
8
|
+
- **Text anonymisation** -- detects personal names in medical reports using a trained spaCy NER model and replaces them with realistic fake names (Hiding in Plain Sight / HIPS technique), as described in *"Evaluation of Named Entity Recognition for Automated Extraction of Present Tumor Size and Personal Names from Radiology Reports Using Spacy"* ([DOI:10.1055/s-0045-1803715](https://doi.org/10.1055/s-0045-1803715)).
|
|
9
9
|
|
|
10
10
|
## Pipeline overview
|
|
11
11
|
|
|
12
12
|
### Image defacing pipeline
|
|
13
13
|
|
|
14
|
-
The defacing pipeline consists of three steps:
|
|
14
|
+
The defacing pipeline supports both **MRI** and **CT** modalities, selected via the required `--modality {mri,ct}` flag. The pipeline consists of three steps, with modality-specific backends:
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
| Step | MRI | CT |
|
|
17
|
+
|------|-----|-----|
|
|
18
|
+
| 1. Reorientation | → RAS | → RAS |
|
|
19
|
+
| 2. Brain extraction | [HD-BET](https://github.com/MIC-DKFZ/HD-BET) | [TotalSegmentator](https://github.com/wasserth/TotalSegmentator) |
|
|
20
|
+
| 3. Registration template | MNI152 T1 (bundled) | CT brain atlas (from TotalSegmentator) |
|
|
21
|
+
| Background value | Always 0 | Auto-detected per volume |
|
|
22
|
+
|
|
23
|
+
1. **Reorientation** -- Aligns NIfTI scans to RAS canonical orientation (MNI152 standard) using nibabel, equivalent to FSL's `fslreorient2std`.
|
|
24
|
+
2. **Skull-stripping** -- Extracts brain masks, then applies dynamic dilation to preserve peripheral brain structures. MRI uses [HD-BET](https://github.com/MIC-DKFZ/HD-BET); CT uses [TotalSegmentator](https://github.com/wasserth/TotalSegmentator) (brain class from the total segmentation task).
|
|
25
|
+
3. **Registration & Defacing** -- Registers each scan to a modality-matched template using BRAINSFit (affine), warps a face mask into the scan's space, and applies it to remove facial features. For CT, the background fill value is automatically detected from the volume histogram (~-1000 HU for native encoding).
|
|
19
26
|
|
|
20
27
|
### Text anonymisation (NER + HIPS)
|
|
21
28
|
|
|
22
29
|
The text anonymisation module uses a trained spaCy Named Entity Recognition (NER) model to identify personal names (`PER` entities) in `.txt` files and replaces them with realistic fake names generated by the [Faker](https://faker.readthedocs.io/) library. This "Hiding in Plain Sight" (HIPS) approach produces anonymised reports that remain naturally readable. Consistent name mapping ensures that the same real name is always replaced with the same fake name within a document.
|
|
23
30
|
|
|
24
|
-
All required models and data are **bundled with the package
|
|
31
|
+
All required models and data for MRI defacing and text anonymisation are **bundled with the package**. CT defacing requires installing the optional `[ct]` extra (see [Installation](#installation)).
|
|
25
32
|
|
|
26
33
|
## Requirements
|
|
27
34
|
|
|
@@ -35,7 +42,7 @@ All required models and data are **bundled with the package**, so no additional
|
|
|
35
42
|
|------|---------|---------|
|
|
36
43
|
| **BRAINSFit** & **BRAINSResample** | Step 3 | Bundled with [3D Slicer](https://www.slicer.org/) |
|
|
37
44
|
|
|
38
|
-
> **Note:** Step 1 (reorientation) no longer requires FSL -- it uses nibabel's orientation tools to reorient scans to
|
|
45
|
+
> **Note:** Step 1 (reorientation) no longer requires FSL -- it uses nibabel's orientation tools to reorient scans to RAS (equivalent to `fslreorient2std`).
|
|
39
46
|
|
|
40
47
|
#### Finding BRAINSFit and BRAINSResample
|
|
41
48
|
|
|
@@ -65,13 +72,21 @@ We recommend using a conda environment:
|
|
|
65
72
|
```bash
|
|
66
73
|
conda create -n caideface python=3.10 -y
|
|
67
74
|
conda activate caideface
|
|
75
|
+
|
|
76
|
+
# MRI defacing only
|
|
68
77
|
pip install caideface
|
|
78
|
+
|
|
79
|
+
# MRI + CT defacing (includes TotalSegmentator)
|
|
80
|
+
pip install caideface[ct]
|
|
69
81
|
```
|
|
70
82
|
|
|
71
83
|
Or install from GitHub:
|
|
72
84
|
|
|
73
85
|
```bash
|
|
74
86
|
pip install "caideface @ git+https://github.com/cai4cai/defacing_pipeline.git#subdirectory=caideface"
|
|
87
|
+
|
|
88
|
+
# With CT support
|
|
89
|
+
pip install "caideface[ct] @ git+https://github.com/cai4cai/defacing_pipeline.git#subdirectory=caideface"
|
|
75
90
|
```
|
|
76
91
|
|
|
77
92
|
Or install from source:
|
|
@@ -79,10 +94,13 @@ Or install from source:
|
|
|
79
94
|
```bash
|
|
80
95
|
git clone https://github.com/cai4cai/defacing_pipeline.git
|
|
81
96
|
cd defacing_pipeline/caideface
|
|
82
|
-
pip install -e .
|
|
97
|
+
pip install -e . # MRI only
|
|
98
|
+
pip install -e ".[ct]" # MRI + CT
|
|
83
99
|
```
|
|
84
100
|
|
|
85
101
|
> **Note:** caideface requires `numpy<2` (enforced automatically). Some dependencies (HD-BET / nnU-Net) are not yet compatible with NumPy 2.x.
|
|
102
|
+
>
|
|
103
|
+
> **Note:** CT support requires [TotalSegmentator](https://github.com/wasserth/TotalSegmentator), which downloads model weights (~1.5 GB) on first use to `~/.totalsegmentator/`. All inference runs locally -- no scan data is sent externally.
|
|
86
104
|
|
|
87
105
|
## Usage
|
|
88
106
|
|
|
@@ -91,7 +109,15 @@ pip install -e .
|
|
|
91
109
|
Run all three steps in one command:
|
|
92
110
|
|
|
93
111
|
```bash
|
|
112
|
+
# MRI
|
|
94
113
|
caideface run ./input_nifti ./output \
|
|
114
|
+
--modality mri \
|
|
115
|
+
--brainsfit /path/to/BRAINSFit \
|
|
116
|
+
--brainsresample /path/to/BRAINSResample
|
|
117
|
+
|
|
118
|
+
# CT
|
|
119
|
+
caideface run ./input_nifti ./output \
|
|
120
|
+
--modality ct \
|
|
95
121
|
--brainsfit /path/to/BRAINSFit \
|
|
96
122
|
--brainsresample /path/to/BRAINSResample
|
|
97
123
|
```
|
|
@@ -105,12 +131,13 @@ This creates three subdirectories under `./output`:
|
|
|
105
131
|
|
|
106
132
|
| Flag | Default | Description |
|
|
107
133
|
|------|---------|-------------|
|
|
108
|
-
| `--
|
|
109
|
-
| `--
|
|
134
|
+
| `--modality` | *required* | Image modality: `mri` or `ct` |
|
|
135
|
+
| `--device` | auto-detected | `cpu` or `cuda` for brain extraction |
|
|
136
|
+
| `--no-tta` | on | Disable HD-BET test-time augmentation (MRI only) |
|
|
110
137
|
| `--dilation-mm` | `14.0` | Brain mask dilation in mm |
|
|
111
|
-
| `--background` |
|
|
112
|
-
| `--template` | bundled | Custom
|
|
113
|
-
| `--face-mask` | bundled | Custom face mask in
|
|
138
|
+
| `--background` | auto-detected | Background fill value (auto-detected per volume; override with explicit value) |
|
|
139
|
+
| `--template` | bundled | Custom skull-stripped template |
|
|
140
|
+
| `--face-mask` | bundled | Custom face mask in template space |
|
|
114
141
|
| `--steps` | `all` | Run specific steps: `reorient`, `skull_strip`, `deface` (comma-separated) |
|
|
115
142
|
| `-v` | off | Verbose/debug logging |
|
|
116
143
|
|
|
@@ -120,13 +147,14 @@ Run each step separately for more control:
|
|
|
120
147
|
|
|
121
148
|
```bash
|
|
122
149
|
# Step 1: Reorientation
|
|
123
|
-
caideface reorient ./raw_nifti ./reoriented
|
|
150
|
+
caideface reorient ./raw_nifti ./reoriented --modality mri
|
|
124
151
|
|
|
125
152
|
# Step 2: Skull-stripping
|
|
126
|
-
caideface skull-strip ./reoriented ./hdbet --device cpu
|
|
153
|
+
caideface skull-strip ./reoriented ./hdbet --modality mri --device cpu
|
|
127
154
|
|
|
128
155
|
# Step 3: Registration & Defacing
|
|
129
156
|
caideface deface ./reoriented ./hdbet ./defaced \
|
|
157
|
+
--modality mri \
|
|
130
158
|
--brainsfit /path/to/BRAINSFit \
|
|
131
159
|
--brainsresample /path/to/BRAINSResample
|
|
132
160
|
```
|
|
@@ -218,6 +246,7 @@ from caideface import (
|
|
|
218
246
|
anonymize_batch, # Text anonymisation (batch)
|
|
219
247
|
anonymize_single, # Text anonymisation (single file)
|
|
220
248
|
default_ner_model_path, # Path to bundled NER model
|
|
249
|
+
detect_background_value, # CT/MRI background detection
|
|
221
250
|
)
|
|
222
251
|
```
|
|
223
252
|
|
|
@@ -268,7 +297,21 @@ If you use this tool, please cite:
|
|
|
268
297
|
}
|
|
269
298
|
```
|
|
270
299
|
|
|
271
|
-
If you use
|
|
300
|
+
If you use CT defacing (TotalSegmentator, Step 2), please also cite:
|
|
301
|
+
|
|
302
|
+
```bibtex
|
|
303
|
+
@article{Wasserthal2023,
|
|
304
|
+
author={Wasserthal, Jakob and Breit, Hanns-Christian and Meyer, Manfred T. and Pradella, Maurice and Hinck, Daniel and Sauter, Alexander W. and Heye, Tobias and Boll, Daniel T. and Cyriac, Joshy and Yang, Shan and Bach, Michael and Segeroth, Martin},
|
|
305
|
+
title={TotalSegmentator: Robust Segmentation of 104 Anatomic Structures in CT Images},
|
|
306
|
+
journal={Radiology: Artificial Intelligence},
|
|
307
|
+
volume={5},
|
|
308
|
+
number={5},
|
|
309
|
+
year={2023},
|
|
310
|
+
doi={10.1148/ryai.230024}
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
If you use HD-BET (MRI skull-stripping, Step 2), please also cite:
|
|
272
315
|
|
|
273
316
|
```bibtex
|
|
274
317
|
@article{Isensee2019,
|
|
@@ -299,4 +342,4 @@ If you use the text anonymisation (NER + HIPS), please also cite:
|
|
|
299
342
|
|
|
300
343
|
## License
|
|
301
344
|
|
|
302
|
-
This project is licensed under the Apache License 2.0 -- see the [LICENSE](
|
|
345
|
+
This project is licensed under the Apache License 2.0 -- see the [LICENSE](https://github.com/cai4cai/defacing_pipeline/blob/main/LICENSE) file for details.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "caideface"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.3"
|
|
8
8
|
description = "MRI defacing pipeline with skull-stripping and affine registration from cai4cai"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "Apache-2.0"}
|
|
@@ -8,7 +8,7 @@ A three-step pipeline for anonymising head MRI scans:
|
|
|
8
8
|
Plus standalone text anonymisation via NER + HIPS (Hiding in Plain Sight).
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
-
__version__ = "0.3.
|
|
11
|
+
__version__ = "0.3.3"
|
|
12
12
|
|
|
13
13
|
from .pipeline import DefacePipeline
|
|
14
14
|
from .reorient import reorient_batch, reorient_single
|
|
@@ -49,10 +49,9 @@ def main():
|
|
|
49
49
|
run_parser.add_argument("--steps", default="all", help="Steps to run: all, or comma-separated: reorient,skull_strip,deface")
|
|
50
50
|
|
|
51
51
|
# --- reorient ---
|
|
52
|
-
reorient_parser = subparsers.add_parser("reorient", help="Step 1: Reorient NIfTI scans", parents=[parent])
|
|
52
|
+
reorient_parser = subparsers.add_parser("reorient", help="Step 1: Reorient NIfTI scans to RAS", parents=[parent])
|
|
53
53
|
reorient_parser.add_argument("input_dir", help="Directory with NIfTI files")
|
|
54
54
|
reorient_parser.add_argument("output_dir", help="Output directory for reoriented files")
|
|
55
|
-
reorient_parser.add_argument("--modality", required=True, choices=["mri", "ct"], help="Image modality (mri→LAS, ct→RAS)")
|
|
56
55
|
|
|
57
56
|
# --- skull-strip ---
|
|
58
57
|
ss_parser = subparsers.add_parser("skull-strip", help="Step 2: Skull-strip with HD-BET", parents=[parent])
|
|
@@ -118,7 +117,7 @@ def main():
|
|
|
118
117
|
sys.exit(1)
|
|
119
118
|
|
|
120
119
|
elif args.command == "reorient":
|
|
121
|
-
reorient_batch(args.input_dir, args.output_dir
|
|
120
|
+
reorient_batch(args.input_dir, args.output_dir)
|
|
122
121
|
|
|
123
122
|
elif args.command == "skull-strip":
|
|
124
123
|
skull_strip_batch(
|
|
Binary file
|
|
@@ -97,10 +97,9 @@ class DefacePipeline:
|
|
|
97
97
|
# Step 1: Reorientation
|
|
98
98
|
if "reorient" in run_steps:
|
|
99
99
|
logger.info("=" * 60)
|
|
100
|
-
|
|
101
|
-
logger.info("STEP 1: Reorientation to %s", target)
|
|
100
|
+
logger.info("STEP 1: Reorientation to RAS")
|
|
102
101
|
logger.info("=" * 60)
|
|
103
|
-
reorient_log = reorient_batch(input_dir, reoriented_dir
|
|
102
|
+
reorient_log = reorient_batch(input_dir, reoriented_dir)
|
|
104
103
|
results["reorient_log"] = reorient_log
|
|
105
104
|
else:
|
|
106
105
|
logger.info("Skipping Step 1 (reorientation)")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Step 1: Reorientation of NIfTI scans using nibabel."""
|
|
1
|
+
"""Step 1: Reorientation of NIfTI scans to RAS using nibabel."""
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
import logging
|
|
@@ -9,18 +9,15 @@ import pandas as pd
|
|
|
9
9
|
|
|
10
10
|
logger = logging.getLogger(__name__)
|
|
11
11
|
|
|
12
|
-
#
|
|
13
|
-
|
|
14
|
-
"mri": ("L", "A", "S"), # LAS — matches fslreorient2std
|
|
15
|
-
"ct": ("R", "A", "S"), # RAS — matches CT brain atlas
|
|
16
|
-
}
|
|
12
|
+
# RAS matches the MNI152 standard, fslreorient2std, HD-BET, and the CT brain atlas.
|
|
13
|
+
TARGET_ORIENTATION = ("R", "A", "S")
|
|
17
14
|
|
|
18
15
|
|
|
19
|
-
def reorient_single(input_file: str, output_file: str
|
|
20
|
-
"""Reorient a single NIfTI file to
|
|
16
|
+
def reorient_single(input_file: str, output_file: str) -> bool:
|
|
17
|
+
"""Reorient a single NIfTI file to RAS orientation.
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
This is equivalent to FSL's ``fslreorient2std`` and matches the
|
|
20
|
+
MNI152 template orientation used by both the MRI and CT pipelines.
|
|
24
21
|
|
|
25
22
|
Parameters
|
|
26
23
|
----------
|
|
@@ -28,8 +25,6 @@ def reorient_single(input_file: str, output_file: str, modality: str = "mri") ->
|
|
|
28
25
|
Path to the input NIfTI (.nii.gz) file.
|
|
29
26
|
output_file : str
|
|
30
27
|
Path where the reoriented file will be saved.
|
|
31
|
-
modality : str
|
|
32
|
-
``'mri'`` (target LAS) or ``'ct'`` (target RAS).
|
|
33
28
|
|
|
34
29
|
Returns
|
|
35
30
|
-------
|
|
@@ -38,12 +33,10 @@ def reorient_single(input_file: str, output_file: str, modality: str = "mri") ->
|
|
|
38
33
|
"""
|
|
39
34
|
os.makedirs(os.path.dirname(output_file), exist_ok=True)
|
|
40
35
|
|
|
41
|
-
target = TARGET_ORIENTATIONS.get(modality, TARGET_ORIENTATIONS["mri"])
|
|
42
|
-
|
|
43
36
|
try:
|
|
44
37
|
img = nib.load(input_file)
|
|
45
38
|
orig_ornt = io_orientation(img.affine)
|
|
46
|
-
target_ornt = axcodes2ornt(
|
|
39
|
+
target_ornt = axcodes2ornt(TARGET_ORIENTATION)
|
|
47
40
|
transform = ornt_transform(orig_ornt, target_ornt)
|
|
48
41
|
reoriented = img.as_reoriented(transform)
|
|
49
42
|
nib.save(reoriented, output_file)
|
|
@@ -54,8 +47,8 @@ def reorient_single(input_file: str, output_file: str, modality: str = "mri") ->
|
|
|
54
47
|
return os.path.exists(output_file)
|
|
55
48
|
|
|
56
49
|
|
|
57
|
-
def reorient_batch(input_dir: str, output_dir: str
|
|
58
|
-
"""Reorient all NIfTI files found recursively under *input_dir
|
|
50
|
+
def reorient_batch(input_dir: str, output_dir: str) -> pd.DataFrame:
|
|
51
|
+
"""Reorient all NIfTI files found recursively under *input_dir* to RAS.
|
|
59
52
|
|
|
60
53
|
The directory structure is mirrored under *output_dir*.
|
|
61
54
|
|
|
@@ -66,8 +59,6 @@ def reorient_batch(input_dir: str, output_dir: str, modality: str = "mri") -> pd
|
|
|
66
59
|
output_dir : str
|
|
67
60
|
Root directory where reoriented files will be saved,
|
|
68
61
|
preserving the subdirectory structure.
|
|
69
|
-
modality : str
|
|
70
|
-
``'mri'`` (target LAS) or ``'ct'`` (target RAS).
|
|
71
62
|
|
|
72
63
|
Returns
|
|
73
64
|
-------
|
|
@@ -77,8 +68,7 @@ def reorient_batch(input_dir: str, output_dir: str, modality: str = "mri") -> pd
|
|
|
77
68
|
input_dir = os.path.abspath(input_dir)
|
|
78
69
|
output_dir = os.path.abspath(output_dir)
|
|
79
70
|
|
|
80
|
-
|
|
81
|
-
logger.info("Target orientation: %s (%s)", "".join(target), modality)
|
|
71
|
+
logger.info("Target orientation: RAS")
|
|
82
72
|
|
|
83
73
|
log_rows = []
|
|
84
74
|
for root, _dirs, files in os.walk(input_dir):
|
|
@@ -91,7 +81,7 @@ def reorient_batch(input_dir: str, output_dir: str, modality: str = "mri") -> pd
|
|
|
91
81
|
out_path = os.path.join(output_dir, rel, fname)
|
|
92
82
|
|
|
93
83
|
logger.info("Reorienting %s", input_path)
|
|
94
|
-
success = reorient_single(input_path, out_path
|
|
84
|
+
success = reorient_single(input_path, out_path)
|
|
95
85
|
log_rows.append({"input": input_path, "output": out_path, "success": success})
|
|
96
86
|
|
|
97
87
|
if success:
|
|
@@ -111,21 +111,31 @@ def _extract_brain_totalseg(
|
|
|
111
111
|
"""
|
|
112
112
|
try:
|
|
113
113
|
from totalsegmentator.python_api import totalsegmentator
|
|
114
|
+
import totalsegmentator.config as _ts_config
|
|
114
115
|
except ImportError:
|
|
115
116
|
raise ImportError(
|
|
116
117
|
"TotalSegmentator is required for CT skull-stripping.\n"
|
|
117
118
|
"Install it with: pip install caideface[ct]"
|
|
118
119
|
)
|
|
119
120
|
|
|
121
|
+
# Disable anonymous usage statistics — no data should leave the machine.
|
|
122
|
+
# Patch send_usage_stats to a no-op so no network calls are made.
|
|
123
|
+
_orig_send = _ts_config.send_usage_stats
|
|
124
|
+
_ts_config.send_usage_stats = lambda *a, **kw: None
|
|
125
|
+
|
|
120
126
|
ts_device = "cpu" if device == "cpu" else "gpu"
|
|
121
127
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
128
|
+
try:
|
|
129
|
+
input_img = nib.load(input_file)
|
|
130
|
+
brain_mask = totalsegmentator(
|
|
131
|
+
input=input_img,
|
|
132
|
+
task="total",
|
|
133
|
+
roi_subset=["brain"],
|
|
134
|
+
device=ts_device,
|
|
135
|
+
quiet=True,
|
|
136
|
+
)
|
|
137
|
+
finally:
|
|
138
|
+
_ts_config.send_usage_stats = _orig_send
|
|
129
139
|
|
|
130
140
|
# Save the raw binary brain mask
|
|
131
141
|
mask_data = brain_mask.get_fdata().astype(np.uint8)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: caideface
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: MRI defacing pipeline with skull-stripping and affine registration from cai4cai
|
|
5
5
|
Author-email: Lorena Garcia-Foncillas <lorenagarfon00@gmail.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -31,28 +31,35 @@ Requires-Dist: TotalSegmentator; extra == "ct"
|
|
|
31
31
|
|
|
32
32
|
# caideface
|
|
33
33
|
|
|
34
|
-
**MRI defacing and text anonymisation toolkit** from the [cai4cai](https://cai4cai.ml/) research group (Contextual Artificial Intelligence for Computer Assisted Interventions).
|
|
34
|
+
**MRI and CT defacing and text anonymisation toolkit** from the [cai4cai](https://cai4cai.ml/) research group (Contextual Artificial Intelligence for Computer Assisted Interventions).
|
|
35
35
|
|
|
36
36
|
This package provides two complementary anonymisation capabilities:
|
|
37
37
|
|
|
38
|
-
- **Image defacing** -- removes facial features from head MRI scans while preserving brain structures
|
|
39
|
-
- **Text anonymisation** -- detects personal names in medical reports using a trained spaCy NER model and replaces them with realistic fake names (Hiding in Plain Sight / HIPS technique).
|
|
38
|
+
- **Image defacing** -- removes facial features from head MRI and CT scans while preserving brain structures. The MRI pipeline is described in the paper *"A Generalisable Head MRI Defacing Pipeline: Evaluation on 2,566 Meningioma Scans"* ([arXiv:2505.12999](https://arxiv.org/abs/2505.12999)).
|
|
39
|
+
- **Text anonymisation** -- detects personal names in medical reports using a trained spaCy NER model and replaces them with realistic fake names (Hiding in Plain Sight / HIPS technique), as described in *"Evaluation of Named Entity Recognition for Automated Extraction of Present Tumor Size and Personal Names from Radiology Reports Using Spacy"* ([DOI:10.1055/s-0045-1803715](https://doi.org/10.1055/s-0045-1803715)).
|
|
40
40
|
|
|
41
41
|
## Pipeline overview
|
|
42
42
|
|
|
43
43
|
### Image defacing pipeline
|
|
44
44
|
|
|
45
|
-
The defacing pipeline consists of three steps:
|
|
45
|
+
The defacing pipeline supports both **MRI** and **CT** modalities, selected via the required `--modality {mri,ct}` flag. The pipeline consists of three steps, with modality-specific backends:
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
| Step | MRI | CT |
|
|
48
|
+
|------|-----|-----|
|
|
49
|
+
| 1. Reorientation | → RAS | → RAS |
|
|
50
|
+
| 2. Brain extraction | [HD-BET](https://github.com/MIC-DKFZ/HD-BET) | [TotalSegmentator](https://github.com/wasserth/TotalSegmentator) |
|
|
51
|
+
| 3. Registration template | MNI152 T1 (bundled) | CT brain atlas (from TotalSegmentator) |
|
|
52
|
+
| Background value | Always 0 | Auto-detected per volume |
|
|
53
|
+
|
|
54
|
+
1. **Reorientation** -- Aligns NIfTI scans to RAS canonical orientation (MNI152 standard) using nibabel, equivalent to FSL's `fslreorient2std`.
|
|
55
|
+
2. **Skull-stripping** -- Extracts brain masks, then applies dynamic dilation to preserve peripheral brain structures. MRI uses [HD-BET](https://github.com/MIC-DKFZ/HD-BET); CT uses [TotalSegmentator](https://github.com/wasserth/TotalSegmentator) (brain class from the total segmentation task).
|
|
56
|
+
3. **Registration & Defacing** -- Registers each scan to a modality-matched template using BRAINSFit (affine), warps a face mask into the scan's space, and applies it to remove facial features. For CT, the background fill value is automatically detected from the volume histogram (~-1000 HU for native encoding).
|
|
50
57
|
|
|
51
58
|
### Text anonymisation (NER + HIPS)
|
|
52
59
|
|
|
53
60
|
The text anonymisation module uses a trained spaCy Named Entity Recognition (NER) model to identify personal names (`PER` entities) in `.txt` files and replaces them with realistic fake names generated by the [Faker](https://faker.readthedocs.io/) library. This "Hiding in Plain Sight" (HIPS) approach produces anonymised reports that remain naturally readable. Consistent name mapping ensures that the same real name is always replaced with the same fake name within a document.
|
|
54
61
|
|
|
55
|
-
All required models and data are **bundled with the package
|
|
62
|
+
All required models and data for MRI defacing and text anonymisation are **bundled with the package**. CT defacing requires installing the optional `[ct]` extra (see [Installation](#installation)).
|
|
56
63
|
|
|
57
64
|
## Requirements
|
|
58
65
|
|
|
@@ -66,7 +73,7 @@ All required models and data are **bundled with the package**, so no additional
|
|
|
66
73
|
|------|---------|---------|
|
|
67
74
|
| **BRAINSFit** & **BRAINSResample** | Step 3 | Bundled with [3D Slicer](https://www.slicer.org/) |
|
|
68
75
|
|
|
69
|
-
> **Note:** Step 1 (reorientation) no longer requires FSL -- it uses nibabel's orientation tools to reorient scans to
|
|
76
|
+
> **Note:** Step 1 (reorientation) no longer requires FSL -- it uses nibabel's orientation tools to reorient scans to RAS (equivalent to `fslreorient2std`).
|
|
70
77
|
|
|
71
78
|
#### Finding BRAINSFit and BRAINSResample
|
|
72
79
|
|
|
@@ -96,13 +103,21 @@ We recommend using a conda environment:
|
|
|
96
103
|
```bash
|
|
97
104
|
conda create -n caideface python=3.10 -y
|
|
98
105
|
conda activate caideface
|
|
106
|
+
|
|
107
|
+
# MRI defacing only
|
|
99
108
|
pip install caideface
|
|
109
|
+
|
|
110
|
+
# MRI + CT defacing (includes TotalSegmentator)
|
|
111
|
+
pip install caideface[ct]
|
|
100
112
|
```
|
|
101
113
|
|
|
102
114
|
Or install from GitHub:
|
|
103
115
|
|
|
104
116
|
```bash
|
|
105
117
|
pip install "caideface @ git+https://github.com/cai4cai/defacing_pipeline.git#subdirectory=caideface"
|
|
118
|
+
|
|
119
|
+
# With CT support
|
|
120
|
+
pip install "caideface[ct] @ git+https://github.com/cai4cai/defacing_pipeline.git#subdirectory=caideface"
|
|
106
121
|
```
|
|
107
122
|
|
|
108
123
|
Or install from source:
|
|
@@ -110,10 +125,13 @@ Or install from source:
|
|
|
110
125
|
```bash
|
|
111
126
|
git clone https://github.com/cai4cai/defacing_pipeline.git
|
|
112
127
|
cd defacing_pipeline/caideface
|
|
113
|
-
pip install -e .
|
|
128
|
+
pip install -e . # MRI only
|
|
129
|
+
pip install -e ".[ct]" # MRI + CT
|
|
114
130
|
```
|
|
115
131
|
|
|
116
132
|
> **Note:** caideface requires `numpy<2` (enforced automatically). Some dependencies (HD-BET / nnU-Net) are not yet compatible with NumPy 2.x.
|
|
133
|
+
>
|
|
134
|
+
> **Note:** CT support requires [TotalSegmentator](https://github.com/wasserth/TotalSegmentator), which downloads model weights (~1.5 GB) on first use to `~/.totalsegmentator/`. All inference runs locally -- no scan data is sent externally.
|
|
117
135
|
|
|
118
136
|
## Usage
|
|
119
137
|
|
|
@@ -122,7 +140,15 @@ pip install -e .
|
|
|
122
140
|
Run all three steps in one command:
|
|
123
141
|
|
|
124
142
|
```bash
|
|
143
|
+
# MRI
|
|
125
144
|
caideface run ./input_nifti ./output \
|
|
145
|
+
--modality mri \
|
|
146
|
+
--brainsfit /path/to/BRAINSFit \
|
|
147
|
+
--brainsresample /path/to/BRAINSResample
|
|
148
|
+
|
|
149
|
+
# CT
|
|
150
|
+
caideface run ./input_nifti ./output \
|
|
151
|
+
--modality ct \
|
|
126
152
|
--brainsfit /path/to/BRAINSFit \
|
|
127
153
|
--brainsresample /path/to/BRAINSResample
|
|
128
154
|
```
|
|
@@ -136,12 +162,13 @@ This creates three subdirectories under `./output`:
|
|
|
136
162
|
|
|
137
163
|
| Flag | Default | Description |
|
|
138
164
|
|------|---------|-------------|
|
|
139
|
-
| `--
|
|
140
|
-
| `--
|
|
165
|
+
| `--modality` | *required* | Image modality: `mri` or `ct` |
|
|
166
|
+
| `--device` | auto-detected | `cpu` or `cuda` for brain extraction |
|
|
167
|
+
| `--no-tta` | on | Disable HD-BET test-time augmentation (MRI only) |
|
|
141
168
|
| `--dilation-mm` | `14.0` | Brain mask dilation in mm |
|
|
142
|
-
| `--background` |
|
|
143
|
-
| `--template` | bundled | Custom
|
|
144
|
-
| `--face-mask` | bundled | Custom face mask in
|
|
169
|
+
| `--background` | auto-detected | Background fill value (auto-detected per volume; override with explicit value) |
|
|
170
|
+
| `--template` | bundled | Custom skull-stripped template |
|
|
171
|
+
| `--face-mask` | bundled | Custom face mask in template space |
|
|
145
172
|
| `--steps` | `all` | Run specific steps: `reorient`, `skull_strip`, `deface` (comma-separated) |
|
|
146
173
|
| `-v` | off | Verbose/debug logging |
|
|
147
174
|
|
|
@@ -151,13 +178,14 @@ Run each step separately for more control:
|
|
|
151
178
|
|
|
152
179
|
```bash
|
|
153
180
|
# Step 1: Reorientation
|
|
154
|
-
caideface reorient ./raw_nifti ./reoriented
|
|
181
|
+
caideface reorient ./raw_nifti ./reoriented --modality mri
|
|
155
182
|
|
|
156
183
|
# Step 2: Skull-stripping
|
|
157
|
-
caideface skull-strip ./reoriented ./hdbet --device cpu
|
|
184
|
+
caideface skull-strip ./reoriented ./hdbet --modality mri --device cpu
|
|
158
185
|
|
|
159
186
|
# Step 3: Registration & Defacing
|
|
160
187
|
caideface deface ./reoriented ./hdbet ./defaced \
|
|
188
|
+
--modality mri \
|
|
161
189
|
--brainsfit /path/to/BRAINSFit \
|
|
162
190
|
--brainsresample /path/to/BRAINSResample
|
|
163
191
|
```
|
|
@@ -249,6 +277,7 @@ from caideface import (
|
|
|
249
277
|
anonymize_batch, # Text anonymisation (batch)
|
|
250
278
|
anonymize_single, # Text anonymisation (single file)
|
|
251
279
|
default_ner_model_path, # Path to bundled NER model
|
|
280
|
+
detect_background_value, # CT/MRI background detection
|
|
252
281
|
)
|
|
253
282
|
```
|
|
254
283
|
|
|
@@ -299,7 +328,21 @@ If you use this tool, please cite:
|
|
|
299
328
|
}
|
|
300
329
|
```
|
|
301
330
|
|
|
302
|
-
If you use
|
|
331
|
+
If you use CT defacing (TotalSegmentator, Step 2), please also cite:
|
|
332
|
+
|
|
333
|
+
```bibtex
|
|
334
|
+
@article{Wasserthal2023,
|
|
335
|
+
author={Wasserthal, Jakob and Breit, Hanns-Christian and Meyer, Manfred T. and Pradella, Maurice and Hinck, Daniel and Sauter, Alexander W. and Heye, Tobias and Boll, Daniel T. and Cyriac, Joshy and Yang, Shan and Bach, Michael and Segeroth, Martin},
|
|
336
|
+
title={TotalSegmentator: Robust Segmentation of 104 Anatomic Structures in CT Images},
|
|
337
|
+
journal={Radiology: Artificial Intelligence},
|
|
338
|
+
volume={5},
|
|
339
|
+
number={5},
|
|
340
|
+
year={2023},
|
|
341
|
+
doi={10.1148/ryai.230024}
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
If you use HD-BET (MRI skull-stripping, Step 2), please also cite:
|
|
303
346
|
|
|
304
347
|
```bibtex
|
|
305
348
|
@article{Isensee2019,
|
|
@@ -330,4 +373,4 @@ If you use the text anonymisation (NER + HIPS), please also cite:
|
|
|
330
373
|
|
|
331
374
|
## License
|
|
332
375
|
|
|
333
|
-
This project is licensed under the Apache License 2.0 -- see the [LICENSE](
|
|
376
|
+
This project is licensed under the Apache License 2.0 -- see the [LICENSE](https://github.com/cai4cai/defacing_pipeline/blob/main/LICENSE) file for details.
|
|
@@ -30,7 +30,7 @@ def _make_nifti(shape=(64, 64, 32), orientation="PSR", dirpath=None):
|
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
class TestReorientSingle:
|
|
33
|
-
def
|
|
33
|
+
def test_reorients_to_ras(self, tmp_path):
|
|
34
34
|
input_path = _make_nifti(orientation="PSR", dirpath=str(tmp_path))
|
|
35
35
|
output_path = os.path.join(str(tmp_path), "output", "reoriented.nii.gz")
|
|
36
36
|
|
|
@@ -39,10 +39,10 @@ class TestReorientSingle:
|
|
|
39
39
|
assert success is True
|
|
40
40
|
assert os.path.exists(output_path)
|
|
41
41
|
img = nib.load(output_path)
|
|
42
|
-
assert nib.aff2axcodes(img.affine) == ("
|
|
42
|
+
assert nib.aff2axcodes(img.affine) == ("R", "A", "S")
|
|
43
43
|
|
|
44
|
-
def
|
|
45
|
-
input_path = _make_nifti(orientation="
|
|
44
|
+
def test_already_ras_is_unchanged(self, tmp_path):
|
|
45
|
+
input_path = _make_nifti(orientation="RAS", dirpath=str(tmp_path))
|
|
46
46
|
output_path = os.path.join(str(tmp_path), "output", "reoriented.nii.gz")
|
|
47
47
|
|
|
48
48
|
success = reorient_single(input_path, output_path)
|
|
@@ -86,7 +86,7 @@ class TestReorientSingle:
|
|
|
86
86
|
success = reorient_single(input_path, output_path)
|
|
87
87
|
assert success is True
|
|
88
88
|
img = nib.load(output_path)
|
|
89
|
-
assert nib.aff2axcodes(img.affine) == ("
|
|
89
|
+
assert nib.aff2axcodes(img.affine) == ("R", "A", "S"), f"Failed for {ornt}"
|
|
90
90
|
|
|
91
91
|
def test_invalid_file_returns_false(self, tmp_path):
|
|
92
92
|
fake_path = os.path.join(str(tmp_path), "nonexistent.nii.gz")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|