caideface 0.1.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.1.3/LICENSE.md +21 -0
- caideface-0.1.3/PKG-INFO +198 -0
- caideface-0.1.3/README.md +169 -0
- caideface-0.1.3/pyproject.toml +51 -0
- caideface-0.1.3/setup.cfg +4 -0
- caideface-0.1.3/src/caideface/__init__.py +24 -0
- caideface-0.1.3/src/caideface/cli.py +127 -0
- caideface-0.1.3/src/caideface/data/mni_icbm152_t1_tal_nlin_sym_55_ext_brain_only.nii.gz +0 -0
- caideface-0.1.3/src/caideface/data/t1_mask.nii.gz +0 -0
- caideface-0.1.3/src/caideface/pipeline.py +139 -0
- caideface-0.1.3/src/caideface/register.py +395 -0
- caideface-0.1.3/src/caideface/reorient.py +98 -0
- caideface-0.1.3/src/caideface/skull_strip.py +248 -0
- caideface-0.1.3/src/caideface.egg-info/PKG-INFO +198 -0
- caideface-0.1.3/src/caideface.egg-info/SOURCES.txt +20 -0
- caideface-0.1.3/src/caideface.egg-info/dependency_links.txt +1 -0
- caideface-0.1.3/src/caideface.egg-info/entry_points.txt +2 -0
- caideface-0.1.3/src/caideface.egg-info/requires.txt +12 -0
- caideface-0.1.3/src/caideface.egg-info/top_level.txt +1 -0
- caideface-0.1.3/tests/test_register.py +101 -0
- caideface-0.1.3/tests/test_reorient.py +120 -0
- caideface-0.1.3/tests/test_skull_strip.py +80 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-present cai4cai
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
caideface-0.1.3/PKG-INFO
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: caideface
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: MRI defacing pipeline with skull-stripping and affine registration from cai4cai
|
|
5
|
+
Author-email: Lorena Garcia-Foncillas <lorenagarfon00@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/LorenaGarcia-Foncillas/caideface
|
|
8
|
+
Project-URL: Repository, https://github.com/LorenaGarcia-Foncillas/caideface
|
|
9
|
+
Keywords: MRI,defacing,anonymisation,skull-stripping,neuroimaging
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE.md
|
|
17
|
+
Requires-Dist: nibabel>=4.0
|
|
18
|
+
Requires-Dist: numpy<2,>=1.22
|
|
19
|
+
Requires-Dist: scipy>=1.9
|
|
20
|
+
Requires-Dist: SimpleITK>=2.2
|
|
21
|
+
Requires-Dist: pandas>=1.5
|
|
22
|
+
Requires-Dist: natsort>=8.0
|
|
23
|
+
Requires-Dist: tqdm>=4.60
|
|
24
|
+
Requires-Dist: hd-bet
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest; extra == "dev"
|
|
27
|
+
Requires-Dist: ruff; extra == "dev"
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
|
|
30
|
+
# caideface
|
|
31
|
+
|
|
32
|
+
**MRI defacing pipeline with skull-stripping and affine registration** from the [cai4cai](https://cai4cai.ml/) research group (Contextual Artificial Intelligence for Computer Assisted Interventions).
|
|
33
|
+
|
|
34
|
+
This pipeline anonymises head MRI scans by removing facial features while preserving brain structures, as 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)).
|
|
35
|
+
|
|
36
|
+
## Pipeline overview
|
|
37
|
+
|
|
38
|
+
The pipeline consists of three steps:
|
|
39
|
+
|
|
40
|
+
1. **Reorientation** -- Aligns NIfTI scans to LAS canonical orientation (MNI152 standard) using nibabel.
|
|
41
|
+
2. **Skull-stripping** -- Extracts brain masks using [HD-BET](https://github.com/MIC-DKFZ/HD-BET), then applies dynamic dilation to preserve peripheral brain structures.
|
|
42
|
+
3. **Registration & Defacing** -- Registers each scan to the MNI152 template using BRAINSFit (affine), warps a face mask into the scan's space, and applies it to remove facial features.
|
|
43
|
+
|
|
44
|
+
The MNI152 skull-stripped template and face mask are **bundled with the package**, so no additional downloads are needed.
|
|
45
|
+
|
|
46
|
+
## Requirements
|
|
47
|
+
|
|
48
|
+
### Python
|
|
49
|
+
|
|
50
|
+
- Python >= 3.9
|
|
51
|
+
|
|
52
|
+
### External tools (not pip-installable)
|
|
53
|
+
|
|
54
|
+
| Tool | Used in | Install |
|
|
55
|
+
|------|---------|---------|
|
|
56
|
+
| **BRAINSFit** & **BRAINSResample** | Step 3 | Bundled with [3D Slicer](https://www.slicer.org/) |
|
|
57
|
+
|
|
58
|
+
> **Note:** Step 1 (reorientation) no longer requires FSL -- it uses nibabel's orientation tools to reorient scans to LAS (equivalent to `fslreorient2std`).
|
|
59
|
+
|
|
60
|
+
#### Finding BRAINSFit and BRAINSResample
|
|
61
|
+
|
|
62
|
+
These executables are included with 3D Slicer. Common locations:
|
|
63
|
+
|
|
64
|
+
- **macOS**: `/Applications/Slicer.app/Contents/lib/Slicer-5.8/cli-modules/BRAINSFit`
|
|
65
|
+
- **Linux**: `/path/to/Slicer/lib/Slicer-5.8/cli-modules/BRAINSFit`
|
|
66
|
+
|
|
67
|
+
Replace `5.8` with your installed Slicer version if different. To verify the executables are found and working:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Check they exist
|
|
71
|
+
ls /Applications/Slicer.app/Contents/lib/Slicer-5.8/cli-modules/BRAINSFit
|
|
72
|
+
ls /Applications/Slicer.app/Contents/lib/Slicer-5.8/cli-modules/BRAINSResample
|
|
73
|
+
|
|
74
|
+
# Check they run (should print usage/help info)
|
|
75
|
+
/Applications/Slicer.app/Contents/lib/Slicer-5.8/cli-modules/BRAINSFit --help
|
|
76
|
+
/Applications/Slicer.app/Contents/lib/Slicer-5.8/cli-modules/BRAINSResample --help
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
You can also build them from source via [BRAINSTools](https://github.com/BRAINSia/BRAINSTools).
|
|
80
|
+
|
|
81
|
+
## Installation
|
|
82
|
+
|
|
83
|
+
We recommend using a conda environment:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
conda create -n caideface python=3.10 -y
|
|
87
|
+
conda activate caideface
|
|
88
|
+
pip install caideface
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Or install from source:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
git clone https://github.com/cai4cai/caideface.git
|
|
95
|
+
cd caideface
|
|
96
|
+
pip install -e .
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
> **Note:** caideface requires `numpy<2` (enforced automatically). Some dependencies (HD-BET / nnU-Net) are not yet compatible with NumPy 2.x.
|
|
100
|
+
|
|
101
|
+
## Usage
|
|
102
|
+
|
|
103
|
+
### CLI -- Full pipeline
|
|
104
|
+
|
|
105
|
+
Run all three steps in one command:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
caideface run ./input_nifti ./output \
|
|
109
|
+
--brainsfit /path/to/BRAINSFit \
|
|
110
|
+
--brainsresample /path/to/BRAINSResample
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
This creates three subdirectories under `./output`:
|
|
114
|
+
- `reoriented/` -- Step 1 outputs
|
|
115
|
+
- `hdbet/` -- Step 2 outputs (skull-stripped, masks, dilated)
|
|
116
|
+
- `defaced/` -- Step 3 outputs (final defaced scans)
|
|
117
|
+
|
|
118
|
+
#### Options
|
|
119
|
+
|
|
120
|
+
| Flag | Default | Description |
|
|
121
|
+
|------|---------|-------------|
|
|
122
|
+
| `--device` | auto-detected | `cpu` or `cuda` for HD-BET |
|
|
123
|
+
| `--no-tta` | on | Disable HD-BET test-time augmentation (faster but less accurate) |
|
|
124
|
+
| `--dilation-mm` | `14.0` | Brain mask dilation in mm |
|
|
125
|
+
| `--background` | `0` | Fill value for defaced regions (0 for MRI, -1024 for CT) |
|
|
126
|
+
| `--template` | bundled | Custom MNI152 skull-stripped template |
|
|
127
|
+
| `--face-mask` | bundled | Custom face mask in MNI152 space |
|
|
128
|
+
| `--steps` | `all` | Run specific steps: `reorient`, `skull_strip`, `deface` (comma-separated) |
|
|
129
|
+
| `-v` | off | Verbose/debug logging |
|
|
130
|
+
|
|
131
|
+
### CLI -- Individual steps
|
|
132
|
+
|
|
133
|
+
Run each step separately for more control:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Step 1: Reorientation
|
|
137
|
+
caideface reorient ./raw_nifti ./reoriented
|
|
138
|
+
|
|
139
|
+
# Step 2: Skull-stripping
|
|
140
|
+
caideface skull-strip ./reoriented ./hdbet --device cpu
|
|
141
|
+
|
|
142
|
+
# Step 3: Registration & Defacing
|
|
143
|
+
caideface deface ./reoriented ./hdbet ./defaced \
|
|
144
|
+
--brainsfit /path/to/BRAINSFit \
|
|
145
|
+
--brainsresample /path/to/BRAINSResample
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Output structure
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
output/
|
|
152
|
+
├── reoriented/
|
|
153
|
+
│ ├── reorientation_log.csv
|
|
154
|
+
│ └── <subject>/<scan>.nii.gz
|
|
155
|
+
├── hdbet/
|
|
156
|
+
│ ├── hd_bet_log.csv
|
|
157
|
+
│ └── <subject>/
|
|
158
|
+
│ ├── hd_bet_<scan>.nii.gz # Skull-stripped
|
|
159
|
+
│ ├── hd_bet_mask_<scan>.nii.gz # Dilated brain mask
|
|
160
|
+
│ └── hd_bet_dilated_<scan>.nii.gz # Dilated skull-stripped
|
|
161
|
+
└── defaced/
|
|
162
|
+
├── not_defaced_scans.csv # Only if failures occurred
|
|
163
|
+
└── <subject>/
|
|
164
|
+
└── hd_bet_dilated_<scan>_masked.nii.gz # Final defaced scan
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Existing transforms
|
|
168
|
+
|
|
169
|
+
If you have pre-computed registration transforms (e.g. from 3D Slicer), place a file named `Transform_to_template.txt` in the same directory as the dilated skull-stripped scan. The pipeline will use it instead of running BRAINSFit. Both plain 4x4 text matrices and ITK/Slicer transform formats are supported.
|
|
170
|
+
|
|
171
|
+
## Citation
|
|
172
|
+
|
|
173
|
+
If you use this tool, please cite:
|
|
174
|
+
|
|
175
|
+
```bibtex
|
|
176
|
+
@article{caideface2025,
|
|
177
|
+
title={A Generalisable Head MRI Defacing Pipeline: Evaluation on 2,566 Meningioma Scans},
|
|
178
|
+
year={2025},
|
|
179
|
+
url={https://arxiv.org/abs/2505.12999}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
If you use HD-BET (skull-stripping, Step 2), please also cite:
|
|
184
|
+
|
|
185
|
+
```bibtex
|
|
186
|
+
@article{Isensee2019,
|
|
187
|
+
author={Isensee, F. and Schell, M. and Tursunova, I. and Brugnara, G. and Bonekamp, D. and Neuberger, U. and Wick, A. and Schlemmer, H. P. and Heiland, S. and Wick, W. and Bendszus, M. and Maier-Hein, K. H. and Kickingereder, P.},
|
|
188
|
+
title={Automated brain extraction of multi-sequence MRI using artificial neural networks},
|
|
189
|
+
journal={Human Brain Mapping},
|
|
190
|
+
year={2019},
|
|
191
|
+
pages={1--13},
|
|
192
|
+
doi={10.1002/hbm.24750}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## License
|
|
197
|
+
|
|
198
|
+
This project is licensed under the MIT License -- see the [LICENSE](LICENSE.md) file for details.
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# caideface
|
|
2
|
+
|
|
3
|
+
**MRI defacing pipeline with skull-stripping and affine registration** from the [cai4cai](https://cai4cai.ml/) research group (Contextual Artificial Intelligence for Computer Assisted Interventions).
|
|
4
|
+
|
|
5
|
+
This pipeline anonymises head MRI scans by removing facial features while preserving brain structures, as 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)).
|
|
6
|
+
|
|
7
|
+
## Pipeline overview
|
|
8
|
+
|
|
9
|
+
The pipeline consists of three steps:
|
|
10
|
+
|
|
11
|
+
1. **Reorientation** -- Aligns NIfTI scans to LAS canonical orientation (MNI152 standard) using nibabel.
|
|
12
|
+
2. **Skull-stripping** -- Extracts brain masks using [HD-BET](https://github.com/MIC-DKFZ/HD-BET), then applies dynamic dilation to preserve peripheral brain structures.
|
|
13
|
+
3. **Registration & Defacing** -- Registers each scan to the MNI152 template using BRAINSFit (affine), warps a face mask into the scan's space, and applies it to remove facial features.
|
|
14
|
+
|
|
15
|
+
The MNI152 skull-stripped template and face mask are **bundled with the package**, so no additional downloads are needed.
|
|
16
|
+
|
|
17
|
+
## Requirements
|
|
18
|
+
|
|
19
|
+
### Python
|
|
20
|
+
|
|
21
|
+
- Python >= 3.9
|
|
22
|
+
|
|
23
|
+
### External tools (not pip-installable)
|
|
24
|
+
|
|
25
|
+
| Tool | Used in | Install |
|
|
26
|
+
|------|---------|---------|
|
|
27
|
+
| **BRAINSFit** & **BRAINSResample** | Step 3 | Bundled with [3D Slicer](https://www.slicer.org/) |
|
|
28
|
+
|
|
29
|
+
> **Note:** Step 1 (reorientation) no longer requires FSL -- it uses nibabel's orientation tools to reorient scans to LAS (equivalent to `fslreorient2std`).
|
|
30
|
+
|
|
31
|
+
#### Finding BRAINSFit and BRAINSResample
|
|
32
|
+
|
|
33
|
+
These executables are included with 3D Slicer. Common locations:
|
|
34
|
+
|
|
35
|
+
- **macOS**: `/Applications/Slicer.app/Contents/lib/Slicer-5.8/cli-modules/BRAINSFit`
|
|
36
|
+
- **Linux**: `/path/to/Slicer/lib/Slicer-5.8/cli-modules/BRAINSFit`
|
|
37
|
+
|
|
38
|
+
Replace `5.8` with your installed Slicer version if different. To verify the executables are found and working:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Check they exist
|
|
42
|
+
ls /Applications/Slicer.app/Contents/lib/Slicer-5.8/cli-modules/BRAINSFit
|
|
43
|
+
ls /Applications/Slicer.app/Contents/lib/Slicer-5.8/cli-modules/BRAINSResample
|
|
44
|
+
|
|
45
|
+
# Check they run (should print usage/help info)
|
|
46
|
+
/Applications/Slicer.app/Contents/lib/Slicer-5.8/cli-modules/BRAINSFit --help
|
|
47
|
+
/Applications/Slicer.app/Contents/lib/Slicer-5.8/cli-modules/BRAINSResample --help
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
You can also build them from source via [BRAINSTools](https://github.com/BRAINSia/BRAINSTools).
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
We recommend using a conda environment:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
conda create -n caideface python=3.10 -y
|
|
58
|
+
conda activate caideface
|
|
59
|
+
pip install caideface
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Or install from source:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
git clone https://github.com/cai4cai/caideface.git
|
|
66
|
+
cd caideface
|
|
67
|
+
pip install -e .
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
> **Note:** caideface requires `numpy<2` (enforced automatically). Some dependencies (HD-BET / nnU-Net) are not yet compatible with NumPy 2.x.
|
|
71
|
+
|
|
72
|
+
## Usage
|
|
73
|
+
|
|
74
|
+
### CLI -- Full pipeline
|
|
75
|
+
|
|
76
|
+
Run all three steps in one command:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
caideface run ./input_nifti ./output \
|
|
80
|
+
--brainsfit /path/to/BRAINSFit \
|
|
81
|
+
--brainsresample /path/to/BRAINSResample
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
This creates three subdirectories under `./output`:
|
|
85
|
+
- `reoriented/` -- Step 1 outputs
|
|
86
|
+
- `hdbet/` -- Step 2 outputs (skull-stripped, masks, dilated)
|
|
87
|
+
- `defaced/` -- Step 3 outputs (final defaced scans)
|
|
88
|
+
|
|
89
|
+
#### Options
|
|
90
|
+
|
|
91
|
+
| Flag | Default | Description |
|
|
92
|
+
|------|---------|-------------|
|
|
93
|
+
| `--device` | auto-detected | `cpu` or `cuda` for HD-BET |
|
|
94
|
+
| `--no-tta` | on | Disable HD-BET test-time augmentation (faster but less accurate) |
|
|
95
|
+
| `--dilation-mm` | `14.0` | Brain mask dilation in mm |
|
|
96
|
+
| `--background` | `0` | Fill value for defaced regions (0 for MRI, -1024 for CT) |
|
|
97
|
+
| `--template` | bundled | Custom MNI152 skull-stripped template |
|
|
98
|
+
| `--face-mask` | bundled | Custom face mask in MNI152 space |
|
|
99
|
+
| `--steps` | `all` | Run specific steps: `reorient`, `skull_strip`, `deface` (comma-separated) |
|
|
100
|
+
| `-v` | off | Verbose/debug logging |
|
|
101
|
+
|
|
102
|
+
### CLI -- Individual steps
|
|
103
|
+
|
|
104
|
+
Run each step separately for more control:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Step 1: Reorientation
|
|
108
|
+
caideface reorient ./raw_nifti ./reoriented
|
|
109
|
+
|
|
110
|
+
# Step 2: Skull-stripping
|
|
111
|
+
caideface skull-strip ./reoriented ./hdbet --device cpu
|
|
112
|
+
|
|
113
|
+
# Step 3: Registration & Defacing
|
|
114
|
+
caideface deface ./reoriented ./hdbet ./defaced \
|
|
115
|
+
--brainsfit /path/to/BRAINSFit \
|
|
116
|
+
--brainsresample /path/to/BRAINSResample
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Output structure
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
output/
|
|
123
|
+
├── reoriented/
|
|
124
|
+
│ ├── reorientation_log.csv
|
|
125
|
+
│ └── <subject>/<scan>.nii.gz
|
|
126
|
+
├── hdbet/
|
|
127
|
+
│ ├── hd_bet_log.csv
|
|
128
|
+
│ └── <subject>/
|
|
129
|
+
│ ├── hd_bet_<scan>.nii.gz # Skull-stripped
|
|
130
|
+
│ ├── hd_bet_mask_<scan>.nii.gz # Dilated brain mask
|
|
131
|
+
│ └── hd_bet_dilated_<scan>.nii.gz # Dilated skull-stripped
|
|
132
|
+
└── defaced/
|
|
133
|
+
├── not_defaced_scans.csv # Only if failures occurred
|
|
134
|
+
└── <subject>/
|
|
135
|
+
└── hd_bet_dilated_<scan>_masked.nii.gz # Final defaced scan
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Existing transforms
|
|
139
|
+
|
|
140
|
+
If you have pre-computed registration transforms (e.g. from 3D Slicer), place a file named `Transform_to_template.txt` in the same directory as the dilated skull-stripped scan. The pipeline will use it instead of running BRAINSFit. Both plain 4x4 text matrices and ITK/Slicer transform formats are supported.
|
|
141
|
+
|
|
142
|
+
## Citation
|
|
143
|
+
|
|
144
|
+
If you use this tool, please cite:
|
|
145
|
+
|
|
146
|
+
```bibtex
|
|
147
|
+
@article{caideface2025,
|
|
148
|
+
title={A Generalisable Head MRI Defacing Pipeline: Evaluation on 2,566 Meningioma Scans},
|
|
149
|
+
year={2025},
|
|
150
|
+
url={https://arxiv.org/abs/2505.12999}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
If you use HD-BET (skull-stripping, Step 2), please also cite:
|
|
155
|
+
|
|
156
|
+
```bibtex
|
|
157
|
+
@article{Isensee2019,
|
|
158
|
+
author={Isensee, F. and Schell, M. and Tursunova, I. and Brugnara, G. and Bonekamp, D. and Neuberger, U. and Wick, A. and Schlemmer, H. P. and Heiland, S. and Wick, W. and Bendszus, M. and Maier-Hein, K. H. and Kickingereder, P.},
|
|
159
|
+
title={Automated brain extraction of multi-sequence MRI using artificial neural networks},
|
|
160
|
+
journal={Human Brain Mapping},
|
|
161
|
+
year={2019},
|
|
162
|
+
pages={1--13},
|
|
163
|
+
doi={10.1002/hbm.24750}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## License
|
|
168
|
+
|
|
169
|
+
This project is licensed under the MIT License -- see the [LICENSE](LICENSE.md) file for details.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "caideface"
|
|
7
|
+
version = "0.1.3"
|
|
8
|
+
description = "MRI defacing pipeline with skull-stripping and affine registration from cai4cai"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Lorena Garcia-Foncillas", email = "lorenagarfon00@gmail.com"},
|
|
14
|
+
]
|
|
15
|
+
keywords = ["MRI", "defacing", "anonymisation", "skull-stripping", "neuroimaging"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Intended Audience :: Science/Research",
|
|
19
|
+
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Topic :: Scientific/Engineering :: Medical Science Apps.",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"nibabel>=4.0",
|
|
25
|
+
"numpy>=1.22,<2",
|
|
26
|
+
"scipy>=1.9",
|
|
27
|
+
"SimpleITK>=2.2",
|
|
28
|
+
"pandas>=1.5",
|
|
29
|
+
"natsort>=8.0",
|
|
30
|
+
"tqdm>=4.60",
|
|
31
|
+
"hd-bet",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
dev = [
|
|
36
|
+
"pytest",
|
|
37
|
+
"ruff",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[project.scripts]
|
|
41
|
+
caideface = "caideface.cli:main"
|
|
42
|
+
|
|
43
|
+
[project.urls]
|
|
44
|
+
Homepage = "https://github.com/LorenaGarcia-Foncillas/caideface"
|
|
45
|
+
Repository = "https://github.com/LorenaGarcia-Foncillas/caideface"
|
|
46
|
+
|
|
47
|
+
[tool.setuptools.packages.find]
|
|
48
|
+
where = ["src"]
|
|
49
|
+
|
|
50
|
+
[tool.setuptools.package-data]
|
|
51
|
+
caideface = ["data/*.nii.gz"]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""caideface - MRI defacing pipeline from cai4cai.
|
|
2
|
+
|
|
3
|
+
A three-step pipeline for anonymising head MRI scans:
|
|
4
|
+
1. Reorientation to MNI152 atlas reference (nibabel)
|
|
5
|
+
2. Skull-stripping with HD-BET and dynamic dilation
|
|
6
|
+
3. Affine registration and defacing (BRAINSFit)
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__version__ = "0.1.3"
|
|
10
|
+
|
|
11
|
+
from .pipeline import DefacePipeline
|
|
12
|
+
from .reorient import reorient_batch, reorient_single
|
|
13
|
+
from .skull_strip import skull_strip_batch, skull_strip_single
|
|
14
|
+
from .register import deface_batch, deface_single
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"DefacePipeline",
|
|
18
|
+
"reorient_batch",
|
|
19
|
+
"reorient_single",
|
|
20
|
+
"skull_strip_batch",
|
|
21
|
+
"skull_strip_single",
|
|
22
|
+
"deface_batch",
|
|
23
|
+
"deface_single",
|
|
24
|
+
]
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""Command-line interface for caideface."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import logging
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
from .pipeline import DefacePipeline
|
|
8
|
+
from .reorient import reorient_batch
|
|
9
|
+
from .skull_strip import skull_strip_batch, get_default_device
|
|
10
|
+
from .register import deface_batch
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _setup_logging(verbose: bool):
|
|
14
|
+
level = logging.DEBUG if verbose else logging.INFO
|
|
15
|
+
logging.basicConfig(
|
|
16
|
+
level=level,
|
|
17
|
+
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
|
|
18
|
+
datefmt="%H:%M:%S",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def main():
|
|
23
|
+
# Shared parent so -v works on any subcommand
|
|
24
|
+
parent = argparse.ArgumentParser(add_help=False)
|
|
25
|
+
parent.add_argument("-v", "--verbose", action="store_true", help="Enable debug logging")
|
|
26
|
+
|
|
27
|
+
parser = argparse.ArgumentParser(
|
|
28
|
+
prog="caideface",
|
|
29
|
+
description="MRI defacing pipeline from cai4cai: reorientation, skull-stripping, and affine-based defacing.",
|
|
30
|
+
parents=[parent],
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
subparsers = parser.add_subparsers(dest="command", help="Available commands")
|
|
34
|
+
|
|
35
|
+
# --- run: full pipeline ---
|
|
36
|
+
run_parser = subparsers.add_parser("run", help="Run the full defacing pipeline", parents=[parent])
|
|
37
|
+
run_parser.add_argument("input_dir", help="Directory containing raw NIfTI files")
|
|
38
|
+
run_parser.add_argument("output_dir", help="Root output directory")
|
|
39
|
+
run_parser.add_argument("--brainsfit", required=True, help="Path to BRAINSFit executable")
|
|
40
|
+
run_parser.add_argument("--brainsresample", required=True, help="Path to BRAINSResample executable")
|
|
41
|
+
run_parser.add_argument("--device", default=None, choices=["cpu", "cuda"], help="Device for HD-BET (auto-detected if omitted)")
|
|
42
|
+
run_parser.add_argument("--no-tta", action="store_true", default=True, help="Disable HD-BET test-time augmentation (default: disabled)")
|
|
43
|
+
run_parser.add_argument("--dilation-mm", type=float, default=14.0, help="Brain mask dilation in mm (default: 14)")
|
|
44
|
+
run_parser.add_argument("--background", type=float, default=0, help="Background value for defaced voxels (default: 0 for MRI, use -1024 for CT)")
|
|
45
|
+
run_parser.add_argument("--template", default=None, help="Custom MNI152 skull-stripped template (uses bundled if omitted)")
|
|
46
|
+
run_parser.add_argument("--face-mask", default=None, help="Custom face mask in MNI152 space (uses bundled if omitted)")
|
|
47
|
+
run_parser.add_argument("--steps", default="all", help="Steps to run: all, or comma-separated: reorient,skull_strip,deface")
|
|
48
|
+
|
|
49
|
+
# --- reorient ---
|
|
50
|
+
reorient_parser = subparsers.add_parser("reorient", help="Step 1: Reorient NIfTI scans to MNI152", parents=[parent])
|
|
51
|
+
reorient_parser.add_argument("input_dir", help="Directory with NIfTI files")
|
|
52
|
+
reorient_parser.add_argument("output_dir", help="Output directory for reoriented files")
|
|
53
|
+
|
|
54
|
+
# --- skull-strip ---
|
|
55
|
+
ss_parser = subparsers.add_parser("skull-strip", help="Step 2: Skull-strip with HD-BET", parents=[parent])
|
|
56
|
+
ss_parser.add_argument("input_dir", help="Directory with reoriented NIfTI files")
|
|
57
|
+
ss_parser.add_argument("output_dir", help="Output directory for HD-BET results")
|
|
58
|
+
ss_parser.add_argument("--device", default=None, choices=["cpu", "cuda"], help="Device for HD-BET")
|
|
59
|
+
ss_parser.add_argument("--no-tta", action="store_true", default=True, help="Disable test-time augmentation")
|
|
60
|
+
ss_parser.add_argument("--dilation-mm", type=float, default=14.0, help="Dilation in mm")
|
|
61
|
+
|
|
62
|
+
# --- deface ---
|
|
63
|
+
deface_parser = subparsers.add_parser("deface", help="Step 3: Register and deface", parents=[parent])
|
|
64
|
+
deface_parser.add_argument("reoriented_dir", help="Directory with reoriented scans (Step 1 output)")
|
|
65
|
+
deface_parser.add_argument("hdbet_dir", help="Directory with HD-BET results (Step 2 output)")
|
|
66
|
+
deface_parser.add_argument("output_dir", help="Output directory for defaced scans")
|
|
67
|
+
deface_parser.add_argument("--brainsfit", required=True, help="Path to BRAINSFit executable")
|
|
68
|
+
deface_parser.add_argument("--brainsresample", required=True, help="Path to BRAINSResample executable")
|
|
69
|
+
deface_parser.add_argument("--template", default=None, help="Custom MNI152 skull-stripped template")
|
|
70
|
+
deface_parser.add_argument("--face-mask", default=None, help="Custom face mask in MNI152 space")
|
|
71
|
+
deface_parser.add_argument("--background", type=float, default=0, help="Background value (default: 0 for MRI, use -1024 for CT)")
|
|
72
|
+
|
|
73
|
+
args = parser.parse_args()
|
|
74
|
+
|
|
75
|
+
if not args.command:
|
|
76
|
+
parser.print_help()
|
|
77
|
+
sys.exit(1)
|
|
78
|
+
|
|
79
|
+
_setup_logging(args.verbose)
|
|
80
|
+
|
|
81
|
+
if args.command == "run":
|
|
82
|
+
pipeline = DefacePipeline(
|
|
83
|
+
brainsfit_path=args.brainsfit,
|
|
84
|
+
brainsresample_path=args.brainsresample,
|
|
85
|
+
device=args.device,
|
|
86
|
+
disable_tta=args.no_tta,
|
|
87
|
+
desired_dilation_mm=args.dilation_mm,
|
|
88
|
+
background_value=args.background,
|
|
89
|
+
target_path=args.template,
|
|
90
|
+
face_mask_path=args.face_mask,
|
|
91
|
+
)
|
|
92
|
+
results = pipeline.run(args.input_dir, args.output_dir, steps=args.steps)
|
|
93
|
+
failed = results.get("failed_defacing", [])
|
|
94
|
+
if failed:
|
|
95
|
+
print(f"\n{len(failed)} scan(s) failed to deface. See output log for details.")
|
|
96
|
+
sys.exit(1)
|
|
97
|
+
|
|
98
|
+
elif args.command == "reorient":
|
|
99
|
+
reorient_batch(args.input_dir, args.output_dir)
|
|
100
|
+
|
|
101
|
+
elif args.command == "skull-strip":
|
|
102
|
+
skull_strip_batch(
|
|
103
|
+
args.input_dir,
|
|
104
|
+
args.output_dir,
|
|
105
|
+
device=args.device,
|
|
106
|
+
disable_tta=args.no_tta,
|
|
107
|
+
desired_dilation_mm=args.dilation_mm,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
elif args.command == "deface":
|
|
111
|
+
failed = deface_batch(
|
|
112
|
+
reoriented_dir=args.reoriented_dir,
|
|
113
|
+
hdbet_dir=args.hdbet_dir,
|
|
114
|
+
output_dir=args.output_dir,
|
|
115
|
+
brainsfit_path=args.brainsfit,
|
|
116
|
+
brainsresample_path=args.brainsresample,
|
|
117
|
+
target_path=args.template,
|
|
118
|
+
face_mask_path=args.face_mask,
|
|
119
|
+
background_value=args.background,
|
|
120
|
+
)
|
|
121
|
+
if failed:
|
|
122
|
+
print(f"\n{len(failed)} scan(s) failed. See output log.")
|
|
123
|
+
sys.exit(1)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
if __name__ == "__main__":
|
|
127
|
+
main()
|
|
Binary file
|
|
Binary file
|