简介这是基于MATLAB的CAT12工具箱专为神经影像领域的体素形态计量学VBM分析设计面向需要处理结构磁共振数据、比较不同个体或群体脑灰质/白质形态差异的研究者。压缩包共518个文件约124MB以.m源码、mex编译函数、.nii影像数据、.gii表面网格为主另有Annot分区文件、模板与HTML帮助文档构成完整的预处理-分割-统计-可视化链路。已有2824人学习下载既适合刚开始接触VBM的医学影像学生也适合需要批处理多被试数据的科研人员。包内除核心算法外还提供示例数据与表面配准模板可直接跑通从原始sMRI到灰质体积比较的典型流程同时附带多平台mex版本便于Windows/Linux/Mac环境复用。该工具箱支持灰质、白质和脑脊液分割并可结合统计参数映射逐体素检验能支撑神经退行性疾病、精神疾病等领域的脑结构差异研究。1. CAT12 到底是什么先搞清楚它和 SPM 的老关系上个月有做认知实验的师弟抱着一块硬盘来找我里面是两百多份 T1 结构像。他导师的要求只有一句比较两组被试的灰质体积差异。他查了一圈工具最后停在 CAT12 这个名词上问我是不是要配合 SPM 用。这个问题问得很典型——CAT12 不是独立软件它是挂在 SPM 生态里的一个工具箱专攻基于体素的形态计量学VBM分析输入是 T1 加权结构像输出是逐体素的灰质体积统计图。它解决的痛点很直接不同人大脑形状和体积天然不同脑区之间又没有清晰边界没法像 ROI 那样直接量体积。这篇笔记就按我实际处理数据的顺序把 CAT12 从分割参数到统计推断的关键步骤和踩坑记录都过一遍给想用 VBM 做结构像分析的人一条能直接走通的路。2. VBM 分析的核心逻辑分割、配准、调制、平滑四步走2.1 VBM 为什么能看灰质体积变化不是在做“形状比较”VBM 的思路不是把大脑掰成同一个形状再量而是把所有被试的 T1 像放到同一个标准空间里逐体素比较灰质“浓度”或“体积”。这个流程可以拆成四个阶段第一步是把每个被试的 T1 分割成灰质、白质、脑脊液的概率图每个体素保留一个 0 到 1 之间的概率值第二步是用 DARTEL 这类非线性配准算法把所有被试的灰质图对齐到同一模板空间第三步是调制modulation这一步最关键因为单纯配准会把体积变化“挤压”进体素强度里如果不做调制灰质体积差异就会被配准过程吃掉第四步是用高斯核做平滑让离散的体素数据变得连续符合统计检验的随机场假设。很多人第一次听到“平滑”会不理解平滑不是把细节抹掉了对自然图像确实是坏事但 VBM 里的统计是以体素为单位做的平滑本质上是在做信号聚合和噪声抑制同时让结果不依赖于体素网格的精确对齐。平滑核大小一般选 6 到 10 毫米全宽半高FWHM选 4 毫米或更小往往会让结果碎片化选 15 毫米以上又容易把真实差异抹平这个选择直接影响能不能统计出结果。2.2 CAT12 与 SPM 的 DARTEL 流程为什么选 CAT12传统的 SPM VBM 流程需要手动串好几个模块先用 New Segment 做分割再用 DARTEL 建立模板、把灰质图配准到 MNI 空间最后还要自己写 batch 串联这些步骤。CAT12 把这整条流水线整合成了一个入口在 SPM 菜单里选择 CAT12再选 Segment选好 T1 文件点运行分割、配准、调制、平滑一次完成。CAT12 相比 SPM 自带流程还有几个优势用的是自适应分割算法对扫描仪品牌和场强差异更鲁棒内置了质量检查QA报告能直观看到每个被试的图像噪声水平和配准质量还额外支持皮层厚度计算不只能做体素水平的灰质体积分析。下表是我从实际使用角度做的对比对比维度SPM 经典 DARTEL 流程CAT12 流程操作步骤分割、建模板、配准、调制、平滑多步串联单入口一键完成质量检查无内置 QA需手动查看每一步输出每次运行生成 xml 质量报告皮层厚度不支持支持处理速度取决于手动 batch 优化内置并行与优化策略新手友好度流程复杂易漏步骤界面和脚本相对清晰一句话总结如果你手上已有 SPM装一个 CAT12 工具箱就能跑 VBM不需要另配独立软件如果你还没装 SPM就得先把 SPM 装好再挂载 CAT12两者版本要注意匹配。2.3 从 T1 到 mwp1一次预处理到底产出了什么跑完 Segment 之后输出目录里会出现一堆带前缀的文件很多人在这里看懵。以最核心的灰质输出为例文件名里每个字母都有含义m 代表调制过modulatedw 代表已经配准到标准空间warpedp 代表概率图probability后面的 1 代表灰质。也就是说mwp1 文件就是“调制后、标准化到 MNI 空间、灰质概率图”这才是你后面统计真正要用的数据。前缀含义是否用于 VBM 统计mwp1调制 配准 灰质概率图是核心文件m0wp1未调制的灰质概率图否体积信息已丢p1原始空间分割出的灰质仅用于检查s 前缀分割后各组织视情况用于二次处理xml质量检查报告用于质控这里有个常见的理解偏差很多人以为 p1 是灰质体积直接拿去做组间比较。但 p1 是“灰质概率”没有经过调制不同被试由于全脑体积差异和配准伸缩体素值并不直接反映体积。我一般会把 mwp1 和 wc1 命名规则打印出来贴在工位上防止哪天顺手选错文件。3. 从原始 T1 到预处理完成一版可直接复现的 CAT12 操作路径3.1 数据组织目录结构、格式与命名跑预处理之前数据目录一定要整理干净。CAT12 对文件名和路径敏感路径里有中文或者空格MATLAB 解析很容易出问题。我一般会建两层目录第一层按研究分组第二层按被试编号T1 文件统一命名为 sub-001_T1.nii 这种风格。头部信息比如扫描参数建议用 MI Toolkit 或 SPM 自带的 Display 检查一遍确认方向信息完整、原点位置合理。下面是推荐的目录结构/data/VBM_raw ├── group1 │ ├── sub-001 │ │ └── sub-001_T1.nii │ ├── sub-002 │ │ └── sub-002_T1.nii │ └── ... └── group2 ├── sub-021 │ └── sub-021_T1.nii └── ...文件格式优先使用 .nii 或 .nii.gz尽量避免 .nii 嵌套文件夹网上下载的原始数据经常是 DICOM建议先用 dcm2nii 批量转。转换时注意保留原始分辨率信息不要顺手把图像重新采样到各向同性重采样会让后续分割引入不必要的误差。我习惯在转换后用 python 脚本读一遍 nifti header检查 voxel size 是否在合理范围常见为 1mm 或 1.2mm 各向同性或接近各向同性。3.2 跑通 SegmentGUI 操作与参数含义数据准备完毕打开 MATLAB保证 SPM12 和 CAT12 都在路径里命令行输入 spm 启动图形界面依次点SPM 菜单栏 → CAT12 → Segment。界面会要求选择 T1 图像文件可以多选确认后默认参数其实就能跑出结果。但我建议至少调整以下几个选项Segmentation Estim估计参数保持默认即可新版 CAT12 会自动检测 TPM 模板。Output 里的“GM Output”开关 Native、Modulated、DARTEL Imported 三项VBM 统计只保留 DARTEL imported modulated 的那个文件其他可以先不生成能省一大半磁盘空间。Affine Registration 设置默认 4mm 分辨率质量差的图像可改成 4mm 精度优先。如果是批处理多个被试建议直接用 job 脚本而不是一个个点 GUI。下面这个批量脚本是我日常用的模板% CAT12 批量 Segment 脚本运行前确认 SPM 和 CAT12 已在路径中 spm(defaults, FMRI); spm_jobman(initcfg); % 路径换成你自己的数据目录 data_dir /data/VBM_raw; files spm_select(FPListRec, data_dir, ^sub-.*T1.*\.nii$); matlabbatch{1}.spm.tools.cat.estwrite.data cellstr(files); matlabbatch{1}.spm.tools.cat.estwrite.output.GM.native 0; % 不输出原始空间 GM matlabbatch{1}.spm.tools.cat.estwrite.output.GM.mod 0; % 不输出未配准 GM matlabbatch{1}.spm.tools.cat.estwrite.output.GM.dartel 1; % 输出配准到模板的 GM matlabbatch{1}.spm.tools.cat.estwrite.output.GM.mwp 1; % 输出调制后的 mwp1 文件 matlabbatch{1}.spm.tools.cat.estwrite.extopts.expertmode 1; % 打开专家模式以读取这些选项 spm_jobman(run, matlabbatch);注意 output.GM.dartel 和 output.GM.mwp 的区别前者是没调制的配准后灰质配准到 DARTEL 模板后者是调制过的统计时要用 mwp1千万别拿 dartel 输出的文件当最终结果。spm_select 用了 FPListRec 递归搜索文件名如果你的数据不是统一命名建议先把文件名改好再跑。运行过程中 SPM 会在命令行滚动日志如果某个被试中途报错整个 batch 会中断而不是跳过继续。我的做法是一个组一个组跑出问题先修掉那一例再继续避免后面全部白跑。3.3 QA 报告不只是“跑完就完”CAT12 每次 Segment 会在与输入文件同级的目录生成一个 XML 文件名字类似 cat_sub-001_T1.xml。这个文件是自动生成的质控报告包含几个核心指标噪声水平Noise、偏置场不均匀度Bias、图像质量Image Quality、分辨率Resolution。每个指标有等级A/B 代表质量好C 以下说明图像存在问题。我用 QA 报告有一条明确标准任何一个被试出现 Image Quality 等级为 C 或更低就要拉出来单独看原始 T1 图和分割结果图。不要因为样本量紧张就硬留着质量差的数据VBM 统计对离群体素极敏感一个坏数据往往能做出一个假性脑区。如果确实想保留至少要跑两次统计一次含该被试、一次不含看结果稳定性。QA 文件本身也可以用文本编辑器打开里面是 dat 结构方便你写批量脚本自动筛查全部被试的质量等级。跑完预处理后我会先用一个 Python 脚本读取全部 xml把所有 C 级以下的被试列出来再一一手动检查。4. 组间比较怎么做设计矩阵、协变量与统计推断4.1 两样本 t 检验的完整设置拿到所有 mwp1 文件接下来就是标准的 SPM 统计流程。很多人在这里有一个误区以为分组比较就是简单地把两组的 mwp1 文件路径填进 t 检验界面其实设计矩阵里还要考虑协变量。VBM 研究中最重要的协变量是脑袋大小TIV全脑总体积不同人全脑体积差异能达到 20% 以上如果不控制灰质体积的组间差异会被头大小混杂。CAT12 在预处理时也会在输出目录生成一份 TIV 估计值统计阶段可以把它作为回归协变量。在 SPM 里点Stats → Two-sample t-test然后将两组的 mwp1 文件分别填入 Group 1 和 Group 2。在 Covariates 栏添加 TIV 协变量如果你的设计里有性别或者年龄也一并加进去。下面是直接的脚本写法% 两样本 t 检验带 TIV 协变量 spm(defaults, FMRI); spm_jobman(initcfg); g1 cellstr(spm_select(FPList, /data/VBM_out/group1, ^mwp1.*\.nii$)); g2 cellstr(spm_select(FPList, /data/VBM_out/group2, ^mwp1.*\.nii$)); matlabbatch{1}.spm.stats.factorial_design.des.t2.scans1 g1; matlabbatch{1}.spm.stats.factorial_design.des.t2.scans2 g2; % TIV 协变量与被试顺序一一对应 tiv_vals [1512 1445 1587 ... 1260]; % 改成你的 TIV 数据长度等于被试总数 matlabbatch{1}.spm.stats.factorial_design.cov(1).c tiv_vals(:); matlabbatch{1}.spm.stats.factorial_design.cov(1).cname TIV; matlabbatch{1}.spm.stats.factorial_design.masking.tm.tma.ircat 1; matlabbatch{1}.spm.stats.factorial_design.masking.tm.tma.atham 1; matlabbatch{1}.spm.stats.factorial_design.masking.im 0; % 不用隐式掩膜 spm_jobman(run, matlabbatch);这里 cov(1).c 的每一行对应一个被试顺序必须跟 g1 和 g2 拼接起来的顺序完全一致。一个稳妥做法是把两组路径按名字排序后输出成一个被试顺序文件再用程序读取 TIV 列表避免手工排列错位。设计矩阵生成后点 Estimate 估算参数再点 Results 设置对比。两样本 t 检验的对比向量一般是 [-1 1]正方向表示第二组大于第一组TIV 协变量不进入对比向量因为它的目的是把全脑体积差异的方差解释掉。4.2 平滑核、显式掩膜和绝对阈值影响结果是否显著的三个隐藏开关统计结果能不能出来往往不取决于被试数量而是取决于这三个设置。第一是平滑核CAT12 默认生成的数据已经做过 8mm 平滑但如果你自己改了预处理参数统计时就要确认平滑程度是否匹配。一般推荐 8mm这个数值不是拍脑袋定的体素尺度普遍在 1.5mm配准后的残余误差在 2-4mm8mm 平滑既能压制噪声又不会过度模糊解剖边界。第二是显式掩膜可以在统计时指定一个灰质模板作为兴趣范围把脑外组织和脑白质排除在外抑制假阳性。第三是绝对阈值掩膜absolute threshold masking这个参数在实际使用中比显式掩膜更容易被忽略SPM 默认值是 0.05VBM 分析我一般调到 0.1 或 0.2。原因很简单低于这个阈值的体素灰质概率太低大概率是脑脊液或边界区域把这些体素纳入统计只会增加多重比较的负担。有人说“我不设阈值把所有体素都跑一遍不更客观”这样做的结果是统计校正范围太大很多真实但较小的效应过不了 FWE 校正。设置合理阈值不是操控结果而是缩小搜索空间到解剖学上有意义的灰质区域前提是你把阈值设置写进方法部分。4.3 结果怎么看xjView、坐标与校正方式统计跑完SPM Results 界面会显示对比后的显著性图。先看顶部面板里的峰值体素表和簇表SPM 默认报告的是未校正或 FWE 校正的体素水平 p 值。VBM 分析常见的报告方式是簇水平 FWE 校正簇大小和峰值坐标都要报告。如果只写了峰值坐标和 t 值审稿人一般会追问校正方式和簇大小。我习惯用 xjView 打开统计图它能直接读取 spmT 图像并显示脑区标签还可以导出多层横断面图。坐标要注意CAT12 预处理输出的空间是 MNI 空间报告坐标要注明是 MNI如果你想对照 Talairach 坐标做脑区定位需要用转换工具不要直接混用。另外不要在 FWE 不显著时悄悄换成 uncorrected p 0.001 再报告“显著”要么明说这是探索性分析要么把未校正的结果严格当假设生成而不下结论。5. 避坑从预处理到统计最容易翻车的五个细节5.1 分割进度卡住或报错 “No inlier”现象某被试跑到 Segmentation 阶段直接报错或者卡在 99% 不动日志里出现“No inlier”或“Error using … estimate”的提示。原因最常见的是图像原点偏离标准位置太多DARTEL 初始化搜索不到合适的配准起点其次是被试图像的方向信息缺失或错误nifti header 的 qform/sform 不一致。解决先用 SPM Display 打开该 T1检查原点位置是否在大脑中心附近。如果偏离明显用任何支持重置 origin 的工具比如 ITK-SNAP把原点重置到前联合附近再重新跑。如果图像方向信息损坏用 FSL 的 fslreorient2std 修正后再转 nii。我还会在预处理前加一步校验判断所有文件的 qform 矩阵是否接近单位阵提前拦截这批问题数据。5.2 加 TIV 协变量后结果两级反转现象第一次跑不加 TIV结果显著加上 TIV 之后不显著了或者反过来不加不显著、加了变显著。原因TIV 与组别存在强相关。比如老年组和青年组比较本来就存在整体脑体积差异TIV 解释了相当一部分组间方差要是把这种与分组高度相关的协变量和分组同时放入模型会造成多重共线性结果解读就变得很微妙。解决先做一次 TIV 的独立样本 t 检验报告两组差异。如果差异较大加协变量就要谨慎可以在模型里只把 TIV 作为相关协变量但结果中要明确说明“结果在控制 TIV 后获得”避免被质疑为统计操纵。我一般会把加不加 TIV 的两套结果都跑出来对比稳定性报告中选主分析结果补充材料里放敏感性分析。5.3 平滑核从一个数换到另一个数结果时有时无现象同一批数据用 6mm 平滑有结果换成 10mm 平滑就没结果或者反过来。原因平滑核过小噪声主导了估计平滑核过大真实效应被抹平。另外配准质量也会和平滑核相互作用配准质量差需要更大平滑来掩盖但代价是丢失细节。解决不要在结果出来后反复试平滑核挑一个“好看”的结果这是典型的多重比较 p-hacking。应该在分析前就根据体素尺寸和文献确定平滑核通常 8mm FWHM。如果真想验证稳健性把 6mm/8mm/10mm 跑完统一报告而不是挑一个。5.4 把未调制的 wc1 当体积文件用现象统计时选了一批 wc1 或 dartel 输出的灰质文件结果发现两组差异巨大但查看原始图发现只是配准不够精细差异是形状差异不是体积差异。原因未调制文件保留的是配准过程中“挤压”后的强度不能直接反映灰质体积只有在比较相对浓度时才使用。解决认准 mwp1 前缀。调制过程会把 Jacobian 行列式乘回到体素强度这样体素值和灰质体积对应。拿到输出目录后用文件名筛选工具只保留 mwp1避免后面误选。5.5 QA 报告一团黄红仍然硬用现象某个被试图像质量评级 D但统计出来的显著簇恰好包含这个被试结果不稳定删掉它结果就消失。原因噪声大或存在运动伪影的被试会在配准时产生偏倚尤其在皮层边界区域造成假阳性。小样本研究中一个坏被试的影响会被放大。解决把 QA 报告和统计影响一并做敏感性分析。先看 QA 等级排除 D 级再跑一次删掉该被试的统计验证稳定性。切记在论文方法部分写明 QA 筛选标准这不是为了让结果好看而是给读者完整的可复现信息。6. 批处理脚本与结果验证把整套流程收进一份脚本里6.1 从 T1 到平滑一步到位上面拆开讲了 Segment 和统计实际项目里我更推荐把预处理全部整理成脚本一次跑完。CAT12 支持在同一个 matlabbatch 里串联 Segment 和平滑代码如下% 一步完成分割 平移到统计所需的 mwp1 平滑文件 matlabbatch{1}.spm.tools.cat.estwrite.data cellstr(spm_select(FPListRec, ... /data/VBM_raw, ^sub-.*\.nii$)); matlabbatch{1}.spm.tools.cat.estwrite.output.GM.dartel 1; matlabbatch{1}.spm.tools.cat.estwrite.output.GM.mwp 1; matlabbatch{1}.spm.tools.cat.estwrite.extopts.expertmode 1; spm_jobman(run, matlabbatch); % 批量平滑 mwp1 文件 files spm_select(FPList, /data/VBM_out, ^mwp1.*\.nii$); matlabbatch{1}.spm.spatial.smooth.data cellstr(files); matlabbatch{1}.spm.spatial.smooth.fwhm [8 8 8]; matlabbatch{1}.spm.spatial.smooth.dtype 0; spm_jobman(run, matlabbatch);这里的 FWHM 选择了 8 毫米如果你前面的体素尺寸不是 1.5mm 等常见值平滑核可以按体素大小换算后微调但尽量保持与文献一致。需要注意的是这两个步骤放在一个 matlabbatch 里跑时第二步的文件选择依赖第一步完成如果数据量大建议拆成两个脚本在命令行分步执行方便排查问题。6.2 跑完一批数据后必须做的三件事第一件逐个打开 QA xml 报告把所有 C 级以下的被试列出来手动复核。第二件做组内或全样本平均模板用 Display 检查归一化后的平均灰质图是否清晰平滑边界有没有明显变形。第三件把每个被试的 mwp1 文件值做一次分布统计看看有没有极端离群值。这三件事做下来预处理阶段的问题基本都能暴露别急着跑统计。之前有一批 60 例的数据我没做 QA 直接跑统计结果出来一个非常漂亮的脑区兴奋之余多看了一眼发现是某个被试头皮未完全去除留下的残余信号一个体素的强度是其他所有被试的三倍。从那以后我每次处理一批结构像都会强制先做 QA 筛查和分布检查哪怕多花十分钟也值得。CAT12 的批处理确实省力但那份 xml 报告和后续验证步骤才是真正决定组间结果可信度的关键。希望帮到你。本文还有配套的精品资源点击获取