简介:VBM软件下载与教程包面向神经影像科研人员及临床研究者,解决基于体素的形态学分析中软件获取与入门操作难题。该工具作为SPM插件在MATLAB环境中运行,可完成MRI图像标准化、组织分割及灰质密度校正等核心步骤,适用于脑疾病灰质改变、老化与认知发展等研究场景。压缩包共含21个文件,以18个m源文件为主,涵盖核心函数与运算脚本;另附PDF使用手册、txt说明及man文件,分别用于操作指南、快速查阅与辅助说明,整体仅226KB,体积小巧便于下载部署。通过这套资料,读者可获得对应版本的VBM插件及其配套代码,并结合手册掌握配准、分割和统计参数图生成流程;适合SPM初学者跟随教程逐步实践,也能帮助进阶用户快速定位函数功能与参数含义。目前已有1776人学习下载,是入门VBM分析较为实用的轻量资源。
1. VBM 软件选型与落地:从 SPM+CAT12 安装到批处理全程拆解
VBM(Voxel-Based Morphometry,体素形态学分析)是从 T1 结构像里逐体素比较灰质体积/密度,找出两组被试在全脑哪些地方灰质显著变小。别小看这条流水线,配准、分割、调制、平滑、统计校正每一环都在影响结果。要是拿 SPM 自带的 Segment 直接跑老年大脑或质量一般的样本,很容易在配准环节翻车。
这篇笔记把 VBM 的软件选型、安装、数据整理、批处理实测到统计校正全部拆开,让你拿到资源后直接从 DICOM 走到显著团块坐标。刚接手结构像、准备做组间灰质对比的话,这份能帮你少折腾两周。下文涉及的每一处参数我都尽量写清边界和理由,你可以照抄,也可以按自己样本量微调。
2. 工具链安装:MATLAB 版本确认、SPM 与 CAT12 的协同配置
2.1 为什么要选 SPM+CAT12 而不是只用 SPM 自带工具
VBM 的底层算法本质上做三件事:把所有人的脑对齐到同一个模板空间,把图像分割成灰质/白质/脑脊液,再对灰质图做统计比较。SPM12 提供主框架,内置的 Segment 功能把统一分割和配准一起完成,但这一步在扫描质量一般的数据上会产生两种典型问题:一是灰质分割受脑膜、血管信号干扰,二是配准变形量不够,老化和萎缩明显的脑很难被拉回模板。
CAT12 是建立在 SPM 之上的扩展工具包,它把分割、配准、噪声校正、质量检查做成了一条自动流水线,还引入了更稳的分割模型。同一个样本,用两种工具跑出来的灰质体积相关性可能到 0.9 以上,但 CAT12 在异常点数量和局部配准精度上明显更稳。实际项目里我也见过有团队只用 SPM 的 VBM 工具跑出结果,但后期要做大量手动清理,因为分割图里混进了不少非脑组织。
选型建议很直接:如果你只处理几十个健康成年人、图像质量都很理想,SPM 自带功能勉强够用;如果样本里有老年被试、扫描仪批次不齐、或者你想同时拿灰质和白质体积做分析,直接上 SPM12+CAT12,省下的时间足够你多跑两轮统计验证。
2.2 目录布局、解压与 MATLAB 路径配置
CAT12 运行在 SPM12 内部,两者都要下载完整压缩包。SPM12 压缩包不大,CAT12 因为带了不少预处理模型和模板文件,解压后体积明显更大,常见情形是几百 MB 级别。下载完先把工具包放到和数据隔离的目录,我一般放在/data/tools/下面,SPM12 解压成spm12,CAT12 解压成cat12。这样路径清楚,后续写脚本也不会因为目录嵌套太深而报错。
解压时注意一点:两个包解压后,目录下直接就是spm.m、cat_install_ui.m这类入口文件。如果解压后多了一层同名文件夹,说明你解压了嵌套结构,需要把addpath指到真正含有spm.m的那一层,否则后面一启动就报找不到函数。
在 MATLAB 里配置路径时,我习惯不直接改 MATLAB 的全局路径,而是写一个独立的启动脚本:
% 保存为 startup_vbm.m % 每次新开 MATLAB 后执行一次即可 spm_dir = '/data/tools/spm12'; cat_dir = '/data/tools/cat12'; addpath(spm_dir); addpath(cat_dir); % 无界面批处理时需要初始化 SPM job 管理器 spm('defaults', 'FMRI'); spm_jobman('initcfg'); disp('SPM12 and CAT12 are ready.');这段代码里,addpath把两个工具目录加入当前会话的搜索路径。spm('defaults', 'FMRI')的作用不是区分 FMRI 还是结构像,而是提前加载 SPM 的默认全局设置,避免后面批量跑 job 时出现“Defaults not set”之类的提示。spm_jobman('initcfg')则让 job 管理器知道配置已经就绪,这一步在-nodisplay的服务器环境里尤其重要,不做的话批处理很可能卡在初始化阶段。
配置成功后,在 MATLAB 命令行执行which cat_install_ui,如果能返回cat12目录下的路径,说明 CAT12 已经被正确加载。这一步是安装阶段最直接的验证方式,比打开 GUI 看图标更可靠。
2.3 MATLAB 版本依赖与最小冒烟测试
CAT12 对 MATLAB 版本有窗口要求,常见支持区间是 R2015b 到 R2020a。新版 MATLAB 理论上能跑,但偶尔会因为编译器接口变化导致个别 MEX 文件需要重新编译,新手遇到这种情况很难处理。我通常会直接选 R2018b 或 R2019a,在这个场景下表现稳定,网上能找到的踩坑记录也最少。
装完工具包后不要急着处理全量数据,先做一次最小冒烟测试:随便挑一张小尺寸 T1 图,跑一次完整分割。这个测试能一次性暴露三类问题:MEX 文件是否匹配、模板路径是否正确、输出文件能否正常写入。如果冒烟测试失败,优先检查 MATLAB 版本和工具包目录层级,这两个原因占了安装报错的大头。
CAT12 和 SPM12 的典型角色分工如下:
| 组件 | 作用 | 安装后关键文件 |
|---|---|---|
| SPM12 | 主框架:图像显示、配准、统计建模 | spm.m,spm_jobman.m |
| CAT12 | 分割扩展:灰质/白质提取、质量检查 | cat_install_ui.m,cat_batch_cat.m |
我在服务器上跑批处理时,经常连 GUI 都不打开。MATLAB 的-nodisplay模式加上上面的startup_vbm.m,完全可以完成从分割到统计的全流程。唯一的区别是结果检查要依赖spm_check_registration这类脚本,或者直接把分割图导出成图片看,这会在第 6 章细说。
3. 数据准备:DICOM 转 NIfTI、目录结构与命名规范
3.1 先把原始数据整理成 BIDS 风格
VBM 分析的数据源头大多是医院或队列项目拿到的原始 DICOM,文件名经常是乱码,还混着局部定位像、B1 校正像等多个序列。我接手的第一个模拟项目X就是这样,几千个 DICOM 文件堆在一起,光靠文件名根本分不清哪张是 T1。后来我学乖了,所有数据先重排成类 BIDS 结构:
StudyX/ sub-001/ anat/ sub-001_T1w.nii sub-002/ anat/ sub-002_T1w.niiBIDS 结构本身不直接参与 VBM 计算,但它有两个实际好处:一是脚本可以用统一规则遍历所有受试者,不用在代码里硬编码每个文件的路径;二是排查问题时能快速定位是哪一步输出异常。对新手来说,这个目录习惯能省掉不少低级错误。
3.2 DICOM 转 NIfTI 的批量循环
从 DICOM 到 NIfTI 的转换,我一般用 dcm2niix。它能处理大多数厂商的私有格式,自动判断序列类型和方向信息,生成的 NIfTI 文件还附带头部元数据。转换脚本很简单:
for d in /data/StudyX/raw/sub-*/DICOM; do sid=$(basename "$(dirname "$d")") mkdir -p "/data/StudyX/${sid}/anat" dcm2niix -z y -b y -f "${sid}_%s" -o "/data/StudyX/${sid}/anat" "$d" done这段脚本假设原始 DICOM 已经按受试者分目录存放,sid变量提取的是受试者目录名。-z y表示输出压缩后的.nii.gz,-b y表示同时生成 JSON 元数据文件,-f "${sid}_%s"把输出文件名定为受试者 ID 加序列标签。参数说明里最需要注意的是-f:不设这个参数时,dcm2niix 会按原始 DICOM 文件名生成输出,很可能出现文件名和受试者 ID 对不上的情况。
转换完成后,检查每个受试者目录下是否只有一个 T1 序列。有时扫描协议会包含两个 T1 序列,一个是定位用的低分辨率版本,一个是高分辨率结构化序列。VBM 只接受后者,所以在整理目录时就要确认清楚。
3.3 转换后的三重检查:尺寸、方向矩阵、覆盖范围
转换完不能直接开跑,我习惯先做三件事。第一,检查分辨率和矩阵尺寸,确认体素大小在 1mm 左右,矩阵维度符合预期;第二,检查方向信息,确认图像没有发生左右翻转或头脚颠倒;第三,检查扫描覆盖范围,看头颅底部有没有被截断。
用命令行检查方向的常用方式是查看 NIfTI 头文件里的 sform 信息:
fslhd /data/StudyX/sub-001/anat/sub-001_T1w.nii.gz | grep -E "qform|sform"如果 sform 全为 0,说明方向信息可能没写进文件,后续分割结果会非常不稳定。这种文件要重新转换,或者用专门工具重新定向。覆盖范围检查更简单:打开图像看一眼底部是否包含小脑和脑干下部。如果扫描范围切掉了小脑,VBM 分割时会把灰质图谱截断,统计阶段就会出现大片异常的脑干团块。
3.4 输入质量对 VBM 的影响边界
T1 图像质量直接决定分割可靠性。最常见的输入问题是运动伪影和金属伪影。运动伪影表现为脑表面边缘发虚,分割算法会把灰质边界误判成白质;金属伪影通常出现在口腔区,会导致附近组织信号缺失。这类有问题的数据最好不要一股脑塞进自动流水线,否则后期清理比分析还累。
CAT12 自带质量检查功能,但那是处理完才看的。更实际的做法是在转换阶段就快速浏览一张中间层切片,排除明显的运动模糊和截断问题。等到全部数据分割完,再做系统性的 QA 评分,这个我在第 6 章会详述。
4. 批量分割与统计建模:CAT12 批处理脚本实测
4.1 构造 estimation + write 的批处理 job
CAT12 最常用的批处理入口是estwrite,它同时完成两件事:估计分割参数,并把分割结果写入磁盘。只用 estimate 不勾 write 是新手最容易犯的错误之一,后面第 5 章会专门讲。先看代码:
clear matlabbatch p = '/data/StudyX/'; subs = dir(fullfile(p, 'sub-*')); for i = 1:numel(subs) subj_path = fullfile(p, subs(i).name, 'anat', [subs(i).name '_T1w.nii.gz']); matlabbatch{1}.spm.tools.cat.estwrite.data{i, 1} = subj_path; end % 输出灰质和白质,不输出噪声图 matlabbatch{1}.spm.tools.cat.estwrite.output.GM = 1; matlabbatch{1}.spm.tools.cat.estwrite.output.WM = 1; matlabbatch{1}.spm.tools.cat.estwrite.output.bias = 0; % 使用 CAT12 内部默认模板,不手动指定 TPM matlabbatch{1}.spm.tools.cat.estwrite.opts.tpm = {''}; % 关闭调试输出,避免日志过长 matlabbatch{1}.spm.tools.cat.estwrite.extopts.verbosity = 0; spm_jobman('run', matlabbatch);这段脚本先遍历StudyX下的所有受试者目录,逐个构造 T1 文件路径。output.GM=1和output.WM=1分别要求输出灰质和白质分割图,bias=0表示不输出偏置场校正图,节省磁盘空间。opts.tpm我写成空字符串,目的是让 CAT12 使用内部默认模板;如果手动指定,路径必须精确匹配你安装的 CAT12 模板目录,错一点就会报错。
脚本跑完后,每个受试者目录下会生成一组以m0wrp开头的文件,比如m0wrp1sub-001_T1w.nii.gz和m0wrp2sub-001_T1w.nii.gz。m0表示调制的原生空间灰质图,wrp表示该图已经配准并写入模板空间。后续统计分析用的就是这些文件。
4.2 调制、平滑与体素大小的选择
CAT12 分割完后,最常用的统计输入是调制的灰质图。调制(modulation)是把分割概率值乘以配准过程中的体积变化量,这样每个体素的数值就近似反映灰质体积,而不是单纯的灰质密度。如果不调制,结果解释的是灰质浓度,两者在老化和萎缩实验中往往结论差别很大。做组间体积对比时,我一般默认打开调制,这也是多数 VBM 研究的标准做法。
平滑核的选择直接影响统计灵敏度和空间分辨率。文献里最常见的是 8mm FWHM 的高斯核。8mm 的好处是符合模板平滑特性的假设,统计结果比较稳;6mm 更敏感但更容易受个体差异影响;12mm 适合做团块级判断,但会丢失精细空间信息。我自己的习惯是先跑一次 8mm,如果结果团块零散且没通过校正,再试 6mm 或 10mm 作为敏感性分析,但最终报告以预设参数为主,不能等看到结果再临时挑一个能出显著性的。
体素大小的选择在 CAT12 里通常是重采样到模板空间时的设置。常见做法是把体素设为 1.5mm,既能保证计算速度,又不会让图像过于平滑。如果你需要更精细的团块定位,可以设成 1mm,但计算时间和内存消耗会明显上升。批量处理几十个样本时,1.5mm 往往是性价比最高的选择。
4.3 第二层统计建模:双样本 t 检验与协变量
分割完成只是第一层处理,真正的统计问题在第二层。研究设计常见的场景是两组被试做灰质体积对比,同时控制年龄和总颅内体积。用 SPM 的 factorial design 模块实现:
clear matlabbatch % 组1:健康对照 matlabbatch{1}.spm.stats.factorial_design.des.t2.scans1 = group1_warps; % 组2:疾病组 matlabbatch{1}.spm.stats.factorial_design.des.t2.scans2 = group2_warps; % 协变量:年龄 matlabbatch{1}.spm.stats.factorial_design.cov(1).c = age_vector; matlabbatch{1}.spm.stats.factorial_design.cov(1).cname = 'Age'; matlabbatch{1}.spm.stats.factorial_design.cov(1).iCC = 1; % 协变量:总颅内体积,从分割结果中读取 matlabbatch{1}.spm.stats.factorial_design.cov(2).c = tiv_vector; matlabbatch{1}.spm.stats.factorial_design.cov(2).cname = 'TIV'; matlabbatch{1}.spm.stats.factorial_design.cov(2).iCC = 1; matlabbatch{1}.spm.stats.factorial_design.dir = {[p '/stats']}; matlabbatch{1}.spm.stats.factorial_design.masking.tm.tma.which = 1; spm_jobman('run', matlabbatch);des.t2.scans1和des.t2.scans2分别接收两组被试的调制灰质图路径,cov结构里可以加入任意数量的连续协变量。iCC表示协变量和受试者的对应关系,设成 1 时表示一个受试者一个值。我在实际项目中一定会放入年龄和总颅内体积这两个协变量。年龄因为灰质体积随年龄下降,不放进去很容易把年龄差异误判成疾病差异;总颅内体积则是用来校正头大小差异,这是 VBM 领域公认需要控制的因素。
设计矩阵建好后,下一步是估计和对比设置。对比通常设为疾病组减对照组,得到一个负方向的 t 对比,表示疾病组灰质体积显著小于对照组。做完这步,SPM 会生成spmT_0001.nii文件,这就是携带统计值的全脑图。
4.4 阈值、校正方法与结果读取方式
统计图不等于结论,必须做多重比较校正。VBM 全脑有上百万个体素,不做校正随便设个 p<0.001 就会得到一大片假阳性团块。常见做法是使用 FWE(Family-Wise Error)校正,在体素水平控制假阳性;或者使用 FDR 校正。我的态度很明确:给论文或导师看的结果至少做到 FWE 校正 p<0.05,或者 cluster-level FWE 校正通过,否则后面审稿意见会非常难看。
在 SPM 里读取结果时,设定阈值的界面需要两层设置:一个是体素水平的 p 值,一个是团块范围的扩展阈值。扩展阈值一般设为 50 个体素以上,用来滤掉孤立的小团块。解读结果时,看的不只是 peak 坐标,还要看团块覆盖了哪些脑区,是否与先验假设一致。我遇到过一个情况,结果出来的显著团块落在脑室边缘的灰质核团上,看起来离奇,最后发现是分割残留导致。
5. 避坑与常见问题:四个几乎必踩的 VBM 大坑
5.1 分割跑完但找不到 m0wrp 输出文件
现象:批处理日志显示每个受试者都跑完了,但进目录一看,只有sub-001_T1w.nii和几个中间文件,一个m0wrp1开头的文件都没有。
原因:这是我把estwrite的字段写错时踩过的坑。CAT12 的批处理 job 里有 estimate 和 write 两种模式。如果你不小心用了est而不是estwrite,或者界面里只勾选了 estimate,算法只会估计分割参数并生成中间结果,不会输出调制图。另一种可能是output.GM被设成了 0,系统认为你不需要灰质图,自然不会写m0wrp1。
解决:检查 job 结构,确认spm.tools.cat.estwrite是 estwrite 而非 est,同时确认output.GM=1。已经跑完的数据不用重跑全部,只把输出缺失的受试者挑出来重新放进 batch 就行。这个坑的隐蔽性在于日志不报错,你必须去文件系统层面确认输出。
5.2 批处理脚本报 Undefined function 或 job 字段错误
现象:脚本一运行,MATLAB 直接抛错,提示找不到某个函数,或者提示matlabbatch里某个字段不存在。
原因:这个错误我碰到过两次。一次是 CAT12 版本升级后,job 字段名变了,老脚本直接用旧字段,结果字段被 SPM job 管理器拒绝;另一次是addpath没加对,CAT12 的路径没生效,导致cat_install_ui能运行但底层的分割函数找不到。
解决:先执行which cat12和which cat_install_ui,确认路径加载正常。然后打开 CAT12 的 GUI,手工配置一次全部参数,再通过菜单里的导出 batch 按钮生成完整 job 脚本。这个方法能拿到当前版本真正接受的字段结构,比对着旧教程改字段靠谱很多。从那以后我再也不敢跨版本直接复制 batch 脚本。
5.3 图像方向翻转导致分割结果一塌糊涂
现象:某个受试者的分割图看起来非常奇怪,灰质图整体前后颠倒,或者左右翻转,统计阶段这个样本成为明显的异常点。
原因:DICOM 转 NIfTI 时方向信息读取失败,最常见的诱因是原始 DICOM 缺少方向标签,或者扫描序列是倾斜采集的。转换后 sform/qform 字段不完整,CAT12 读到的图像方向就错了。还有一个我没少见的场景:手动把 NIfTI 文件从一个平台拷到另一个平台,路径没问题,但方向信息被某一步误改了。
解决:用fslhd检查 qform/sform 值,确认方向矩阵非零且符合 RPI 等常见方向约定。如果方向有问题,重新转换原始 DICOM,或者用专门工具把方向重设为标准方向。处理完再做一次分割冒烟测试。方向问题不会报错,只会安静地产生错误结果,这也是它比报错更危险的原因。
5.4 统计显著团块很多但全部落在不合理的区域
现象:双样本 t 检验结果通过校正,但显著团块分布在脑室边缘、头皮附近或血管区域,大小和分布都不符合解剖预期。
原因:这个坑本质上是输入数据质量不行。某些受试者的分割图里有明显的非脑组织残留,这些残留经过平滑后会形成一片区域性假阳性。另一个推手是平滑核太小,没办法把体素噪声压下去,导致局部极值多到不可控。有时候一个组的图像质量系统性地差于另一组,也会产生同样的问题。
解决:回到分割阶段,用 CAT12 的 QA 工具给每个样本打质量分。凡是 QA 标记为异常或可疑的样本,都要查看原始 T1 和分割掩膜。我处理过一批数据,某台扫描仪出的图像全部带运动伪影,QA 显示异常,剔除这些样本后统计结果明显变干净。另外,把平滑核从 6mm 换到 8mm 也能有效减少碎片团块。记住一个原则:统计结果必须能在大脑解剖上讲得通,否则先查数据质量,别急着改统计参数。
6. 验证与进阶:QA 评分、结果可重复性与论文参数报告
6.1 用 CAT12 的 QA 工具扫描全部样本
CAT12 的 job 里有一个专门的 QA 模块,跑完分割后可以生成所有受试者的质量评分和诊断图。处理完一批数据后,我会把 QA 输出的 xml 文件统一收集起来,用脚本解析出每个样本的灰质体积、分割质量和异常标记。第一步先看有没有红色异常,第二步检查灰质体积分布的离群值,第三步把可疑样本的图全部翻一遍再决定去留。
6.2 重复运行稳定性:算一次灰质总量 ICC
想确认整条处理流程是否稳定,可以在同参数下把同一批数据跑两遍,然后对每个受试者的灰质总体积做一致性比较。两遍结果基本一致,说明流程本身没有随机性,数据结果可信。具体的 ICC 计算可以导成 CSV,用常规统计软件完成。我自己的习惯是至少抽三个样本重跑分割,确认输出的 m0wrp 图数值一致,再继续后续分析。
6.3 论文和报告里必须写清的 VBM 参数
常见期刊对 VBM 方法描述写得比较精简,但审稿人经常追问五件事:软件版本、分割算法、模板空间、调制方式、平滑核大小。如果你不写清楚,读者无法复现,复现不了就等于结果作废。报告模板可以这样组织:
| 参数项 | 填写示例 |
|---|---|
| 软件与版本 | SPM12 + CAT12 |
| T1 重采样体素 | 1.5mm |
| 分割方法 | 统一分割 + 内置模板 |
| 调制 | 调制(体积分析) |
| 平滑核 | 8mm FWHM |
| 统计模型 | 双样本 t 检验 + 年龄/TIV 协变量 |
| 校正方法 | FWE 体素水平 p<0.05 |
这套参数表写进方法部分,基本不会让审稿人挑出信息缺失。另一个容易被忽略的细节是模板坐标系版本,不同版本的模板会给出略有差异的 MNI 坐标,严谨的报告会标注模板来源和版本号。
几乎每个 VBM 项目我都坚持一条流程:先跑一个 5 人小样本,把 QA 图、方向矩阵、输出文件全部确认无误,再跑全量数据。这个习惯帮我拦下过不止一次由方向信息和批处理脚本引发的大规模返工。希望这份拆解能帮你在自己的数据上少踩同样的坑,顺利拿到稳定、可复现的结果。
本文还有配套的精品资源,点击获取