CAT12.7安装配置与VBM预处理全流程避坑指南

发布时间:2026/10/27 7:32:33
CAT12.7安装配置与VBM预处理全流程避坑指南

简介:CAT12.7 是面向脑结构 MRI 与 T1 加权图像处理学习者的 SPM 工具箱安装包,适合正在复现教程笔记、需要固定旧版本环境的研究生与神经影像初学者使用,尤其适合依赖旧版界面与函数接口的课程实验。压缩包内含 822 个文件,约 222.93MB,以 m 源码脚本、exe 与多平台 mex 二进制、nii/gii 影像与表面数据、annot 脑图谱标注、png/html 说明文档及 txt/csv 配置清单为主,并保留模板、mask 与部分 C/C++ 扩展源码,便于了解工具箱的目录组织和运行依赖。已有 1731 人学习下载。对于官方已覆盖旧版、难以再获取 CAT12.7 的读者,这份包可用于搭建稳定的 T1 处理环境,对照笔记完成分割、配准与表面指标计算等流程,也方便检查版本兼容、补全图谱与模板文件,减少因环境不一致导致的复现偏差,并对照官方更新差异判断后续迁移风险。

1. CAT12.7 安装包到底装的是什么:一份压缩包和它背后的三层依赖

把 CAT12.7 版本安装包解压开,第一层很容易让人误判:没有 setup.exe,没有安装向导,只有一堆 .m 文件、一个 cat12 目录和若干描述文件。它是典型的源码软件分发形态——放进搜索路径就能用,路径不对则一行错误都不给。本质是 SPM12 的一个工具箱插件,负责结构像的分割、配准、调制、皮层表面重建和质量控制,跑 VBM、ROI 体积、皮层厚度的流程都绕不开它。它适合已经能启动 MATLAB、手里有 T1 结构像的从业者;完全没碰过 MATLAB 的人,先补命令行和路径概念,否则每一步都是未知错误。

2. 前置环境对表:MATLAB、SPM12 与 CAT12.7 的版本咬合怎么对

装 CAT12.7 翻车的案例里,真正因为压缩包损坏的极少,绝大多数是三件套没咬合上。这一章把版本边界、目录规划和路径写入讲清楚,后面所有操作才有稳定的地基。

2.1 三个组件各自的职责与版本边界

MATLAB 是运行时和图形宿主,负责解释 .m 文件、渲染 SPM 的 batch 界面、提供并行池;SPM12 是宿主框架,提供 batch 系统、NIfTI/XML/GIfTI 读写、统计模块;CAT12.7 只负责它自己那部分算法和模板。分清楚这层关系,报错就能第一时间定位到应该检查哪一层,而不是对着 CAT12 的目录反复重装。

版本边界不必记死,记住“新的带旧的”这条经验规则就够用:MATLAB 定在 64 位 R2020a 及以上,SPM12 用近两年的修订版,CAT12.7 用压缩包原样。确实以压缩包内 README 为准,但按这个区间配,十台机器里九台不会出问题。

组件职责建议版本区间不匹配时的典型症状
MATLAB解释器、图形、并行池R2020a+ 64 位界面控件不渲染、并行启动失败
SPM12batch、图像 IO、统计近两年修订版Undefined function 'spm_jsonread'一类缺失函数
CAT12.7分割、配准、表面、QC与压缩包同名版本SPM 界面无 CAT12 面板、spm_cat12找不到

最容易踩的坑是 SPM12 用了几年前的旧包。CAT12.7 在启动时会调用 SPM 里相对新的函数和默认字段,老版本 SPM 上直接抛“未定义函数”,而这个报错的位置往往在 CAT12 的初始化代码里,看起来像是 CAT12 坏了,实际是宿主太旧。反过来,MATLAB 版本过高也有代价:新版 MATLAB 对图形句柄和字符串类型的处理更严格,极老的 SPM 修订版会出兼容问题,所以两头都别走极端。

提示:先确认spm('Ver')返回的 SPM12 修订号,再动 CAT12 的目录。宿主版本不确定时,后面所有排查都是盲猜。

2.2 目录结构与路径规划的具体做法

路径规划的原则只有一条:全英文、无空格、层级浅。Windows 上用户名是中文、把工具包放在“桌面\新建文件夹”里,是 CAT12 报错的高发来源——MATLAB 的addpath能处理中文路径,但 CAT12 内部调用外部程序、写临时文件、解析 NIfTI 头时不一定能,出问题的位置离真正原因很远。

我一般把工具和数据分开放在两个根目录下,工具只读、数据可写,备份和迁移都省事:

D:/neuro/apps/spm12/ # SPM12 解压后的根目录 D:/neuro/apps/spm12/toolbox/cat12/ # CAT12.7 放这里 D:/neuro/data/sub-001/anat/ # 原始 T1,按被试分目录 D:/neuro/work/ # 中间结果和临时文件 D:/neuro/scripts/ # 自己的批处理脚本

落位前先看一眼解压结果。压缩包解开后如果多套了一层,比如cat12.7_xxxx/cat12/...,直接整个丢进 toolbox 就会变成toolbox/cat12.7_xxxx/cat12/cat12.m,SPM 扫不到,界面上的 CAT12 面板就是不出现。正确形态是toolbox/cat12/cat12.m和toolbox/cat12/spm_cat12.m直接可见。

数据目录里不要混放 DICOM 和 NIfTI。CAT12 的 DICOM 导入会按目录扫描,混放时容易把已经转好的 NIfTI 再当输入喂一遍,或者把不同序列的 DICOM 归到同一个输出名上,结果就是文件名撞车、后写的覆盖先写的,而且不报错。

2.3 MATLAB 路径写入与启动配置

路径有两种加的方式:一次性的addpath,和固化进pathdef.m的savepath。工具包目录固定不变,就直接固化,省得每次开机重来。用addpath而不是genpath是血泪经验——genpath会把工具箱里所有子目录(包括 external、demo、旧版本兼容代码)全塞进搜索路径,函数名冲突立刻出现,典型表现是某个 SPM 函数被 CAT12 自带的同名旧版覆盖,行为变得莫名其妙。

% 一次性配置:把宿主和插件都加进搜索路径,然后固化 addpath('D:/neuro/apps/spm12'); addpath('D:/neuro/apps/spm12/toolbox/cat12'); savepath; % 写入 pathdef.m,下次启动自动生效 % 验证:两个 which 都应该返回具体路径,而不是 'not found' which spm which cat12

savepath在 MATLAB 装在系统盘 Program Files 下时会因为写权限失败,提示无法保存。这时别去改系统目录权限,改用userpath指向一个有写权限的目录,或者干脆在startup.m里保留那两行addpath,每次启动自动执行,效果一样且不动系统文件。

启动 SPM 之前先设默认参数,这一步决定后面 batch 的默认值:

spm('defaults', 'fmri'); % 设默认模态,影响默认 TR 和滤波参数 spm_jobman('initcfg'); % 初始化 batch 系统,脚本化调用前必须执行

spm('defaults','fmri')影响的是统计模块的默认值,分割流程用不到 TR,但设了没坏处,能避免 batch 里出现空字段。spm_jobman('initcfg')则是脚本化运行的必需品,漏掉它,spm_jobman('run', ...)会报配置未初始化。

2.4 多版本共存时用路径顺序说话

同一台机器上放两个 CAT12 版本做对比,是很常见的需求。这时不要靠“记住哪个是真的”,而是靠addpath的顺序——MATLAB 搜索路径是从前到后的,第一个命中的就是生效的。把要用的版本addpath在最前面(或者用addpath(..., '-begin')),另一个版本放在后面,切换时重新执行一次即可。

有个隐蔽的坑:CAT12 启动后会在基础工作区或全局变量里缓存版本信息和部分配置。切换版本后不重启 MATLAB,界面上显示的版本号可能还是旧的,看上去像是“装错了”。切换版本的正确姿势是清空工作区、重新addpath、再启动 SPM,别在同一个会话里来回切。

3. 落位与冒烟测试:解压、加路径、跑通一个被试

装完不等于能用。这一章给出一个最小闭环:从一个 T1 图像进去,从灰质图出来,全程不超过十分钟,但能暴露九成的环境问题。

3.1 三种落位方式各自的代价

放在spm12/toolbox/cat12是最省事的做法,SPM 启动时会自动扫描 toolbox 目录下的子目录并注册,面板直接出现,不需要额外addpath。代价是 SPM 升级时容易连带覆盖,升级前要单独备份一份 CAT12。

独立目录加addpath适合多版本并存和权限受限的机器,比如 SPM 装在只读的网络盘上。代价是每次启动都要保证addpath执行过,否则面板消失;用startup.m固化可以解决。

丢进 MATLAB 自己的 toolbox 目录是不推荐的做法。MATLAB 会在启动时对这个目录做缓存,新增工具箱后需要rehash toolboxcache才认,而且和 MATLAB 自带工具箱混在一起,卸载时极容易误删。

3.2 启动验证的三种方式

界面验证最直观:命令行敲spm打开 SPM 主界面,底部或侧边应该出现 CAT12 的面板区块,里面有 Segmentation、Surface、Tools 之类的入口。看不到就说明路径没生效,别急着怀疑压缩包。

命令行验证更可靠:

which cat12 % 应返回 .../toolbox/cat12/cat12.m which spm_cat12 % 应返回 .../toolbox/cat12/spm_cat12.m cat12; % 直接调起 CAT12 的独立界面

三个都通,再去看 SPM 界面。顺序反过来会浪费很多时间——界面是最后渲染的,它不出来可能只是图形问题,而不是路径问题。

3.3 最小闭环:一张 T1 进,一张灰质图出

不要一上来就跑整批数据。先拿一个被试跑通,确认输出目录有文件、文件头正确、灰度分布合理,再谈批处理。下面是最小的脚本化调用,字段名来自 CAT12 的 batch 结构:

spm('defaults', 'fmri'); spm_jobman('initcfg'); t1 = 'D:/neuro/data/sub-001/anat/sub-001_T1w.nii'; matlabbatch = {}; matlabbatch{1}.spm.tools.cat.estwrite.data = {t1}; matlabbatch{1}.spm.tools.cat.estwrite.nproc = 1; % 单被试调试,别开并行 matlabbatch{1}.spm.tools.cat.estwrite.opts.tpm = {'D:/neuro/apps/spm12/tpm/TPM.nii'}; matlabbatch{1}.spm.tools.cat.estwrite.extopts.regstr = 1; % 默认配准强度 matlabbatch{1}.spm.tools.cat.estwrite.extopts.vox = 1.5; % 输出体素,1.5mm 省时省盘 matlabbatch{1}.spm.tools.cat.estwrite.output.GM.native = 1; matlabbatch{1}.spm.tools.cat.estwrite.output.GM.mod = 1; matlabbatch{1}.spm.tools.cat.estwrite.output.GM.dartel = 1; matlabbatch{1}.spm.tools.cat.estwrite.output.WM.native = 1; matlabbatch{1}.spm.tools.cat.estwrite.output.CSF.native = 1; matlabbatch{1}.spm.tools.cat.estwrite.output.bias.native = 1; matlabbatch{1}.spm.tools.cat.estwrite.output.surface = 0; % 冒烟测试跳过表面重建 spm_jobman('run', matlabbatch);

字段名不必背。正确做法是在 SPM 界面里把 Segmentation 的选项点一遍,然后 File → Save Batch 导出成 .mat,用load打开看结构,照着抄字段。CAT12 每个小版本都可能挪动个别字段,抄界面导出的结构永远不会错。

参数说明按影响从大到小排:nproc是并行进程数,调试期一定设 1,否则报错信息会被多个进程的输出冲散;extopts.regstr是配准强度,默认档在成人结构像上够用,儿童或明显萎缩的脑可以往上调一档;extopts.vox是输出体素大小,1.5mm 相比 1.0mm 能把耗时和磁盘占用压到一半左右,做群体统计时差异通常可以接受;output.surface关掉可以跳过皮层表面重建,冒烟测试阶段没必要跑。

3.4 冒烟测试的验收标准

跑完先看目录。应该出现以mwp1、wp1、p1开头的 NIfTI,以及一个记录分割质量的文本文件。文件数量对不上,说明输出选项没生效,回去检查 batch 里output那几行。

再看图像。用 SPM 的 Display 打开p1(灰质概率图),灰质应该集中在皮层和深部核团,脑室和颅骨区域接近零。如果整张图灰蒙蒙、灰白质边界糊成一团,多半是配准没收敛,或者输入的 T1 本身有严重的运动伪影和强度不均。

最后看质量记录文件的几个指标。CAT12 会输出每个被试的配准误差和图像质量评分,这两项异常的被试,后面统计阶段会变成离群点,与其到那时再回头删,不如在冒烟阶段就记下来。

4. VBM 预处理参数:模板、配准强度与调制输出怎么选

分割参数不是玄学,每个选项背后都对应一个“你要回答什么科学问题”的判断。这一章按输出用途倒推参数,而不是罗列选项。

4.1 配准强度与模板选择

CAT12 把空间配准拆成两步:仿射配准把个体脑大致对齐到模板空间,非线性配准再细化局部形变。仿射那一步的强度是可调的,常见做法是用默认档,遇到脑形态偏离模板较远的样本(儿童、老年人、明显萎缩)往上调一档,让仿射阶段多花点时间,换取非线性阶段更少的局部扭曲。

模板选择在 CAT12 里主要是组织概率图(TPM)的路径。用默认 TPM 就够,它由大量成人数据平均而来。如果研究对象是婴幼儿,成人 TPM 明显不合适,需要换专门的模板;这类模板不是 CAT12 自带的,得自己准备并显式指定路径,指定错了会表现为分割出的灰质体积系统性偏小或偏大。

注意:模板换了,后续所有体积数值都不能和用默认模板跑出来的结果直接比较。混着用是群体分析里最难查的错误之一。

4.2 输出前缀与统计端的对应关系

CAT12 输出文件名前面的小写字母有严格含义,搞混了统计结果就是错的。这是新手最容易翻车的地方,因为文件都在、都能打开,看起来一切正常。

前缀含义典型用途
p1/p2/p3组织概率图,未归一化检查分割质量
wp1/wp2归一化到模板空间,未调制看形状,不做体积统计
mwp1/mwp2归一化 + 调制,保留局部体积信息标准 VBM 灰质体积分析
wj开头雅可比行列式形变场分析、局部萎缩程度
DARTEL 导出供 DARTEL 做组间配准的刚性组织图大样本精细配准

标准 VBM 用mwp1:调制把非线性形变造成的体积变化乘回图像强度里,所以每个体素的值反映的是局部灰质体积,而不是灰质密度。只用wp1做统计,等于把体积信息抹掉,结论会偏向“密度”而非“体积”,写文章时容易被审稿人抓住。

DARTEL 导出是为大样本准备的。CAT12 可以把组织图按 DARTEL 的格式导出,交给 SPM 的 DARTEL 工具做组内平均模板,再归一化。样本量在几十以上、脑形态差异大时值得走这条路,代价是多一整套流程和更长的耗时。

4.3 平滑核的选择

VBM 统计前要做高斯平滑,核宽(FWHM)常见取 6~10mm。核宽和经验规则有关:越接近预期效应团的尺寸,统计灵敏度越高;核宽太小,配准残差会带来大量假阳性;核宽太大,小范围效应被抹平。

我一般先用 8mm 跑一版看整体格局,如果预期效应是弥散的皮层改变,8mm 合适;如果是深部小核团,改用 6mm 并配合更严格的团块阈值。平滑在 SPM 的 Smooth 模块做,输入选mwp1图像,输出会加s前缀,统计时读smwp1。

平滑前要先确认所有被试的mwp1是同一个包围盒和体素大小。CAT12 默认会用模板的包围盒,但改了extopts.vox之后,不同批次跑出来的图像体素大小会不一致,SPM 的 Smooth 遇到尺寸不一致的输入会报错或者按第一张图的规格裁剪,后者更危险,因为不报错。

4.4 质量检查与样本同质性

CAT12 自带 Check Sample Homogeneity,本质是算所有被试两两之间的图像相似度,画成相关性矩阵和箱线图,把明显偏离群体的被试标出来。这个工具的价值在于,配准失败往往不会报错,只会让某张图看起来“有点不对”,肉眼在一百个被试里根本看不出来。

阈值怎么定:用协方差或相关性都行,箱线图的 IQR 倍数常见设 2 或 3。设 2 会标出更多候选,适合样本量小、宁可多查的时候;设 3 更保守,标出来的基本是真问题。被标出来不等于必须剔除,先打开图像看,确认是配准失败还是解剖本身特殊(比如明显脑室扩大),再决定。

这一步的建议是固定下来,每次跑完批量分割都执行一遍,不要因为“上次没问题”就跳过。环境换了、SPM 版本升了、批量脚本改了一行,都可能让某个被试静默失败。

4.5 长流程的资源控制

一个被试的完整分割(含表面重建)在普通工作站上要十几分钟到半小时,几十个被试就是一夜。资源控制没做好,半夜跑到一半内存耗尽退出,第二天还得从头来。

nproc设成物理核心数的六到七成比较稳,每个进程峰值内存按 2~3GB 估,16GB 内存的机器设 4 个进程就接近上限了。临时目录指向剩余空间大的盘,分割过程会产生大量中间文件,系统盘被写满导致失败的案例不少见。批量跑之前先用一个被试测出单例耗时和内存峰值,再乘上被试数,这个估算比任何经验值都准。

5. 避坑与排查:五类装得上却跑不对的现场问题

下面五条都是“装完了、也能启动、但结果不对”的场景。按现象、原因、解决的顺序写,照着对号入座即可。

5.1 启动 SPM 后看不到 CAT12 面板

现象:which cat12能返回路径,但 SPM 主界面底部没有 CAT12 的区块,菜单里也没有 CAT 相关项。

原因:SPM 扫描 toolbox 目录发生在启动时,如果 CAT12 是在 SPM 启动之后才addpath进来的,面板不会补渲染;另一种情况是目录层级多套了一层,spm_cat12.m不在toolbox/cat12/的直接子级。

解决:先restoredefaultpath清干净,重新addpath宿主和插件,然后重启 MATLAB 再启动 SPM。目录层级问题直接看文件系统,确认cat12.m就在toolbox/cat12/下,多套的那层删掉或者把内层提上来。

5.2 分割跑到一半报内存不足退出

现象:日志显示处理到某个被试时中断,MATLAB 命令窗口出现内存相关的报错,前面几个被试的结果正常。

原因:并行进程数设太高,或者某个被试的图像矩阵特别大(高分辨率、未降采样),单个进程的峰值内存远超估算值。

解决:把nproc降一半重跑,先确认是并发问题还是单例问题。如果单个被试也跑不动,把extopts.vox从 1.0 放到 1.5,输出体素变大,内存和耗时同步下降。批量脚本里加上失败重试和断点续跑,别让一个被试失败拖垮整批。

5.3 报未定义函数,且函数名看起来属于 SPM

现象:启动 CAT12 或者执行分割时报Undefined function 'spm_xxx',而这个函数在 SPM 目录里明明存在。

原因:搜索路径里存在另一份同名的旧版 SPM 函数,被优先命中了;或者genpath把 CAT12 自带的兼容代码加进了路径,覆盖了宿主版本。

解决:which -all spm_xxx看有几个命中,把多余的那份从路径里移掉。根治办法是改用逐个addpath而不是genpath,并且定期restoredefaultpath清理累积的路径污染。

5.4 分割跑完但统计时被试对不齐

现象:所有mwp1都在,SPM 统计也能跑,但结果里出现大片位于脑外的“激活”,或者某个被试的整体信号明显偏移。

原因:某个被试的仿射配准失败,图像被摆到了模板空间的错误位置,但因为流程没报错,一直到统计阶段才暴露;也可能是不同批次跑的图像体素大小不一致,平滑时被静默裁剪。

解决:跑 Check Sample Homogeneity,看相关性矩阵里的离群点;再抽几个被试打开wp1叠到模板上看位置。确认是配准问题的被试,调高配准强度重跑,或者直接剔除。批处理脚本里固定加一步“检查所有输入的维度和体素大小是否一致”,这一步几行代码,能省掉一整轮返工。

5.5 版本号显示和压缩包对不上

现象:装的是新版本,但 CAT12 界面或版本查询返回的是旧版本号。

原因:机器上有多份 CAT12,搜索路径顺序决定了生效的那份;或者切换版本后没有重启 MATLAB,缓存里的版本信息还是旧的。

解决:which -all cat12列出所有命中,按顺序确认哪个在最前。切换版本时用完整的清空流程:clear all、restoredefaultpath、重新addpath、重启 MATLAB,四步都做,别图省事。

6. 批处理与结果校验:把重复劳动压进一个脚本

单个被试跑通之后,真正的成本在批量。手点界面跑五十个被试,中间任何一次误点都要重来,而且没法复现。我的习惯是把整个流程写成一个函数,输入是数据根目录,输出是每个被试的状态表,跑完一眼就能看出谁成功谁失败。

function run_cat12_batch(rootDir, outDir, nproc) % rootDir 下按 sub-*/anat/*T1w.nii 组织,输出统一写到 outDir spm('defaults', 'fmri'); spm_jobman('initcfg'); files = dir(fullfile(rootDir, 'sub-*', 'anat', '*T1w.nii')); status = cell(numel(files), 3); for i = 1:numel(files) t1 = fullfile(files(i).folder, files(i).name); try matlabbatch = {}; matlabbatch{1}.spm.tools.cat.estwrite.data = {t1}; matlabbatch{1}.spm.tools.cat.estwrite.nproc = nproc; matlabbatch{1}.spm.tools.cat.estwrite.extopts.vox = 1.5; matlabbatch{1}.spm.tools.cat.estwrite.output.GM.mod = 1; matlabbatch{1}.spm.tools.cat.estwrite.output.surface = 0; spm_jobman('run', matlabbatch); % 逐被试串行,失败不污染其他人 status{i, 1} = t1; status{i, 2} = 'ok'; catch ME status{i, 1} = t1; status{i, 2} = 'failed'; status{i, 3} = ME.message; % 记下错误原文,便于回溯 end end save(fullfile(outDir, 'batch_status.mat'), 'status'); end

外层串行、内层并行的结构是刻意的:nproc让单个被试内部并行,被试之间串行,这样一个被试崩了不会连带其他被试,状态表也能准确记录到具体是谁失败。如果反过来让被试之间并行,失败信息会和别人的输出混在一起,排查成本翻倍。

跑完之后的校验我固定做三件事,写成一张核对表:

校验项做法不合格的处理
输出文件齐全统计每个被试目录下mwp1是否存在缺失的单独重跑
维度一致读所有mwp1的spm_vol,比对 dim 和 mat不一致的检查extopts.vox设置
样本同质性跑一次 Check Sample Homogeneity离群被试逐个打开确认

这三步加起来不到十分钟,但能挡掉后面统计阶段最难受的一类返工——数据都跑完了,才发现有两个被试从第一步就错了。

从那以后我每换一台机器、每升一次版本,都先拿一个公开的示例 T1 跑一遍这个最小闭环,确认输出文件和图像质量都对,再动真实数据。装工具这件事,验证一次的成本远低于事后追溯。希望帮到你。

本文还有配套的精品资源,点击获取