☰
SPM处理fMRI数据高频问题与解决方案合集
2026/10/5 4:40:26 网站建设 项目流程

搞 FMRI 的人,谁没被 SPM 里各种小问题折磨过?不管是刚入门的研究生,还是做了好几年的老手,只要打开 MATLAB 敲下spm fmri,就总会在某个环节碰到一个让人抓狂的报错或者一个怎么看都不对劲的结果。SPM 这个软件功能确实强大,但它的很多细节设计得非常“老派”,很多问题在官方文档里写得不清不楚,网上答案又零零散散。

我这些年用 SPM 处理过不少 fMRI 数据,从 DICOM 转格式开始,到预处理、一阶分析、二阶分析,再到结果展示,几乎每个阶段都踩过坑。很多问题其实原理并不复杂,就是一些约定俗成的规矩没人告诉你。这篇东西我就把平时遇到的高频问题按处理流程整理成一个合集,每个问题都讲清楚现象、原因和解决办法,给正在被 SPM 折磨的朋友一份可以直接“抄作业”的避坑指南。这篇东西适合所有用 SPM 做 fMRI 数据分析的人,尤其是刚开始接触、还在摸索阶段的新手。

1. 数据准备与格式转换:还没开始就被卡住

很多人以为 SPM 的坑是从预处理开始的,实际上数据准备阶段就有不少问题。这个阶段最烦人的地方在于,报错信息往往看不出来是“格式”问题还是“路径”问题,只能一个一个排查。

1.1 图像文件读不进来的常见原因

SPM 对文件格式的挑剔程度,比大多数人想象的要高得多。最常见的情况是,你在文件夹里明明看到了.nii文件,但 SPM 的Display或者Batch界面里就是显示不出来,或者点选之后直接报错。

首先要确认文件是不是真正的 NIfTI 格式。有些转换工具会生成带.nii后缀但内部结构不合规的文件,尤其是从某些厂商的旧型号机器上导出的数据,用第三方工具转换时容易产生这种问题。SPM12 对 NIfTI 的兼容性还行,但遇到这种“伪 NIfTI”还是会出现File not recognized之类的报错。

另一个常见的坑是文件名和路径。SPM 对路径中的中文、空格、特殊字符非常敏感。我相信很多人都经历过把数据放在“D:\我的数据\第一次扫描\”下面,然后 SPM 直接罢工的情况。解决办法也很简单,数据路径务必要纯英文、无空格,比如D:\fmri_data\session1\。文件夹层级也不要太深,有时候路径太长也会触发不可名状的错误。

提示:前期数据整理时就把路径和文件名规范好,能省掉后面很多不必要的麻烦。文件名建议统一用sub-01_run-1_T1w.nii这类可读性强的命名,方便后续处理。

1.2 图像方向不对:左右颠倒的“灵异事件”

用 SPM 的Display按钮查看刚转好的图像时,有人会发现图像左右好像反了。这个问题的本质是 NIfTI 坐标系的约定问题。

医学影像领域存在两种坐标系:一种是放射学坐标系(radiological),图像左侧对应患者的右侧;另一种是神经科学坐标系(neurological),图像左侧对应患者的左侧。SPM 默认按神经科学坐标系显示,但有些转换工具(尤其是某些 DICOM 转换软件)默认使用放射学坐标系。在 SPM 里看起来“左右颠倒”,往往不是数据本身有问题,而是显示约定不同。

检查方法很简单:在 SPMDisplay里查看时,注意看左上角的方向标签(L/R 标记)。如果担心数据本身有问题,可以对比原始 DICOM 图像和转换后的 NIfTI 图像在同一个层面的显示,只要没有发生镜像翻转,数据处理结果就不会受影响。

1.3 TR、TE 等参数在转换时的准确性

fMRI 数据转换时,DICOM 文件头里包含了大量扫描参数,比如 TR(重复时间)、TE(回波时间)、翻转角、体素大小、层数等。SPM 做统计分析时,TR 是一个非常重要的参数,因为它直接关系到时间单位换算。

很多人用 MRIcro 或者 dcm2nii 转换完数据就直接开始处理,没有检查转换结果里记录的 TR 是否和扫描参数一致。我遇到过一位同学,扫描时 TR 明明是 2000ms,转换出来的 NIfTI 文件里记录的 TR 却变成了 2500ms,结果整个时间序列的统计结果都偏了。

所以转换完成后,建议用 SPM 的Display或者任意一个能查看 NIfTI 头信息的工具(比如 FSL 的fslinfo)确认 TR 值。如果是用 dcm2nii 转换,注意保留原始 DICOM 文件的备份,万一转换出问题还可以重新来过。

1.4 4D NIfTI 和 3D NIfTI 的取舍

fMRI 数据通常是一个 4D 文件(3D 空间 + 时间维),但有些早期转换工具会把每个时间点都存成一个 3D 文件。SPM 两种方式都支持,但处理习惯不一样。

如果数据是 4D 文件,SPM 在Data选择时只需要选一次,后面会自动识别所有时间点。如果是成千上百个 3D 文件,你在 SPM 的 Batch 里需要把整个文件夹的所有文件都选中,或者用SPM12自带的文件选择工具批量选择。

我个人建议尽量转换成 4D NIfTI,因为文件数量少,管理起来方便,批处理时也不容易出错。有时候 SPM 读 4D 文件会要求确认“是否按 4D 读取”,要点“是”,否则它会把时间维当成单独的 3D 文件来处理,后面建模时就会出现时间点数量对不上的问题。

2. 预处理环节:高频踩坑重灾区

预处理是 SPM 处理 fMRI 数据中最容易出错的环节,因为涉及多个步骤,每个步骤都有参数要设置,每个参数都有讲究。这里我把最常见的几个坑拎出来重点说。

2.1 Slice Timing 的 slice order 填错

Slice timing(时间层校正)是 fMRI 预处理的第一步,也是最容易填错的一个步骤。不同厂商、不同扫描序列的采集顺序不一样,有的从下往上顺序采集,有的是隔层采集(先奇数层后偶数层)。

SPM 的Slice timing模块里需要填Number of Slices和Slice Order。很多人就是在这里填错,导致整个时间序列的对齐出现问题,后续统计结果一团糟。

如果扫描仪是隔层采集,且层数是 32,那么 slice order 应该是1:2:32, 2:2:32这种形式——先填所有奇数层,再填所有偶数层。如果是顺序采集,直接填1:32就行。如果不确定扫描序列的采集顺序,去问扫描技师,或者查看扫描协议文档,千万别猜。

注意:Slice timing 的参考层(Reference Slice)选择也有讲究。一般选择时间上居中的一层作为参考,比如 32 层的话选 16 或者 17。这个选择对结果影响不大,但会影响预处理后数据的平滑程度。

2.2 Realign 之后一定要看头动参数

Realign(头动校正)是预处理的重要步骤,它通过刚体变换把不同时间点的图像对齐到参考图像上。但很多人跑完 Realign 就直接进入下一步了,从来不检查头动参数。

SPM 的 Realign 会生成一个rp_*.txt文件,里面记录了每个时间点在 x、y、z 三个方向的平移和旋转参数。如果一个被试的头动超过一个体素(通常 fMRI 体素是 3-4mm),那么这组数据的质量就很可疑了。如果头动超过 3mm 或者 3 度,一般建议考虑剔除该被试,或者在建模时把头动参数作为协变量加进去。

我自己的习惯是,Realign 跑完后,用 SPM 的Check Reg功能把mean*.img和第一个时间点的图像叠加起来看,看不出明显错位的话,再查看rp_*.txt的最大平移和旋转值。如果发现某个被试头动过大,会在项目记录里标注出来,后续做敏感性分析时剔除它再跑一遍。

2.3 Coregister 报错的真正原因

Coregister(配准)这一步是把功能像和结构像对齐。常见的问题是 Source Image 和 Reference Image 的选择搞反了,或者 T1 结构像没有经过重采样导致两个图像分辨率不一致。

在 SPM 的 Coregister 模块里,Reference Image是参考图像(通常是 T1 结构像),Source Image是需要被配准的图像(通常是 mean 功能像)。很多人把这两个搞反了,结果功能像被变换到了奇怪的位置。

另外一个细节是:T1 结构像如果是高分辨率(比如 1mm 各向同性),而功能像是 3.5mm 体素,Coregister 之前最好先通过Reslice或其他工具把 T1 重采样到和功能像一致的分辨率,否则配准过程会非常慢,而且有时会得到很差的配准结果。我在实际处理中发现,SPM12 自带的 Coregister 对这种情况的处理能力有限,先用Segment得到的参数再配准,或者用 ANTs 这类专业工具先跑一遍,效果会好很多。

2.4 Normalize 之后图像变暗或体积变小

Normalize(空间标准化)的目的是把个体脑图像变换到标准空间(MNI 空间),这样不同被试的数据才能放在一起比较。但有人跑完 Normalize 后发现图像变暗了,或者体积变小了,以为数据出了问题。

图像变暗的原因很可能是 Normalize 之后的图像经过了调制(Modulation)处理。如果选择的是 DARTEL 流程,并且勾选了“Modulated Normalisation”,那么图像体素的值会乘以一个缩放因子,以保持总体积不变,视觉上看起来就会变暗。这是正常现象。

体积变小则可能是参数设置问题。如果 Normalize 时选择的 Voxel Size 比原始体素尺寸大,比如原始体素是 3mm 各向同性,你在 Normalize 的 Voxel Size 里填了 8mm,那输出图像的体素数量就会变少,体积看起来自然变小了。常用做法是保持 Voxel Size 和原始数据一致,比如 3mm 或 2mm。

还有一个容易忽视的问题:Normalize 后生成的文件名前缀是w(比如wraf*.nii或wrar*.nii),这表示它已经被变换到了标准空间。后续 Smooth 时应该选择这些带w前缀的文件,而不是原始文件。

2.5 Smooth 的 FWHM 到底选多大

Smooth(空间平滑)的 FWHM(半高全宽)参数选择也是一个经典问题。SPM 默认值是 8mm,很多人就直接用默认值,也不知道为什么。

FWHM 的选择和原始体素大小、期望检测的效应空间尺度有关。如果体素是 3.5mm 各向同性,那么 8mm 的 FWHM 是一个比较合理的选择,既不会过度平滑丢失细节,也不会因平滑不足导致统计检验的随机场假设不满足。如果原始体素比较小(比如 2mm),可以适当减小 FWHM 到 6mm。需要注意的是,Smooth 后的图像应该保存在带s前缀的文件中,比如swraf*.nii,后续统计建模时选择的是这些文件,而不是原始文件。

实操心得:Smooth 的 FWHM 不宜小于原始体素大小的两倍。过小的 FWHM 会导致统计检验时体素之间不满足独立性假设,容易产生假阳性结果。这个原则很多人不知道,但在审稿时可能会被问到。

3. 统计建模:看起来能跑,结果却经不起推敲

预处理做完之后,数据已经有了sw*.nii开头的文件,接下来就是建立统计模型。这个阶段的坑更隐蔽,因为你往往要到出结果的时候才发现有问题。

3.1 条件名称不能以数字开头

这是一个非常细碎但非常常见的问题:在 SPM 的一阶分析(fMRI model specification)中,Condition的Name不能以数字开头。比如你给条件取名1-back或2back,SPM 会直接报错,或者生成的设计矩阵奇奇怪怪。

原因是 SPM 内部会把条件名称作为 MATLAB 的变量名使用,而 MATLAB 变量名不能以数字开头。解决办法很简单:在条件名称前加一个字母,比如c1_back或Cond_2back。我见过有人在这个问题上卡了很久,一直以为是数据问题,结果就是名字没起对。

3.2 Onset 的单位是秒,不是扫描层数

在一阶分析的 Onset 设置中,SPM 要求填写的 Onset 单位是“秒”,而不是扫描的层数或时间点编号。很多人在这里出错,尤其是用某些自动化流程导出的 Onset 文件是时间点编号的形式,直接填进去后模型的时序完全错乱。

还有一种情况是有些任务程序记录的 Onset 是以扫描层数为单位,需要乘以 TR 换算成秒。比如第 20 个时间点,TR 为 2 秒,那么 Onset 就是 40 秒。做这一步时务必统一单位,最好在 Onset 文件的表头写清楚单位,并且保存一份原始记录以备核查。

3.3 设计矩阵秩亏:有人掉进陷阱却不自知

设计矩阵(Design Matrix)的秩亏(rank deficiency)是 fMRI 统计分析中一个常见但容易忽略的问题。SPM 在估计模型时会显示设计矩阵的图形,如果你发现设计矩阵的某些列看起来完全一样,或者有某列全为零,那就说明存在共线性问题。

共线性通常发生在多个条件之间存在高度相关的刺激序列时,或者某个条件在某次扫描中根本没有出现。后一种情况更隐蔽——如果一个 run 里没有呈现某个条件,但你在构建模型时仍然把该条件加进去了,SPM 虽然可能不会报错,但该条件的参数估计结果会毫无意义。

建议在建模之前先检查每个 run 的 Onset 文件,确认每个条件都有实际出现。如果某个 run 中某个条件缺失,可以把这个 run 单独建模,或者在其他 run 中对该条件进行估计后再做组分析。

3.4 多个 run 的处理:Replicate 还是 Concatenate

一个被试通常有多个 run(扫描序列段)。在 SPM 的一阶分析中,有两种处理方式:Replicate 和 Concatenate。

Replicate 是指把多个 run 作为“重复测量”来建模,SPM 会为每个 run 分别估计参数,然后通过二阶分析比较不同 run 之间的差异。Concatenate 则是把所有 run 拼接成一个长的时间序列来建模,前提是各个 run 的扫描参数(TR、层数、体素大小)完全一致。

大多数情况下,建议使用 Replicate 方式处理多个 run,因为这种方式能更好地处理 run 之间的头动差异和时间效应。如果用 Concatenate,需要在建模时添加额外的 regressor 来补偿 run 之间的基线漂移,操作复杂度高,还容易出错。

3.5 二阶分析时选错文件

一阶分析完成后,每个被试会生成一组con_*.img(对比图像)文件。二阶分析(比如单样本 t 检验)需要选择的输入文件就是这些con_*.img或con_*.nii文件。

很多人在这里犯的错误是选择了spmT_*.img文件,或者选择了某个特定条件下的beta_*.img文件。记住一个原则:二阶分析的输入永远是对比图像(contrast images),不是 beta 图或统计图。con_*.nii文件记录的是每个被试在某个对比下的效应大小,最适合做组分析。

实操心得:在 Batch 编辑器里设置二阶分析时,务必使用Factorial design或One-sample t-test模块,并且输入文件类型选择contrast images。选错文件类型的结果就是你的组分析结果完全不可信,而且这个过程不容易察觉。

3.6 结果校正方式:FWE、FDR 和 uncorrected

查看统计结果时,SPM 会提供多种校正方式:FWE(Family-Wise Error)、FDR(False Discovery Rate)和 uncorrected(未校正)。很多新手不知道选哪种,看到有显著的 voxel 就高兴,却忽略了校正问题。

FWE 是最严格的校正方法,通过随机场理论(Random Field Theory)控制多重比较带来的假阳性。FDR 相对宽松一点,控制的是假发现率。uncorrected 则完全不校正,只在探索性分析中使用。

在功能像分析中,voxel-level的 FWE 通常比较严格,如果样本量不大,可能很难达到显著。这时可以看cluster-level的校正结果,它是以簇(连通的显著体素集合)为单位进行校正,敏感性更高,在神经影像文献中也被广泛接受。

如果你看到 “No suprathreshold clusters” 的提示,首先不要慌。这可能是因为阈值设置太高,校正方式太严格,或者数据本身效应不够强。可以尝试调整 p 值阈值(比如从 0.001 放宽到 0.005),或者切换校正方式,看看是否有体素达到显著。

4. 批处理、脚本与进阶提示

SPM 的 GUI 界面虽然便于手点,但处理大量被试时效率太低,而且容易出错。用 Batch 编辑器和脚本可以大大提高效率和可重复性。

4.1 Batch 编辑器里 Dependence 的用法

SPM 的 Batch 编辑器支持通过Dependence机制让后续步骤自动获取前一步的输出。比如 Realign 生成mean*.img后,Coregister 需要mean*.img作为 Source Image,此时就可以在 Batch 中把 Coregister 的 Source Image 设为 Realign 输出的mean*文件的 Dependence。

很多刚开始用 Batch 的人,喜欢在每个步骤里手动选择文件,这样容易选错,而且无法复用。用 Dependence 之后,整个预处理流程可以一键跑完,中途不需要人工干预。这个功能我用得非常频繁,强烈推荐。

具体操作是:在 Batch 编辑器中,把流程的各个模块拖到同一棵树里,然后在需要依赖前一步输出的参数位置右键选择Dependence,再选择对应的模块输出字段。SPM 会自动把前一步生成的文件填进去。

4.2 从 GUI 操作生成脚本:入门脚本的最佳捷径

SPM12 提供了一种方式:在 GUI 里设置完整个 Batch 后,点击Save或Run时选择生成.m脚本文件。这个脚本文件可以在 MATLAB 中直接运行,也可以编辑修改后复用。

我的习惯是:第一次处理时用 GUI 操作一遍,同时生成脚本,之后所有数据的处理都在脚本基础上微调,不再经过 GUI。这样不仅效率高,还能保证所有被试的处理流程完全一致,这是 fMRI 数据分析的基本要求——可重复性。

对于想进一步自动化的朋友,SPM 的脚本本质上是调用 MATLAB 函数,比如spm_preproc、spm_normalise、spm_smooth等。你完全可以在理解这些函数参数的基础上,编写自己的循环脚本,批量处理多个被试。这个过程虽然初期麻烦,但一旦写好,后续数据处理会非常轻松。

4.3 MATLAB 路径里的中文、空格和内存问题

SPM 是在 MATLAB 环境里运行的,因此 MATLAB 的路径问题也会直接影响 SPM 的使用。

第一,SPM 工具箱所在的路径不能有中文或空格。比如你把 SPM12 安装在C:\Program Files\SPM12这种带空格的路径下,有时候会触发奇怪的错误。建议安装在D:\toolbox\spm12这种纯英文、无空格的路径下。

第二,SPM 的数据处理非常耗内存。预处理阶段只要Smooth一个步骤,就会同时加载多张图像,内存不够时 MATLAB 会直接报Out of memory。解决办法包括:关闭其他不必要的 MATLAB 窗口、在 MATLAB 中减少自动保存的暂存变量、使用 64 位版 MATLAB(这是硬性要求)。

第三,如果数据量特别大,建议分批处理,不要一次性把 20 个被试的所有 run 都放进同一个 Batch。我一般以 5-6 个被试为一批,跑完一批再跑下一批,这样既不会爆内存,也方便中途发现问题及时修正。

4.4 结合外部工具提升效率

SPM 虽然功能全面,但有些流程用起来并不顺手。我在实际项目中经常搭配一些外部工具来提升效率和结果质量。

Artifact Detection Tools(ART)是一个非常实用的工具箱,可以自动检测时间序列中的异常信号(比如头动尖峰、伪影),生成一个包含异常时间点的 regressor 文件。把这个 regressor 加入一阶模型作为协变量,可以显著降低头动和伪影对统计结果的影响。很多顶刊文章都会报告用了这种“scrubbing”或“regressing out motion outliers”的方法。

xjView 是另一个常用的结果显示工具,它基于 SPM 的输出结果提供更丰富的可视化选项。SPM 自带的Results界面功能比较基础,xjView 能展示三维脑图、导出表格数据、做 ROI 分析,而且在多个模板(MNI、Talairach)之间切换坐标。我通常在Results界面里找到显著的簇后,用 xjView 生成可发表级别的脑区图。

DPABI(DPARSF 的升级版)则是基于 SPM 的图形化界面,把整个预处理和统计流程串联起来,适合追求便捷的初学者。不过它本质上还是调用 SPM 的函数,所以理解 SPM 本身仍然是第一位的。

4.5 排查问题的方法论:从日志到 Check Reg

最后说一点通用的排查思路。SPM 报错时,首先看命令行窗口的完整报错信息,那里通常会提示是哪个模块、哪一步出了问题。如果报错信息很抽象,可以在 MATLAB 中进入 SPM 模块所在的目录,查看对应函数代码,找到报错的行号,理解触发条件。

对于结果显示类的问题(比如图像显示异常),Check Reg 是一个非常实用的功能。它允许你把多张图像叠加显示,快速检查配准、归一化是否成功。我几乎每步预处理后都会用 Check Reg 检查一遍,尤其是 Realign 和 Coregister 之后。

如果你遇到一个完全没见过的问题,不要独自纠结。SPM 有非常活跃的用户邮件列表([email protected]),搜索历史邮件通常能找到答案。在提问之前,先确认自己的 SPM 版本号、MATLAB 版本号、数据格式,并且提供完整的报错信息,这样别人才能帮你定位问题。

另外要养成记录处理日志的习惯。我曾经通过对比两台电脑上相同的处理流程输出,定位到一个因 SPM 版本细微差异导致的结果不一致问题。这给我提了个醒:合作项目中所有人尽量使用相同版本的工具,结果才具备可比性。

整理这个“小问题合集”的过程,也是我对自己 SPM 使用经验的复盘。这里面很多坑,不是看文档就能避开的,而是要在实际操作中一点点踩过来才知道怎么绕。如果你正被某个问题卡住,希望这里有你要的答案。如果没找到,先按上面提到的几个方向去排查——格式、路径、单位、参数约定,排除掉这些之后,绝大多数问题都迎刃而解。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询