147 lines
5.7 KiB
Markdown
147 lines
5.7 KiB
Markdown
# VoxelMorph Head CT Deformable Registration
|
||
|
||
面向“患者平扫 CT(中立位)到仰头 CT(极度后仰位)”的 3D 形变配准工程。项目包含 DICOM 转 NIfTI、医学图像预处理、官方 VoxelMorph 训练适配器、独立推理,以及 Streamlit 交互式结果查看界面。
|
||
|
||
核心模型使用官方仓库 `voxelmorph/voxelmorph` 的 PyTorch 实现:
|
||
|
||
- 官方仓库:https://github.com/voxelmorph/voxelmorph
|
||
- 固定提交:`db73f34b910bcefcb520f7f40a1bc4a3e0b6401d`
|
||
- 核心类:`voxelmorph.nn.models.VxmPairwise`
|
||
- 平滑正则:`neurite.nn.modules.SpatialGradient`
|
||
- 相似度:默认使用带 epsilon 的稳定 Local NCC;可通过 `--ncc-impl neurite` 切换到 `neurite.nn.modules.NCC`
|
||
|
||
## 工程目录
|
||
|
||
```text
|
||
Voxelmorph_Head_CT/
|
||
├── Data/
|
||
│ ├── 患者1-平扫CT/ # Moving 原始 DICOM
|
||
│ ├── 患者1-仰头CT/ # Fixed 原始 DICOM
|
||
│ └── 患者2-平扫CT/
|
||
├── app.py # Streamlit Web 可视化界面
|
||
├── config.py # 默认路径与预处理参数
|
||
├── data_loader.py # DICOM 序列读取与 NIfTI 转换
|
||
├── environment.yml # Conda CUDA 环境
|
||
├── infer.py # 独立推理,输出 warped image 与 DDF
|
||
├── metrics.py # NCC/MSE/MAE/DDF 等量化指标
|
||
├── model_and_train.py # 官方 VoxelMorph 训练适配器
|
||
├── preprocess.py # 重采样、窗宽窗位、裁剪/填充
|
||
├── requirements.txt
|
||
└── outputs/
|
||
├── nifti/ # DICOM 转换结果
|
||
├── preprocessed/ # 预处理结果
|
||
├── checkpoints/ # 模型权重
|
||
└── inference/ # 推理输出
|
||
```
|
||
|
||
## 环境
|
||
|
||
推荐使用 Conda 创建 CUDA 环境。本机如有 NVIDIA 驱动,不需要单独安装系统 CUDA toolkit,`pytorch-cuda=12.4` 会随 Conda 环境提供运行时。
|
||
|
||
为减少 Conda 包缓存和 Qt 依赖占用,环境采用两步安装:Conda 只安装 Python、PyTorch 与 CUDA runtime,业务依赖和官方 VoxelMorph 用 pip 安装。
|
||
|
||
```bash
|
||
conda env create -f environment.yml
|
||
conda activate voxelmorph-head-ct
|
||
python -m pip install --no-cache-dir -r requirements.txt
|
||
python -c "import torch; print(torch.__version__, torch.cuda.is_available())"
|
||
```
|
||
|
||
也可以直接运行项目脚本:
|
||
|
||
```bash
|
||
bash scripts/setup_env.sh
|
||
```
|
||
|
||
如果只做 CPU 调试,也可以使用 `pip install -r requirements.txt`,但 3D 训练强烈建议使用 CUDA。
|
||
|
||
## 1. DICOM 转 NIfTI
|
||
|
||
```bash
|
||
python data_loader.py \
|
||
--dicom-dir "Data/患者1-平扫CT" \
|
||
--output "outputs/nifti/patient1_moving.nii.gz"
|
||
|
||
python data_loader.py \
|
||
--dicom-dir "Data/患者1-仰头CT" \
|
||
--output "outputs/nifti/patient1_fixed.nii.gz"
|
||
```
|
||
|
||
`data_loader.py` 会优先按 `InstanceNumber` 排序,其次按 `SliceLocation` 排序,并保存 spacing、层厚、排序依据等元数据 JSON。
|
||
|
||
## 2. 预处理
|
||
|
||
```bash
|
||
python preprocess.py \
|
||
--input "outputs/nifti/patient1_moving.nii.gz" \
|
||
--output "outputs/preprocessed/patient1_moving_preprocessed.nii.gz" \
|
||
--target-spacing 1 1 1 \
|
||
--target-shape 160 192 224
|
||
|
||
python preprocess.py \
|
||
--input "outputs/nifti/patient1_fixed.nii.gz" \
|
||
--output "outputs/preprocessed/patient1_fixed_preprocessed.nii.gz" \
|
||
--target-spacing 1 1 1 \
|
||
--target-shape 160 192 224
|
||
```
|
||
|
||
默认窗口为 `W=400, L=40`,适合观察颈部软组织和气道。
|
||
|
||
## 3. 训练
|
||
|
||
```bash
|
||
python model_and_train.py \
|
||
--moving "outputs/preprocessed/patient1_moving_preprocessed.nii.gz" \
|
||
--fixed "outputs/preprocessed/patient1_fixed_preprocessed.nii.gz" \
|
||
--checkpoint "outputs/checkpoints/vxm_head_ct.pt" \
|
||
--epochs 200 \
|
||
--image-loss ncc \
|
||
--ncc-impl local \
|
||
--smooth-weight 0.01
|
||
```
|
||
|
||
训练脚本会调用官方 `vxm.nn.models.VxmPairwise`。如果显存不足,可降低 `--nb-features` 或改小 `--target-shape` 后重新预处理。
|
||
由于 CT 预处理后常有大面积零填充背景,默认 `--ncc-impl local` 会在 NCC 方差项中加入 epsilon,避免低方差窗口导致非有限 loss。
|
||
|
||
## 4. 推理
|
||
|
||
```bash
|
||
python infer.py \
|
||
--moving "outputs/preprocessed/patient1_moving_preprocessed.nii.gz" \
|
||
--fixed "outputs/preprocessed/patient1_fixed_preprocessed.nii.gz" \
|
||
--checkpoint "outputs/checkpoints/vxm_head_ct.pt" \
|
||
--out-dir "outputs/inference"
|
||
```
|
||
|
||
推理会输出:
|
||
|
||
- `outputs/inference/moving_model_input.nii.gz`
|
||
- `outputs/inference/fixed_model_input.nii.gz`
|
||
- `outputs/inference/warped_moving.nii.gz`
|
||
- `outputs/inference/ddf_mm.nii.gz`
|
||
- `outputs/inference/metrics.json`
|
||
|
||
`moving_model_input.nii.gz` 和 `fixed_model_input.nii.gz` 是进入 VoxelMorph 前的统一网格图像。即使两套 CT 原始层数不同,推理前也会按 checkpoint 的输入尺寸和目标 spacing 完成重采样、归一化、中心裁剪/填充。
|
||
|
||
## 5. Web 结果展示
|
||
|
||
```bash
|
||
streamlit run app.py
|
||
```
|
||
|
||
网页提供:
|
||
|
||
- Moving/Fixed/模型权重/输出目录输入。
|
||
- 自动发现 `outputs/` 与项目目录下的 NIfTI 和 checkpoint,也支持手动输入路径。
|
||
- “开始推理”按钮。
|
||
- Axial、Coronal、Sagittal 正交三视图;每个平面按行同时展示 Fixed、Moving、Warped。
|
||
- Fixed 与 Warped 的 Alpha 融合或棋盘格对比。
|
||
- DDF 位移强度热力图。
|
||
- NCC、MSE、MAE、逐切片误差曲线、DDF 位移分布等量化图。
|
||
|
||
## 内存注意事项
|
||
|
||
- DICOM 转换和重采样都有 `--max-memory-mb` 防护。
|
||
- Web 界面对超大 NIfTI 会通过 nibabel proxy 按 stride 切片读取并下采样,只影响浏览器展示,不改变磁盘结果;侧栏可调整显示体素上限。
|
||
- 训练阶段的主要瓶颈是 3D U-Net 显存;`160x192x224` 是较重的 3D 输入,建议优先使用 CUDA GPU。
|