如何使用COBRE数据集Nifti文件构建CNN模型?
COBRE脑MRI数据集适配CNN输入实操方案
1. 批量Nifti文件加载、转模型输入格式方法
很多人对Nilearn的功能有误解:nilearn.image.load_img()并非仅支持单文件加载,传入文件路径列表即可批量读取Nifti数据,完全可以满足100例样本的批量处理需求。
具体处理流程如下:
- 第一步:遍历数据集根目录,收集所有
.nii文件的完整路径,存为排序后的路径列表,保证后续处理顺序和标签顺序对齐 - 第二步:统一做预处理,所有样本必须用完全一致的预处理参数,否则会出现空间不对齐、分布偏移的问题:
- 所有图像配准到MNI152标准模板
- 重采样到相同的空间分辨率与尺寸
- 做颅骨剥离,去除非脑组织的背景区域
- 做信号强度归一化(z-score标准化或者缩放到0~1区间)
- 第三步:根据你用的CNN类型转成对应输入格式:
- 用3D CNN:预处理完的3D脑体积直接补一个通道维度,最终所有样本拼成形状为
(样本数, 通道数, x, y, z)的张量即可输入 - 用2D CNN:按统一规则切分2D切片后,拼成形状为
(切片样本数, 通道数, x, y)的张量即可
- 用3D CNN:预处理完的3D脑体积直接补一个通道维度,最终所有样本拼成形状为
- 存储建议:100例样本的数据量不大,预处理完可以直接存为
.npy或者.h5格式,训练时直接加载即可;如果后续要扩容数据集,可以直接写PyTorch/TensorFlow的自定义Dataset类,在线读取+预处理,不用一次性把所有数据读进内存。
批量处理参考代码:
import os import glob import numpy as np import pandas as pd from nilearn import image, datasets # 加载标准MNI152模板作为配准参考 target_template = datasets.load_mni152_template() # 收集所有nii文件路径 nii_root = "./cobre_raw" # 替换为你的数据集存储路径 file_list = sorted(glob.glob(os.path.join(nii_root, "**/*.nii"), recursive=True)) all_img_arr = [] for file_path in file_list: # 加载单例图像 img = image.load_img(file_path) # 配准重采样到标准模板空间 resampled_img = image.resample_to_img(img, target_template, interpolation="continuous") # 转numpy数组 img_arr = resampled_img.get_fdata() # 强度z-score归一化 img_arr = (img_arr - img_arr.mean()) / img_arr.std() all_img_arr.append(img_arr) # 拼接为(样本数, x, y, z)格式的数组,后续按需加通道维度 all_data = np.stack(all_img_arr, axis=0)
2. 切片选取规则
不需要默认只选中间位置的单张切片,切片选择完全匹配你的任务类型即可,核心原则是所有样本必须用完全一致的切片索引规则:
- 首先先过滤无效切片:每个Nifti文件首尾的切片大多是无脑组织的纯背景,你可以遍历每个切片的非零像素占比,把占比低于阈值(比如<10%)的切片直接排除,剩下的就是包含有效脑组织的切片区间,150张原始切片一般能筛出80~100张有效切片。
- 如果用2D CNN做疾病分类,三种常用选法:
- 计算资源有限时:选取有效区间内覆盖研究相关核心脑区的10~20张切片(比如COBRE是精神分裂症数据集,优先选覆盖颞叶、海马、前额叶的切片),不要只选1张中间切片,单张切片包含的信息太少,模型极易过拟合
- 追求效果时:把所有有效切片都作为独立训练样本,每个切片继承对应受试者的标签,训练时做切片级分类,推理时把同一个受试者所有切片的预测结果做多数投票,得到最终的受试者级分类结果,效果远好于单切片输入
- 如果是特定脑区的针对性研究:直接选取对应脑区所在的切片位置即可
- 如果用3D CNN:不需要单独选切片,把预处理完的3D脑体积裁掉边缘全零区域后,缩放到模型要求的固定输入尺寸(比如64×64×64、128×128×128)即可输入,能保留全部空间信息。
有效切片筛选参考代码:
def get_valid_slices(img_arr, threshold=0.1): valid_z_idx = [] z_total = img_arr.shape[-1] for z in range(z_total): slice_data = img_arr[:, :, z] valid_ratio = np.count_nonzero(slice_data) / slice_data.size if valid_ratio > threshold: valid_z_idx.append(z) return valid_z_idx[0], valid_z_idx[-1] # 返回有效切片的起止索引,所有样本统一用这个区间
3. 标签配置方法
mask文件仅用于脑区分割、ROI信号提取等任务,和分类标签的配置完全无关,不需要依赖mask打标签。
标签配置的具体方法:
- COBRE是公开的精神分裂症数据集,每个受试者的诊断标签(健康对照/精神分裂症患者)在数据集配套的元数据文件里已经给出,你只需要把Nifti文件名里的受试者ID提取出来,和元数据里的ID做匹配,就能拿到每个文件对应的标签。
- 非常推荐用CSV文件存储路径-标签映射关系,CSV只需要两列:
file_path:存储每个.nii文件的完整绝对路径label:存储对应标签,比如健康对照标0,患者标1
后续不管做预处理还是写数据集加载逻辑,直接读取这个CSV就能拿到对应关系,不会出现标签错配的问题。
标签CSV生成参考代码:
# 提前整理元数据里的受试者ID-标签对应关系,示例如下 id_label_map = { "sub0001": 0, "sub0002": 1, # 补全所有受试者的对应关系即可 } csv_records = [] for file_path in file_list: # 从文件名提取受试者ID,根据你自己的文件名命名规则调整截取逻辑 file_name = os.path.basename(file_path) sub_id = file_name.split("_")[0] csv_records.append({ "file_path": file_path, "label": id_label_map[sub_id] }) # 存储为CSV文件 pd.DataFrame(csv_records).to_csv("./cobre_label_map.csv", index=False)
推荐学习资源
- Nilearn官方文档中的神经影像机器学习章节,包含批量处理、特征提取、模型训练的完整流程示例,不要仅参考单文件可视化部分的内容
- 你所用深度学习框架(PyTorch/TensorFlow)的自定义Dataset实现教程,掌握自定义数据加载逻辑后可以适配任意格式的数据集
- 开源的3D CNN脑疾病分类实操项目,重点参考其数据加载、预处理部分的实现逻辑,不需要从零开始踩坑
内容的提问来源于stack exchange,提问作者Ashima Tyagi
相关产品推荐
相关产品推荐

