ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

FreeSurfer Ubuntu安装全攻略:从环境配置到recon-all验证

FreeSurfer Ubuntu安装全攻略:从环境配置到recon-all验证 这些年总有人来问我FreeSurfer怎么装尤其是一些刚入门的神经影像方向研究生。他们大多是在Ubuntu上折腾了一两天卡在各种报错里出不来。我因为工作原因在好几台不同的Ubuntu工作站上装过FreeSurfer从16.04一路装到22.04踩过的坑也算能汇总成一张表了。这篇就把完整的安装流程、背后的原理、以及那些最容易让人抓狂的细节一次性讲清楚。这篇内容适合这样几类人准备在自己Ubuntu机器上部署FreeSurfer的初学者被license或依赖问题困住的进阶用户以及想给实验室工作站做标准化安装、避免后续反复出问题的管理员。我会尽量把每一步为什么这么做也讲明白而不是只丢给你一串命令。1. FreeSurfer移植到机器上本质是什么很多人把FreeSurfer安装理解成下载一个压缩包解压运行。如果只是这么想安装过程大概率会出问题。我习惯把FreeSurfer的安装理解为把一套自带编译环境、数据模板、工具链和脚本体系的完整生态迁移到你的Ubuntu系统里。它跟普通软件的安装逻辑不太一样。1.1 这不是装一个软件是让一套分析环境生根FreeSurfer的发布包里有将近500个可执行文件大量依赖于相对路径、内部环境变量和固定目录结构。它不是把二进制文件丢到/bin目录下就完事的软件也不是有dpkg维护依赖关系的软件包。它更像一个自带运行时的便携式生态。它的目录里除了bin、lib之外还有subjects自带示例数据、average模板、atlas图谱、trctrain纤维追踪数据等一堆数据目录。这些数据在后续recon-all运行中会被反复调用路径一旦乱了整个流程就会崩溃。所以你必须清楚一点FreeSurfer安装的本质是让这个目录结构在一个确定的位置落地生根然后把系统环境变量指向它让所有子命令都能按预期找到彼此。这也是为什么官方一直强调安装路径不要有空格不要有中文最好也不要用软链在中间绕来绕去。我见过有人图省事把它装在带空格的目录里然后跑recon-all到一半报错查了半天发现是路径解析问题。1.2 环境变量与文件布局理解FREESURFER_HOME和SUBJECTS_DIRFreeSurfer对两个环境变量特别敏感。第一个是FREESURFER_HOME它指向FreeSurfer的安装根目录。所有内部脚本都会基于这个变量去找atlas、模板、二进制文件。如果这个变量没设对最典型的症状是source环境时提示找不到文件或者recon-all一启动就报cannot find... something。第二个是SUBJECTS_DIR它指定了FreeSurfer处理数据的输出目录。每个受试者的重建结果会以子文件夹的形式存在这个目录下。很多人忽略了一点SUBJECTS_DIR不一定要跟FREESURFER_HOME在同一个磁盘分区。我一般建议把它单独指向一个空间足够大的数据盘因为单个subject跑完recon-all所有中间产物加起来能到5-10GB如果你计划处理几十上百个受试者根目录分分钟被塞满。export FREESURFER_HOME/usr/local/freesurfer export SUBJECTS_DIR/data/freesurfer_subjects source $FREESURFER_HOME/SetUpFreeSurfer.sh这三个命令是FreeSurfer环境初始化的核心。SetUpFreeSurfer.sh脚本内部会继续导出PATH、LD_LIBRARY_PATH等几十个变量。建议在终端里先手动执行一遍确认无误后再写进~/.bashrc。1.3 版本差异带来的隐含要求FreeSurfer的版本选择也会影响安装流程。目前常见的有两个大版本线6.0.0经典稳定很多论文还在用和7.x系列对现代Ubuntu支持更好。7.x对Ubuntu 18.04、20.04、22.04都有对应的预编译包文件名里会带上系统版本号比如freesurfer-linux-ubuntu22_x86_64-7.4.1.tar.gz。如果你用Ubuntu 22.04却下载了ubuntu18的包大概率会碰到glibc或libstdc版本不兼容的报错。还有一点要注意FreeSurfer官方预编译包目前主要面向x86_64架构。如果你用的是ARM64版本的Ubuntu比如Apple Silicon上的虚拟机或者某些ARM开发板官方是没有现成二进制包的。虽然有人在社区里提供了非官方编译版但稳定性很难保证。所以强烈建议跑FreeSurfer就用x86_64的Ubuntu机器别跟架构较劲。2. 前置条件License、依赖、系统底座安装FreeSurfer之前最容易被卡住的反而不是下载和解压而是三件看起来不起眼的小事license申请、依赖库安装、磁盘空间规划。这三件事如果做好了后面基本能一把过。2.1 License申请晚一天到就影响进度一个月FreeSurfer虽然软件本体可以免费下载但使用它需要注册并获取一个license.txt文件。这个文件的申请入口在官方注册页面需要填写姓名、邮箱、所属单位。提交之后官方会把license.txt作为邮件附件发给你或者直接在页面上提供下载。这个等待时间有时是几分钟有时是几天我不止一次遇到有学生以为马上就能收到结果第二天要用的时候发现还没发到。license.txt的内容是一行或多行文本包含了你的注册邮箱、一个数字ID和计算主机名hostname信息。关键点来了这个license文件跟运行FreeSurfer机器的hostname是绑定的。如果你想在另一台机器上用同一份license需要重新申请或者把对应机器的主机名先确认好再提交。我见过有人在自己笔记本上申请了license然后跑到服务器上一看hostname对不上FreeSurfer直接拒绝运行。下载FreeSurfer也需要注册账号直接用同一个邮箱账号登录下载页面就行。收到license.txt后把它放到FreeSurfer安装目录的根目录下或者放到$FREESURFER_HOME/license.txt。FreeSurfer默认会在这个位置寻找license文件。文件名必须是license.txt大小写也必须是全小写。2.2 依赖库的完整清单和安装命令FreeSurfer依赖一些系统图形库、OpenGL库和X11库。新版7.x在Ubuntu 22.04上的依赖比旧版更少但仍然需要装几个基础包。我在干净系统上实测以下这条命令可以满足大多数情况sudo apt update sudo apt install -y tcsh libglu1-mesa libgomp1 libjpeg62-turbo libxmu6 libxt6 libx11-dev libxmu-dev libxt-dev libxss1 libqt5widgets5 libqt5gui5 libqt5core5a逐一说下为什么需要这些。tcsh是FreeSurfer内部很多脚本使用的C shell解释器虽然你在bash下也能source环境但某些子脚本执行时仍然会调用csh语法不装tcsh会在意想不到的环节报错。libglu1-mesa和libxmu这类库主要服务于freeview等可视化工具它们依赖OpenGL和X11的运行时。libgomp1是OpenMP运行时库recon-all的多线程并行需要它。libjpeg62-turbo用于读取某些旧式医学图像格式属于历史遗留依赖但缺了它有些模块会静默失败或报编码相关错误。这里特别提醒Ubuntu 22.04的apt源里已经默认没有libjpeg62这个包了只有libjpeg62-turbo。如果看到教程让你装libjpeg62在22.04上可以直接替换成libjpeg62-turbo效果一样。如果你的Ubuntu版本是20.04libjpeg62可能还能装上但不用特意追求版本一致。2.3 磁盘空间规划为什么至少留50GBFreeSurfer解压后的安装目录7.x版本大约占用5-7GB。这还不算什么真正吃空间的是recon-all处理过程中产生的中间文件。单个T1加权结构像跑完整流程从原始数据到最终统计结果整个过程会在SUBJECTS_DIR下生成上百个子目录和文件一次性耗掉5-10GB很正常。如果做纵向longitudinal分析或高分辨率扫描数据单个subject占用的空间会更大。所以我在规划FreeSurfer环境时习惯给一个专门的存储位置。如果机器有多块硬盘建议把SUBJECTS_DIR指到大容量的数据盘如果只有一块盘也要提前确认根分区剩余空间充足。我的最低要求是安装前剩余空间不少于50GB否则处理几个被试后就会因为磁盘写满而中断那种recon-all跑了20小时最后告诉你No space left on device的体验经历过一次就再也忘不了。2.4 确认系统架构和下载对应包用uname -m确认架构再用cat /etc/os-release确认Ubuntu版本这两步别省。uname -m cat /etc/os-release如果输出是x86_64就放心去下载x86_64的安装包。接下来去FreeSurfer官方下载页面用注册邮箱登录选择对应的Ubuntu版本下载。整个安装包大概几个GB建议用wget在服务器上下载不要用浏览器下载到本地再传容易断点中断。wget -c https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/7.4.1/freesurfer-linux-ubuntu22_x86_64-7.4.1.tar.gz加-c参数是为了支持断点续传。如果网络不稳定中断了可以从断点继续下载不用从头再来。下载完后顺便用sha256sum校验一下文件完整性虽然官方文档不一定要求但遇到解压失败时能快速判断是文件损坏还是其他问题。3. 主流程下载解压配置一条龙前置条件准备好之后安装主流程其实就只有四步解压、移动、配环境、放置license。每一步都不复杂但每一步都有容易踩的坑。3.1 下载与解压断点续传和校验拿到tar.gz包后先确认文件大小和官网标注一致。然后执行解压sudo mkdir -p /opt sudo tar -xzf freesurfer-linux-ubuntu22_x86_64-7.4.1.tar.gz -C /opt这里有一个细节tar解压出来的目录名默认是freesurfer所以最终路径会是/opt/freesurfer。我不建议自己随意改名成freesurfer-7.4.1之类虽然改了也能用但后续如果官方脚本里硬编码了相对路径可能会出现奇怪问题。保持默认目录名最省心。如果你希望装在/usr/local而不是/opt也可以sudo tar -xzf freesurfer-linux-ubuntu22_x86_64-7.4.1.tar.gz -C /usr/local两条路选一条就行不用纠结只要记住FREESURFER_HOME跟实际路径一致即可。解压后检查一下ls /opt/freesurfer正常会看到average、bin、lib、subjects、trctrain等目录。如果发现解压后的目录结构不完整多半是下载文件损坏或磁盘空间不足重新校验下载文件、清理磁盘后重试。3.2 环境变量配置bash和csh两派FreeSurfer官方环境配置脚本有两个SetUpFreeSurfer.sh给bash用户和SetUpFreeSurfer.csh给csh/tcsh用户。绝大多数Ubuntu用户用的是bash所以我推荐用.sh版本。在~/.bashrc末尾追加echo # FreeSurfer environment ~/.bashrc echo export FREESURFER_HOME/opt/freesurfer ~/.bashrc echo source $FREESURFER_HOME/SetUpFreeSurfer.sh ~/.bashrc或者直接用编辑器打开~/.bashrc手动加上。然后执行source ~/.bashrc执行后如果终端里出现一些提示信息比如Setting up environment for FreeSurfer/FS-FAST and FSL之类说明环境配置脚本已经被正确执行。如果没有提示先确认FREESURFER_HOME路径是否正确再确认SetUpFreeSurfer.sh文件是否有可执行权限正常tar解压后权限是带好的但如果你用FTP或网盘转存过压缩包权限可能被重置那时需要chmod x。有一点要特别提醒环境变量的设置顺序很重要。source SetUpFreeSurfer.sh必须放在export FREESURFER_HOME之后。因为脚本内部会基于FREESURFER_HOME去定位其他资源如果变量为空source过程会报错。还有一个常见问题如果你同时装了FSLFreeSurfer的环境脚本会在PATH里添加自己的FSL版本影响。这不是安装错误但要注意在调用fsl命令时确认到底用的是哪个版本。3.3 license.txt的放置与常见错误把license.txt放到FreeSurfer根目录cp license.txt /opt/freesurfer/放置完成后验证方式很简单。直接运行一个需要license的命令比如freeviewfreeview如果license有问题终端会明确提示license.txt not found或者license check failed。如果license正常freeview的图形界面应该能正常弹出来。在纯服务器无图形界面的环境下freeview可能无法启动这时可以用另一个不需要图形界面的命令验证mri_info --version或者直接跑recon-all -version如果输出正常显示版本号说明license和基础环境都通过了。关于license有三个高频报错值得单独列出来*** ERROR: FreeSurfer license file /opt/freesurfer/license.txt not found。非常直白license.txt没放到根目录或者目录名不对。License not valid. Check license.txt。说明license文件格式或内容有问题常见原因是hostname不匹配或者从邮件复制时把多余空格也带进去了。bash: /opt/freesurfer/bin/recon-all: Permission denied。这不是license问题是权限问题需要用chmod修复可执行权限。3.4 初始化验证freeview和mri_info能不能跑环境配置完成后强烈建议做一个完整的初始化验证而不是直接开始跑大型处理。验证项目就那么几个which freeview which recon-all which mri_info echo $FREESURFER_HOME echo $SUBJECTS_DIR如果which找不到命令说明PATH没有被正确更新需要重新source环境并检查脚本执行过程是否有报错。如果SUBJECTS_DIR显示为空或路径不对需要在.bashrc里显式指定。另外还可以试试FreeSurfer自带的示例数据。安装目录下自带一个叫bert的示例受试者数据位于/opt/freesurfer/subjects/bert。如果这个目录存在说明数据文件完整。用freeview直接加载其中的一个图像文件测试可视化模块freeview /opt/freesurfer/subjects/bert/mri/T1.mgz图像能正常显示说明OpenGL相关的依赖库都没问题。4. 跑通第一个recon-all才算安装完成环境能启动、版本号能输出来只能说明安装成功了一半。真正的验收标准是能完整跑通一个recon-all流程。这一步才是FreeSurfer安装是否真正可用的试金石。4.1 用自带bert数据做全流程测试我建议第一次测试时不要急着处理自己的数据先用FreeSurfer自带的bert示例数据跑一个完整的recon-all流程。为什么因为你自己的数据如果采集参数特殊、有伪影或格式不规范处理失败时你很难判断是安装问题还是数据问题。而bert数据是官方验证过的它出问题的概率极低如果连bert都跑不完那一定是安装或配置问题。先把SUBJECTS_DIR指到一个独立目录并设置好当前要处理的subject名称mkdir -p /data/fs_test export SUBJECTS_DIR/data/fs_test注意SUBJECTS_DIR需要是一个已经存在且可写的目录。然后执行recon-all -s bert -i /opt/freesurfer/subjects/bert/mri/T1.mgz -all -openmp 4这里解释一下参数。-s指定subject名称也就是会在SUBJECTS_DIR下创建一个名为bert的输出目录。-i指定输入图像注意recon-all的输入图像必须是单个T1加权结构像通常是.mgz或.nii格式。-all表示跑完整流程从最初的图像配准、强度归一化到表面重建、拓扑校正、皮层分割、配准到标准空间、生成统计结果全部一条龙执行。-openmp 4表示使用4个线程并行这个参数可以根据CPU核心数调整。4.2 日志与输出结构的判读recon-all -all脚本执行时会实时输出大量日志信息。这些信息看起来密密麻麻其实有规律。正常的输出中会依次出现类似-autorecon1、-autorecon2、-autorecon3这样的阶段标记它们分别对应流程的三个大阶段。每个阶段内部还有更细的子步骤比如mri_em_register、mri_ca_normalize、mri_segment等。判断是否正常最直观的标准有两条一是命令没有在某个步骤报ERROR并终止二是最终能看到recon-all -s bert -all finished without error类似字样。如果中途报错不要慌错误信息通常会直接指出是哪一步失败、涉及哪个输入文件。FreeSurfer的日志也会写到输出目录下的scripts/recon-all.log中打印出来的log路径可以直接查看。跑完后在/data/fs_test/bert目录下会生成mri、surf、label、stats等子目录。其中mri目录下的T1.mgz是配准后的体积数据surf目录下是左右半球的皮层表面网格文件stats目录下是最终的厚度、面积、体积等统计指标。只要这些目录结构都生成了说明recon-all完整走完。4.3 常见失败的真实报错与排查路径我在安装和测试过程中遇到过几种典型的recon-all失败这里给出可复现的排查路径。第一种运行到某个mri_convert或mri_normalize步骤时报cannot open file。这类问题通常和路径有关。比如输入图像路径写错了或者SUBJECTS_DIR没有提前创建。解决方案是检查recon-all的输入路径是否真实存在且文件名后缀是否被工具支持。第二种报Out of memory或进程被系统kill。recon-all非常吃内存处理单个subject时峰值内存可能达到8-16GB。如果机器内存只有8GB-all流程很容易在autorecon2阶段因为内存不足被OOM killer杀掉。有两个应对方式一是减少并行线程数-openmp改为2降低峰值内存二是增加swap空间但不要指望swap能完全替代物理内存只能缓解。条件允许的话建议至少配置16GB物理内存。第三种报Cannot lock file或Permission denied。常见于多用户共用环境。比如你以普通用户身份运行但SUBJECTS_DIR设置在root拥有的目录下。解决方案是把SUBJECTS_DIR目录的属主改成当前用户或者用sudo chown授权。第四种报ERROR: Cannot write to /data/fs_test/bert。这通常是磁盘写权限或空间不足。排查命令df -h /data/fs_test ls -ld /data/fs_test确认空间够、属主对再重新运行。4.4 parallel加速和内存限制前面提到-openmp参数它的作用不仅是对多核心加速还会影响峰值内存占用。很多实验室的普通工作站是4核8线程、16GB内存这种配置跑-openmp 4是可行的但如果你只有8GB内存建议只用-openmp 2。我实测过同样一台机器-openmp 4时峰值内存接近12GB-openmp 2时峰值降到7GB左右时间上大概慢30-40%但至少不会中途崩溃。对于单台64GB内存的服务器-openmp 8也能跑得动但FreeSurfer某些步骤本身并不是严格的并行实现加太多线程收益有限反而可能增加内存压力。一般来说-openmp 4到8之间是比较合理的区间。如果你有一台多核服务器想同时处理多个subject可以并行启动多个recon-all进程每个进程处理不同的subject。但要注意控制并发总数别让内存和CPU同时过载。我的经验是物理内存除以单个预计峰值内存得出最大并发数再留20%余量。5. 长期使用中的实操经验和配置建议安装跑通只是开始日常使用中还有不少细节能让你少踩很多坑。这部分没什么惊心动魄的故障但每一条都是我或身边同事在实践里总结出来的。5.1 多用户共享的权限管理实验室的FreeSurfer通常是多人共用的。如果所有人都用root跑权限问题倒是不多但存在安全隐患且容易互相误删文件。更好的做法是单独建一个freesurfer用户组把需要用到FreeSurfer的账号都加入这个组然后设置共享目录的组权限sudo groupadd freesurfer sudo usermod -a -G freesurfer $USER sudo chown -R root:freesurfer /opt/freesurfer sudo chmod -R 775 /opt/freesurfer这里说明一下/opt/freesurfer本体只需要可读可执行权限不必让普通用户有写权限。真正需要写的是各个人的SUBJECTS_DIR不需要共享到系统目录。每个人在自己的账号下设置自己的SUBJECTS_DIR指向自己的数据目录互不干扰这比一群人共用同一个SUBJECTS_DIR更安全。5.2 与Python/深度学习工作流衔接现在很多人会把FreeSurfer和深度学习流程结合起来比如用FreeSurfer生成皮层厚度、沟回深度等特征然后喂给Python做分析。这里有两个常见问题。一是shell环境变量不会自动传给Python子进程。如果你在Python脚本里用subprocess调用recon-all或mri_convert需要先确保子进程环境里有FreeSurfer的环境变量。最稳妥的办法是在调用前显式设置import os os.environ[FREESURFER_HOME] /opt/freesurfer os.environ[SUBJECTS_DIR] /data/fs_subjects # 然后source环境在非交互式Python中比较麻烦可直接暴露PATH os.environ[PATH] /opt/freesurfer/bin: os.environ.get(PATH, )二是很多人在Jupyter Notebook里source了FreeSurfer环境后发现Python的库冲突了。FreeSurfer自带的Python环境fspython和系统Anaconda环境最好不要混用。建议常规数据分析用Anaconda跑FreeSurfer相关命令时用subprocess或Python的os.system调用外部命令而不要强行import FreeSurfer的Python包。5.3 版本升级与数据兼容FreeSurfer升级是大坑。6.0生成的表面数据拿到7.4里面继续跑大部分情况能兼容但不要想当然。如果实验室里同事之间、上下游流程之间用了不同版本建议统一版本。尤其当你用recon-all生成一批数据后又换了新版本新版本可能带不同的模板配准脚本导致前后两批数据的结果不完全可比。在做多批数据的统计分析时版本不一致意味着你需要额外解释这部分差异来源。我个人的习惯是在一个项目周期内锁定FreeSurfer版本不轻易升级。如果必须升先把旧版本所有处理结果备份再做新版本的完整recon-all测试确认输出和旧版本的一致性达到可接受范围再切过去。5.4 我总结的一套装机后立即要做的事装完FreeSurfer后不要急着进入正式数据处理先用一个下午把下面几件事做完能让后面几个月省心很多第一个recon-all测试用官方数据跑通记录耗时和内存峰值作为这台机器后续所有性能参考基准。写一份环境配置文件放在/etc/profile.d/freesurfer.sh这样所有用户登录时都能自动加载FreeSurfer环境不用每个人手动改.bashrc。设置cron或systemd timer定期清理recon-all临时文件避免磁盘写满。把license.txt备份到云盘或U盘防止机器故障后license丢失。与FreeSurfer相关的操作统一记录到实验室共享的wiki或文档里包括下载链接、依赖包列表、测试命令、踩坑记录。5.5 一些日常使用的高频技巧最后补充几个日常使用中会反复用到的命令行技巧。查看当前FreeSurfer环境是否正常可以执行source $FREESURFER_HOME/SetUpFreeSurfer.sh which recon-all如果which recon-all能输出/opt/freesurfer/bin/recon-all环境就是好的。批量检查多个subject是否处理完成可以写一个简单循环for sub in $(ls /data/fs_subjects); do if [ -f /data/fs_subjects/$sub/surf/lh.thickness ]; then echo $sub done else echo $sub not done fi done想快速提取某个subject的皮层平均厚度可以用aparcstats2table --subjects bert --hemi lh --meas thickness --table lh_thickness.txt这些命令在日常数据分析里出现频率很高建议收藏起来。从装机到跑通FreeSurfer这套环境的部署逻辑其实不复杂但每一步都藏在细节里license与hostname的绑定、依赖库的版本适配、环境变量的加载顺序、recon-all各阶段对内存的需求。把这些细节都过一遍剩下的就是稳定使用了。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进