ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Ubuntu 24.04源码编译COLMAP 3.13.0:CUDA 12.9环境配置与避坑指南

Ubuntu 24.04源码编译COLMAP 3.13.0:CUDA 12.9环境配置与避坑指南 这些年凡是跟三维重建、SLAM 沾边的项目基本绕不开 COLMAP。它是我见过把运动恢复结构SfM和多视角立体视觉MVS整合得最完整的开源工具从特征提取、匹配、几何验证到增量式重建、稠密重建、网格生成一条龙全给你安排得明明白白。我的日常工作流里无论是做相机标定、生成 NeRF 训练数据还是给无人机影像做地形重建COLMAP 都是最核心的那一环。不过官方预编译的二进制包虽然省事但到了自己服务器上总有各种不适配可能没启用 CUDA、可能带的 GUI 缺东西、可能依赖库版本被锁死。所以我这次直接在 Ubuntu 24.04 LTS 上从源码编译了 COLMAP 3.13.0配合 CUDA 12.9 工具链。折腾了两天踩了一堆坑总算把整套环境跑通。这篇文章不打算写成一个干巴巴的编译手册我尽量把背后的原理、每一步的取舍、以及那些文档里从来不写的细节都讲清楚让你照着走能少趟几个雷。1. 整体设计与思路拆解1.1 为什么是 COLMAP 3.13.0 CUDA 12.9 Ubuntu 24.04 这个组合先说版本选择。COLMAP 3.13.0 是当前一个功能比较稳定的版本对 CUDA 12 系列的支持已经比较成熟不需要再去迁就早期那种“CUDA 11.x 老驱动”的配置。更关键的是3.13.0 的 CMake 构建逻辑更清爽依赖项识别更干脆编译过程中少了很多乱七八糟的手工 hack。CUDA 12.9 是 NVIDIA 当前比较新的工具链版本。有人可能觉得“用这么新的 CUDA 有必要吗”我的看法是如果你的显卡本来就是 AmpereRTX 30 系或 Ada LovelaceRTX 40 系架构新版 CUDA 对计算能力 8.x/9.x 的优化会更到位编译出来的代码跑起来理论上也更稳。当然CUDA 版本并不需要过分追新但对于全新部署的环境直接用 12.9 完全没毛病反正 COLMAP 3.13.0 跟它配合得很好。Ubuntu 24.04 LTS 是 2024 年 4 月发布的长期支持版本背后有 5 年安全维护期系统库版本新比如 GCC 13.2、CMake 3.28对 CUDA 12.9 的兼容性也非常好。三个版本放一起基本就是一套“当前时间点上的标准新环境”不用为了兼容老系统去折腾各种降级操作。提示如果你手头是特别老的显卡比如 GTX 10 系列或者更早的 Maxwell 架构建议先查一下计算能力Compute Capability是否在 CUDA 12.9 的官方支持列表里。虽然旧卡通常也能编过但架构参数设置不对编译出来的程序运行时会直接报“no kernel image is available”错。1.2 三种部署方式的对比预编译、Docker、源码编译很多朋友问我既然 COLMAP GitHub Releases 里有编译好的二进制包为什么还要自己从源码折腾一遍我把三条路做过一次对比优劣挺明显的。部署方式优点缺点适合场景官方预编译二进制开箱即用几分钟跑起来不一定带 CUDA 加速GUI 特性可能不全无法针对自己显卡微调架构参数快速验证流程、跑通 demoDocker 镜像环境隔离拉下来就有不污染宿主机GPU 透传要配 NVIDIA Container Toolkit数据卷、权限管理麻烦开发调试不直观临时测试、给团队发统一环境源码编译完全可控可自定义 CUDA 架构、GUI、第三方库版本方便二次开发耗时较长依赖管理需要自己操心长期开发、集成自有数据流、部署到生产服务器我最终选择源码编译核心原因是 COLMAP 很多时候不是终点而是起点。比如我要往里面加自定义的特征提取模块、改 UI、或者把它的重建结果接入我自己的 MVS 流程这时候拿着别人的二进制就很被动。另外自己编译可以把CMAKE_CUDA_ARCHITECTURES精确设到自己显卡的计算能力上性能能吃到最大。1.3 先把依赖树理清楚COLMAP 编译到底需要哪些库COLMAP 不是一个大孤岛它依赖了一大堆第三方库。我习惯把依赖分成四层方便理解和排查问题。第一层是基础构建工具gcc/g、CMake、Ninja、git。CMake 负责生成构建系统Ninja 负责并行编译git 不用说拉源码用的。第二层是图像 IO 相关库FreeImage加载各种图片格式、JPEG/PNG/TIFF编解码库。COLMAP 处理的就是图像数据这一步绕不开。第三层是数值计算和优化相关库Eigen3线性代数核心、Ceres Solver做 Bundle Adjustment 的主力、SuiteSparse稀疏线性求解、glog/gflags日志和命令行参数。这一层是重建质量的关键也是编译过程中最容易出幺蛾子的地方。第四层是 GUI 相关Qt5、QScintilla、GLEW、OpenGL。如果你不需要图形界面可以把 GUI 关掉省不少事但 COLMAP 的 GUI 确实好用查看稀疏点云、各个视角的相机位置非常直观。我用一个类比来理解这套结构CMake 像施工队总指挥负责把各路人马组织起来第三方依赖就是提前做好的建材比如 Ceres Solver 相当于一块高精度预制板直接拿来用不需要自己从零烧水泥。编译 COLMAP 本质上就是把“建材”备齐然后叫“施工队”开工。2. 核心依赖安装与关键细节2.1 安装 CUDA 12.9 Toolkit先装驱动还是只装 Toolkit装 CUDA 是这整套流程里最容易被绊倒的地方先把这个搞定再谈别的。CUDA 的安装分为两种主流方式一种是 deb 包方式一种是 runfile 方式。还有一个前置问题显卡驱动是装新版还是保留旧版。我这次用的是 runfile 方式理由是它可控性最高。deb 方式会把 CUDA 和显卡驱动绑在一起装如果你系统里已经有一个稳定运行的 NVIDIA 驱动deb 方式很可能直接把你的驱动换掉重则导致图形界面黑屏。runfile 方式可以选择不装驱动只装 Toolkit 本体就像给软件单独装一个“运行时环境”而不去动系统已有的“驱动固件”。具体步骤去 NVIDIA 官网下载 CUDA Toolkit 12.9 的 runfile 安装包。步骤是官网 → 选择 Linux → x86_64 → Ubuntu → 24.04 → runfile (local)官网直接拷贝下载命令即可。如果系统里已经有可用驱动先别急确认一下版本nvidia-smi能看到显卡信息且驱动版本不太老的话就能放心用下面的命令跳过驱动安装。给 runfile 加执行权限并执行chmod x cuda_12.9.0_*.run sudo ./cuda_12.9.0_*.run --toolkit --toolkit-path/usr/local/cuda-12.9 --no-opengl-libs这里的--toolkit指的是只装 CUDA 工具包--no-opengl-libs避免覆盖系统的 OpenGL 库如果机器还要跑桌面环境这一项很重要装完后再补一句sudo ln -sf /usr/local/cuda-12.9 /usr/local/cuda环境变量配置这是很多人忽视的一步。把下面这四行写进~/.bashrcexport CUDA_HOME/usr/local/cuda export PATH$PATH:/usr/local/cuda/bin export LD_LIBRARY_PATH$LD_LIBRARY_PATH:/usr/local/cuda/lib64然后source ~/.bashrc通过nvcc -V验证版本。整个过程听起来不复杂但我见过太多人死在环境变量上。nvcc找得到但 CMake 或运行时找不到libcudart.so就是LD_LIBRARY_PATH没配对。注意如果你的机器本来就要做桌面 UI千万别手贱装成整个 CUDA deb 包带的新驱动极易跟桌面环境起冲突最后落得“开机进不了图形界面”的下场。runfile 安装是你在这块最稳的靠山。2.2 一套干净的系统依赖apt 包的选择与调配Ubuntu 24.04 的好处在于很多 COLMAP 的依赖都能直接用 apt 装上不用一个个去手动编译。我建议在编译 COLMAP 之前先把这些包装齐sudo apt update sudo apt upgrade -y sudo apt install -y \ build-essential \ cmake \ ninja-build \ git \ libboost-all-dev \ libeigen3-dev \ libfreeimage-dev \ libgoogle-glog-dev \ libgflags-dev \ libglew-dev \ qtbase5-dev \ libqt5opengl5-dev \ libcgal-dev \ libflann-dev \ libsqlite3-dev \ libmetis-dev \ libsuitesparse-dev \ libqscintilla2-qt5-dev这里有几个点要特别注意第一libqscintilla2-qt5-dev在 Ubuntu 24.04 的仓库里可能不叫这个名字不同小版本下会有包名变动。如果 apt 提示找不到可以先apt search qscintilla搜一下实际的包名再决定装那个。QScintilla 是 COLMAP GUI 用来做脚本编辑器的组件没有它 GUI 编译会挂。第二libmetis-dev和libsuitesparse-dev对 Ceres Solver 和最终的稀疏求解非常重要。Metis 是做图剖分的工具库SuiteSparse 里面的CXSparse、CHOLMOD是 COLMAP 做大规模稀疏线性求解的底层依赖。少了它们编译会报一些跟SuiteSparse相关的找不到符号错误。第三libceres-dev在 Ubuntu 24.04 里是存在的但版本不一定够新。COLMAP 3.13.0 对 Ceres 有最低版本要求通常要 2.2不同时期仓库里的 Ceres 版本线也不好说。为了保证不在这卡壳我一般宁可从源码编译 Ceres这在下一节展开。2.3 为什么建议源码编译 Ceres SolverCeres Solver 是 COLMAP 做 Bundle Adjustment光束法平差的核心优化库。它的作用贯穿 SfM 的每一次迭代优化可以说是重建精度的一个决定性因素。从 apt 仓库直接装libceres-dev确实方便但版本往往滞后。以我这次的环境为例apt 仓库的 Ceres 版本在编译 COLMAP 3.13.0 时差点不够格与其做各种“版本下限”的妥协不如直接源码编译最新稳定版一劳永逸。源码编译 Ceres 也不难大概就是标准的三步走git clone https://ceres-solver.googlesource.com/ceres-solver cd ceres-solver mkdir build cd build cmake .. -GNinja -DBUILD_SHARED_LIBSON -DBUILD_EXAMPLESOFF -DBUILD_TESTINGOFF ninja sudo ninja install关键参数解释-DBUILD_SHARED_LIBSON编译成动态库而不是静态库。虽然静态库链接时更方便但后续如果有多个项目共用同一份 Ceres动态库可以显著减小二进制体积也方便升级。-DBUILD_EXAMPLESOFF和-DBUILD_TESTINGOFF跳过示例和测试代码能省下不少编译时间毕竟我们这里只是把它当作依赖。安装完 Ceres 之后最好跑一下ldconfig确保系统能找到刚安装的动态库sudo ldconfig这个动作很关键因为如果 Ceres 装进了/usr/local/lib而系统的动态库缓存没更新后面 COLMAP 链接时就会报“找不到 libceres.so”的错。3. 完整编译流程实操3.1 源码获取与构建目录规划源码获取没有太多技巧直接从 GitHub 拉 COLMAP 的官方仓库。注意要拉对 release 版本不要在 master 分支上浪master 分支的代码往往在快速演进中依赖要求可能也在变。这次要的是 3.13.0git clone https://github.com/colmap/colmap.git cd colmap git checkout 3.13.0目录规划这块看起来老生常谈但很影响后续的幸福程度。我的习惯是源码目录和构建目录分开构建目录建议建在源码目录内的build/而安装目录单独指定不要默认铺到系统目录。这样卸载的时候非常干净直接删掉安装目录就行。我习惯在构建时通过 CMake 参数显式指定安装前缀比如-DCMAKE_INSTALL_PREFIX/opt/colmap-3.13.0。3.2 CMake 配置唯一不能写错的参数是 CUDA 架构CMake 配置是整个编译流程里信息量最大的一步也是新手最容易翻车的地方。先直接给出我这次实际使用的完整命令然后逐个解释cd colmap mkdir build cd build cmake .. -GNinja \ -DCMAKE_BUILD_TYPERelease \ -DCMAKE_INSTALL_PREFIX/opt/colmap-3.13.0 \ -DCMAKE_CUDA_ARCHITECTURES89 \ -DCUDA_ENABLEDON \ -DGUI_ENABLEDON \ -DCMAKE_CUDA_COMPILER/usr/local/cuda/bin/nvcc很多人配置 CMake 时最容易栽在CMAKE_CUDA_ARCHITECTURES上。这个参数的实质是把 CUDA 的汇编器需要支持的计算能力列表告诉编译器。我的显卡是 Ada Lovelace 架构的 RTX 40 系计算能力是 8.9所以写成89。NVIDIA 对不同架构的计算能力有个对应表显卡架构典型型号计算能力TuringRTX 20 系列75AmpereRTX 30 系列、A10080 / 86Ada LovelaceRTX 40 系列89HopperH10090如果你不清楚自己的显卡计算能力可以在终端直接跑nvidia-smi --query-gpucompute_cap --formatcsv如果代码要部署到多种显卡上可以写成75;80;86;89用分号隔开。但也没必要无限堆砌每种架构都会让编译时间变长、二进制体积变大实际用哪种卡就写哪一种这也是源码编译的价值之一。-DCUDA_ENABLEDON是 COLMAP 自己定义的选项用来控制是否启用 CUDA 相关模块。如果你在装好了 CUDA 的情况下这里显示 OFF多半是 CMake 没探测到 CUDA后面排查章节我会细说。-DGUI_ENABLEDON默认一般是开着如果你不需要图形界面或者 Qt 相关依赖出了问题可以临时关掉OFF把核心编译跑通之后再回头处理 GUI 问题。-DCMAKE_CUDA_COMPILER/usr/local/cuda/bin/nvcc属于防御性写法。系统里同时存在多个 CUDA 版本时CMake 可能找到旧的 nvcc显式指定才能确保用的是 12.9 的那一套。3.3 Ninja 并行编译与安装配置完成后进入编译阶段。Ninja 相比 make 的优势是全量构建时的依赖调度更精细增量编译更快输出也更清爽。不过并行编译的线程数选择需要稍微动点脑子ninja -j8-j后面的数字不是越大越好。CUDA 的编译过程其实分两步先是nvcc把.cu源码编译成 PTX 或 cubin这步非常吃内存。我实测下来一个 nvcc 编译线程峰值能吃掉 2~3GB 内存如果机器只有 16GB 内存却开-j16编译器很容易在链接阶段因为内存不足被 OOM Killer 干掉报一些看起来非常诡异的“internal compiler error”。保险的做法是查看物理内存总量来估算线程数free -h nproc比如内存 32GB、CPU 12 核那么-j6或-j8是比较舒服的档位既能让 CPU 满负荷运转又不会在内存上翻车。编译顺利的话几分钟后就能看到ninja输出的完成信息。接下来执行安装sudo ninja install由于配置时指定了CMAKE_INSTALL_PREFIX/opt/colmap-3.13.0所有编译好的二进制、头文件、库文件都会被放到这个目录里。验证是否安装成功/opt/colmap-3.13.0/bin/colmap -h能看到 COLMAP 的帮助信息那一刻就说明命令行版本已经没问题了。如果想验证 GUI 是否正常编译出来/opt/colmap-3.13.0/bin/colmap gui正常情况下会弹出一个 Qt 窗口左侧是场景树右侧是三维视图区域。4. 常见问题与排查技巧实录4.1 CUDA 检测失败 / 版本识别不对这是源码编译 COLMAP 时最容易碰到的问题之一。症状一般是 CMake 配置阶段输出的日志里CUDA_ENABLED显示 OFF或者编译到一半报CUDA_cublas_LIBRARY not found、CUDA_cudart_LIBRARY not found。排查思路按照从用户态到配置态的先后顺序来第一步验证nvcc -V是否能正常输出版本信息。这一步是最低级别检查如果nvcc: command not found说明环境变量没配对回到 2.1 节把~/.bashrc重新检查一遍。第二步验证 CMake 能否找到 CUDAcmake --find-package -DNAMECUDA -DCOMPILER_IDGNU -DLANGUAGECXX -DMODEEXIST如果找不到多半是 CMake 的CUDAToolkit_ROOT没有指向正确位置。在 3.2 节的 CMake 命令里补一项-DCUDAToolkit_ROOT/usr/local/cudaCMake 就会沿着这个路径去找include/cuda.h和lib64/libcudart.so。第三步清掉旧的 CMakeCache 重新配置。这个灵感是我从一次极其痛苦的排查中得来的。有时候第一次 CMake 配置用的环境是坏的CMake 会把错误的路径缓存到CMakeCache.txt后面怎么改环境变量都不生效。解决方式简单粗暴rm -rf CMakeCache.txt CMakeFiles然后再重新跑 CMake 配置命令往往问题就奇迹般地消失了。4.2 GUI 编译报错QScintilla、Qt 相关的坑GUI 相关的编译错误非常折磨人因为报错信息往往晦涩难懂比如“找不到Qsci/qscilexer.h”或者“QT5::Widgets相关 target not found”。这两类报错说明的核心问题是一致的Qt5 或者 QScintilla 的开发头文件没有正确安装要么是装错了包要么是版本不一致。在 Ubuntu 下Qt5 开发头文件由qtbase5-dev提供QScintilla 由libqscintilla2-qt5-dev提供这点可以回看 2.2 节。如果确实搜不到 QScintilla 或者安装后依旧报错一个务实的备选方案是先关掉 GUI 编译-DGUI_ENABLEDOFF先把核心的 COLMAP 命令行编译跑通确保 CUDA 相关的功能和重建流程没有问题。之后再回过头来专门解决 QScintilla 的版本问题这样可以避免 GUI 依赖的问题阻塞整条编译链路。如果必须要 GUI可以下载 QScintilla 的源码单独编译再用CMAKE_PREFIX_PATH告诉 COLMAP 到哪找它。4.3 链接期 OOM 与并行度控制前面提到过Ceres、SuiteSparse 这类大型 C 库在链接阶段会吃很多内存APR 阶段更是会并发产生大量.o文件。很多人第一次跑ninja时图省事直接-j$(nproc)然后眼睁睁看到进程被系统杀掉日志里甚至不出现编译器报错只有一句 “Killed”。解决方案是动态调整并行度。我建议用watch -n 2 free -h开一个终端实时监控内存核心编译线程单独开另一个终端跑。如果内存占用眼看要见底就打断编译改用更小的并行数重新执行kill -INT $(pgrep -f ninja) # 中断编译 ninja -j4 # 降低线程数Ninja 有断点续传的能力已经编译完的目标不会重复编译所以中断重来并不可怕。4.4 其他小坑速查表我把这几天的其他零散问题整理成一张速查表照着查能省不少时间症状可能原因快速对策CMake 找不到 Boostlibboost-all-dev 没装或版本冲突apt install libboost-all-dev必要时指定-DBOOST_ROOTEigen 报错系统有多个 Eigen 版本卸载旧版统一用/usr/include/eigen3或设置-DEIGEN3_INCLUDE_DIRCeres 报错“Your Ceres version is too old”apt 的 Ceres 太旧源码编译新版 Ceres重新ldconfig编译时 NVCC 报错 “unsupported GNU version”CUDA 与 GCC 版本不匹配CUDA 12.9 对 GCC 13 兼容没问题老 CUDA 需要加--allow-unsupported-compiler或换低版本 GCC找不到libfreeimage.soFreeImage 没装apt install libfreeimage-dev运行时报 “error while loading shared libraries”动态链接库路径缺失在/etc/ld.so.conf.d/colmap.conf写入/usr/local/lib运行sudo ldconfig其中的“NVCC 报错 unsupported GNU version”值得多说两句。CUDA 和 GCC 的版本兼容矩阵是真实存在的新版 CUDA 通常只支持到某个 GCC 大版本。如果你用老 CUDA 配 Ubuntu 24.04 自带的 GCC 13很可能会被 NVCC 拒绝。这种情况下两个选择一个是装一个老版本 GCC通过update-alternatives切换默认 gcc/g另一个是在 NVCC 编译参数里加--allow-unsupported-compiler。第一个办法更稳第二个办法属于把安全阀门拔了硬上我建议你就算用也要多留个心眼编译产物是否正常要以最终运行测试为准。5. 最后再分享一个小技巧编译安装完 COLMAP 后我建议你立刻做一个“全流程冒烟测试”别急着拿真实数据集跑。用 COLMAP 仓库自带的测试数据或者随便一张图片做feature_extractor能跑通就说明 CUDA 模块、图像 IO、数据库读写这些链路都正常。再跑一次mapper输入端到端 SfM 管线这一步能同时验证 Ceres Solver 和稀疏求解器是否有问题。比起拿着一大堆无人机影像跑到一半才发现环境没配对先花一根烟的功夫做冒烟测试要划算得多。这套 COLMAP 3.13.0 CUDA 12.9 Ubuntu 24.04 的组合我这段时间跑下来很稳。个人经验是编译环境这块版本组合千万别盲目追新用之前先把兼容性矩阵查清楚能避免绝大多数莫名其妙的报错。如果读者只是验证算法跑直接下载官方二进制或拉一个 Docker 镜像确实更省心但要真正做二次开发、往生产环境里部署自己编译一遍的价值是无可替代的——你对自己手里这套环境会有一种“心里有底”的确定感。希望这篇能帮你跳过我最开始走过的那些弯路。
返回列表