从.npy到.nii.gz:手把手教你为nnUNet准备2D医学图像数据(附完整Python脚本)
从.npy到.nii.gznnUNet医学图像数据预处理全流程实战指南医学影像分析领域数据格式转换与预处理往往是模型训练的第一步也是最容易出错的环节。许多研究者在使用nnUNet框架时常因2D到3D数据转换不规范导致后续训练失败。本文将系统性地拆解从原始.npy格式到nnUNet标准输入.nii.gz的完整转换流程并提供可直接复用的Python脚本与调试技巧。1. 理解nnUNet的数据规范要求nnUNet作为医学图像分割的标杆框架对输入数据有严格的结构化要求。在开始转换前必须明确三个核心规范三维数据格式即使原始数据是2D切片也必须转换为3D .nii.gz格式通过增加伪维度实现文件目录结构必须遵循TaskXXX_MYPROJECT的命名规范包含imagesTr、labelsTr等标准子目录metadata完整性dataset.json文件需要准确描述模态信息、类别标签等关键元数据常见错误直接使用2D图像训练会导致nnUNet报错Expected 3D image, got 2D根源在于未进行维度扩展2. 环境配置与目录准备2.1 基础环境搭建推荐使用conda创建隔离的Python环境conda create -n nnunet python3.8 conda activate nnunet pip install SimpleITK numpy tqdm2.2 项目目录结构必须严格按以下结构组织数据以Task101_BrainTumor为例nnUNet_raw_data_base/ ├── nnUNet_raw_data/ │ └── Task101_BrainTumor/ │ ├── imagesTr/ # 训练图像 │ ├── labelsTr/ # 训练标签 │ ├── imagesTs/ # 测试图像可选 │ └── dataset.json # 元数据文件可通过以下Python代码自动创建目录import os task_name Task101_BrainTumor base_dir f/path/to/nnUNet_raw_data_base/nnUNet_raw_data/{task_name} os.makedirs(f{base_dir}/imagesTr, exist_okTrue) os.makedirs(f{base_dir}/labelsTr, exist_okTrue)3. 2D到3D数据转换实战3.1 单模态图像转换对于MRI等单模态数据转换核心是使用np.expand_dims增加维度import numpy as np import SimpleITK as sitk def npy_to_nii(npy_path, output_path): # 加载.npy文件 data np.load(npy_path) # 假设shape(H,W) # 增加维度 (H,W) - (1,H,W) data_3d np.expand_dims(data, axis0) # 转换为SimpleITK图像对象 img sitk.GetImageFromArray(data_3d) # 保存为.nii.gz sitk.WriteImage(img, output_path)3.2 多模态数据处理对于多参数MRI等含多个模态的数据需要按约定命名BraTS_001_0000.nii.gz # 模态1 BraTS_001_0001.nii.gz # 模态2转换脚本需相应调整def convert_multimodal(input_dir, output_dir): modalities [T1, T2, FLAIR, ADC] for i, filename in enumerate(os.listdir(input_dir)): for mod_idx, mod in enumerate(modalities): img np.load(f{input_dir}/{filename}/{mod}.npy) img_3d np.expand_dims(img, 0) sitk_img sitk.GetImageFromArray(img_3d) output_path f{output_dir}/{i}_000{mod_idx}.nii.gz sitk.WriteImage(sitk_img, output_path)4. 标签处理的特殊要求nnUNet对分割标签有严格规范标签值必须为连续的整数0,1,2,...背景必须标记为0不同类别标签不能有间断修正标签的典型操作# 原始标签可能有间断值如1,3,5 mask np.load(label.npy) mask[mask 3] 2 # 将3映射到2 mask[mask 5] 3 # 将5映射到35. 构建dataset.json文件该文件是nnUNet识别数据集的关键必须包含以下字段{ name: BrainTumor, description: Example 2D to 3D conversion, reference: Your Institution, licence: CC-BY-SA 4.0, release: 1.0, modality: { 0: MRI }, labels: { 0: background, 1: tumor_core, 2: edema }, numTraining: 100, numTest: 20, training: [ { image: ./imagesTr/case_001.nii.gz, label: ./labelsTr/case_001.nii.gz } ], test: [] }自动生成脚本示例import json def generate_json(output_path, num_cases): template { modality: {0: MRI}, labels: {0: background, 1: tumor}, training: [] } for i in range(num_cases): case { image: f./imagesTr/{i}.nii.gz, label: f./labelsTr/{i}.nii.gz } template[training].append(case) with open(output_path, w) as f: json.dump(template, f, indent4)6. 数据完整性验证在开始训练前必须运行完整性检查nnUNet_plan_and_preprocess -t 101 --verify_dataset_integrity常见错误及解决方案维度不匹配检查是否所有图像和标签具有相同的三维尺寸标签值不连续使用np.unique()检查标签值是否符合要求文件路径错误确认dataset.json中的路径与实际存储位置一致7. 高效训练技巧对于2D数据可以采用这些优化策略显存优化在nnUNetTrainerV2中调整batch_size参数数据增强启用nnUNet内置的随机旋转、缩放等2D专属增强混合精度训练添加--amp参数加速训练过程典型训练命令nnUNet_train 2d nnUNetTrainerV2 Task101_BrainTumor all --npz8. 实际项目中的经验分享在处理MICCAI BraTS数据集时发现几个关键点多模态数据需要保证各模态图像严格对齐大尺寸图像如512x512需要调整nnUNet的默认配置标签重映射时要注意保持解剖结构的合理性一个实用的调试技巧是在转换后立即可视化import matplotlib.pyplot as plt def check_conversion(nii_path): img sitk.ReadImage(nii_path) arr sitk.GetArrayFromImage(img) plt.imshow(arr[0], cmapgray) plt.show()