首页 / 资讯中心 / 文章详情

Ubuntu下OpenCV+opencv_contrib+VTK源码编译完整指南

Ubuntu下OpenCV+opencv_contrib+VTK源码编译完整指南 ★ FEATURED ARTICLE
做三维视觉的人肯定都经历过这么一遭明明装好了 opencv-python跑 SURF 却甩给你一个 AttributeError或者点云重建得挺漂亮想看两眼结果发现连 viz 模块的影子都没有。原因很直接官方预编译包把 opencv_contrib 和 VTK 支持都砍掉了尤其是 VTK 这种带渲染依赖的大家伙官方不可能塞进默认发布包里。所以真想把 OpenCV 用透绕不开 OpenCV opencv_contrib VTK 编译这条路。这篇文章是我在 Ubuntu 上多次走通这条编译链路的完整记录从“为什么非要自己编”“怎么选版本”到 VTK 单独编译、OpenCV 联合编译再到最后验证 demo一条龙讲清楚。适合做三维重建、医学图像可视化、机器人 SLAM、目标位姿估计以及想把深度学习结果做成可交互三维展示的同学直接抄作业。1. 为什么非要自己编译官方包里缺了这三样1.1 你手里的官方包其实是个“缩水版”很多人习惯pip install opencv-python或者直接下载官网的预编译 exe / deb觉得跑个识别、读个视频就够了。但真到做项目的时候问题一个接一个。最典型的是cv2.xfeatures2d这个模块SURF、BEBLID、LUCID 这类经典特征全在里面官方包不编译它其次是aruco、face、text、ximgproc这些子模块全在 opencv_contrib 里预编译包一概没有。我之前带一个三维重建项目模型已经重建出来了想在调试阶段把相机轨迹和点云一起显示出来发现官方包连opencv_viz都没有。viz 模块其实在 OpenCV 主仓库里就有但它强依赖 VTK官方默认不启用。就这一个模块就够你从“能用”走向“必须源码编译”。这么看自己编译不是折腾是解锁 OpenCV 全部能力的前置条件。1.2 VTK 是 viz 模块的地基OpenCV 自带两个世界图像处理和三维可视化。图像处理只需要矩阵运算但三维可视化需要一整套渲染管线包括渲染窗口、相机、光照、交互器这就是 VTK 的活。把两者做一个不贴切的类比OpenCV 像一个工具箱VTK 是一块 3D 画板viz 模块就是工具箱里专门用来把点云、位姿、网格搬到画板上的那把手。有了 viz 模块你在做视觉里程计的时候可以直接把相机位姿画出来看看轨迹是否漂移做点云配准的时候可以把源点云、目标点云、对应点连线同时显示出来。这个对调试的效率提升是巨大的比对着控制台里一串数字猜原因强太多。而这一切的前提就是编译 OpenCV 时让它找到 VTK即WITH_VTKON。1.3 版本搭配的底层逻辑编译这套东西最容易翻车的不是编译过程本身而是版本不匹配。opencv 和 opencv_contrib 必须严格用同一个版本号比如都选 4.8.0VTK 建议选 9.2.x 系列太老的 VTK 8.2 也能编过 OpenCV但和新版编译器的兼容性就差一些。我用的搭配是 OpenCV 4.8.0 opencv_contrib 4.8.0 VTK 9.2.6这套在 Ubuntu 22.04 LTS 默认的 gcc 11 下很稳不需要额外打补丁。这里强调一个原则不要追新OpenCV 每季度的例行版本更新都可能带来编译行为变化VTK 也一样。稳定复现比功能最新重要得多等你把整套流程跑熟再考虑升级。组件推荐版本说明OpenCV4.8.0主仓库源码release 包opencv_contrib4.8.0必须与主仓库同版本VTK9.2.6建议 9.2.x兼容 OpenCV 4.xCMake3.22Ubuntu 22.04 默认即可编译器gcc 11默认工具链不用额外折腾2. 动手前的准备工具链、依赖和目录规划2.1 系统和编译工具链我用的是 Ubuntu 22.04 LTS内核版本、桌面环境对编译本身影响不大但要注意你的系统里得有完整的编译工具链。新装好的系统往往只有 gcc没有 make、cmake、ninja更缺各种头文件。先把基础工具装齐sudo apt update sudo apt install build-essential cmake ninja-build pkg-config \ git wget然后确认版本cmake --version至少在 3.22 以上gcc --version是 11 或者更高。如果版本偏低比如还在用 Ubuntu 20.04 的 cmake 3.16编译新版 VTK 会提示CMake 3.16 is lower than required这时候建议直接装新版 cmake用 apt 自带的旧版本硬编大概率浪费时间。ninja 比 make 快不少尤其在增量编译的时候体验差距很明显Linux 下都装上后面统一用cmake --build加--parallel的方式构建。2.2 依赖库宁可装齐不要缺项OpenCV 本身有很多可选依赖缺了某些库CMake 会静默降级你可能编完了才发现读不了某些图片格式、调不了摄像头、视频解码走的是自带弱实现。所以这里我的习惯是编译前一次性装齐。以下是我长期使用的最小完整依赖集sudo apt install libgtk-3-dev qtbase5-dev libqt5opengl5-dev \ libavcodec-dev libavformat-dev libswscale-dev v4l-utils \ libxvidcore-dev libx264-dev libxine2-dev \ libjpeg-dev libpng-dev libtiff-dev libopenexr-dev \ libwebp-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \ libtbb-dev libeigen3-dev libglew-dev \ libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev里面的 qtbase5-dev 和 libqt5opengl5-dev 主要是给 VTK 和 OpenCV 的 GUI 用的eigen3 是矩阵库OpenCV 的某些 contrib 模块会依赖它TBB 是并行加速库libgstreamer 负责视频流的输入输出。如果某个库没装最轻的后果是 CMake 输出里对应的WITH_XXXOFF重则 compile 到某模块时报 has no member 之类的错误。不要偷懒一句话能装完的事别用半个下午去排版本缺失的错。2.3 源码和目录结构规划我强烈建议用一个独立的目录来装这三份源码结构清楚出了问题也好排查。别把源码散放在 downloads 或者 home 下后期增量维护会非常痛苦。mkdir -p ~/workspace/opencv-build cd ~/workspace/opencv-build在这个目录下放 OpenCV 主仓库、opencv_contrib 仓库、VTK 源码再加上对应的三个 build 目录。举个例子cd ~/workspace/opencv-build # 在官方源码页面下载对应 4.8.0 的 release 源码包或通过版本管理工具拉指定 tag wget opencv-4.8.0.tar.gz wget opencv_contrib-4.8.0.tar.gz wget VTK-9.2.6.tar.gz tar xzf opencv-4.8.0.tar.gz tar xzf opencv_contrib-4.8.0.tar.gz tar xzf VTK-9.2.6.tar.gz如果你习惯用 git就直接拉取 tag注意分支名不要用默认 master老老实实切到 4.8.0否则 contrib 和主仓库版本错位编译的时候各种符号对不上。源码目录准备好以后我习惯在同一个父目录下建 build-vtk、build-opencv 两个构建目录保证源码目录保持干净这样如果你要重编删掉 build 目录即可不用重新解压源码。3. 先搞定 VTK被很多人忽略的第一步3.1 VTK 的 CMake 配置项怎么选才合适VTK 9.x 的 CMake 选项和 8.x 差别挺大9 开始用了一套 “group” 机制把功能分成 Rendering、Qt、Imaging、Visualization 等组。很多人拿到 VTK 源码直接默认配置编编出来倒是不报错但 OpenCV 的 viz 模块找不到自己需要的组件回头再查就麻烦了。我基本固定用这样一组配置cd ~/workspace/opencv-build cmake -S VTK-9.2.6 -B build-vtk \ -DCMAKE_BUILD_TYPERelease \ -DCMAKE_INSTALL_PREFIX/opt/vtk-9.2.6 \ -DVTK_GROUP_ENABLE_RENDERINGYES \ -DVTK_GROUP_ENABLE_IMAGINGYES \ -DVTK_GROUP_ENABLE_QTYES \ -DVTK_GROUP_ENABLE_VIEWSYES \ -DBUILD_TESTINGOFF \ -DBUILD_EXAMPLESOFF \ -DBUILD_SHARED_LIBSON逐一解释。CMAKE_BUILD_TYPERelease不开调试符号编译时间短运行时渲染性能也正常CMAKE_INSTALL_PREFIX/opt/vtk-9.2.6让 VTK 装到独立目录避免污染系统 /usr/local后面你用 project 引用 OpenCV 时也能直接指定 VTK 路径VTK_GROUP_ENABLE_RENDERING是渲染核心OpenCV 的 WCloud、WTriangleMesh 这些 widget 都是用渲染管线画出来的不开这个后面指定类型时报错VTK_GROUP_ENABLE_QT是让 VTK 能创建 Qt 界面如果你计划把三维窗口嵌到自己的 Qt 应用里这个必须开后台你是纯命令行调试开这一项额外多编一些 Qt 组件但值得避免回头想接 Qt 又要重编 VTK。BUILD_TESTINGOFF和BUILD_EXAMPLESOFF纯粹是省时间不编那些你根本用不到的例子和测试程序。BUILD_SHARED_LIBSON保持动态库后面 OpenCV 链接时 so 依赖关系更自然。3.2 VTK 编译与安装耐心等完这一步配置完以后就是构建安装cmake --build build-vtk --parallel 8 cmake --install build-vtk在我这台 8 核 16G 内存的机器上VTK 9.2.6 全量编译大约 20 分钟左右主要耗时在 VTK 的 Rendering 和 Interaction 组件上。编译过程中可以看到输出里不断出现Building CXX object ...不用管注意有没有Error关键字就行。有些机器内存比较小同时开太多编译任务会触发 OOM建议把--parallel数字降到 4甚至 2慢一点无所谓稳定第一。装完之后检查一下目录ls /opt/vtk-9.2.6/lib/cmake/正常情况下应该能看到 vtk-9.2 这样的目录里面是 VTKConfig.cmake 等各种 cmake 模块文件。这个目录路径就是后面给 OpenCV 用的VTK_DIR。如果你忘了这一步直接跳到 OpenCV 编译CMake 会跟你说找不到 VTK。这里的经验是VTK 编译本身不难难的是配置选项不满足下游要求。一定记得在编 OpenCV 前先用一个极小项目验证 VTK 可用哪怕是 cmake 导出一个 VTK 工程再编译一个 vtkCubeSource 的 demo也比最后 OpenCV 编到半路报错强。4. OpenCV opencv_contrib 联合编译实操4.1 核心 CMake 参数逐个拆解OpenCV 的 CMake 参数几百个真正影响这条编译链路的其实就那么十来个。其他默认值一般情况下不用动动了反而容易出幺蛾子。下面是我实测稳定的一组配置cd ~/workspace/opencv-build cmake -S opencv-4.8.0 -B build-opencv \ -DCMAKE_BUILD_TYPERelease \ -DCMAKE_INSTALL_PREFIX/opt/opencv-4.8.0 \ -DOPENCV_EXTRA_MODULES_PATH../opencv_contrib-4.8.0/modules \ -DWITH_VTKON \ -DVTK_DIR/opt/vtk-9.2.6/lib/cmake/vtk-9.2 \ -DWITH_QTON \ -DWITH_TBBON \ -DWITH_EIGENON \ -DOPENCV_ENABLE_NONFREEON \ -DOPENCV_GENERATE_PKGCONFIGON \ -DBUILD_EXAMPLESOFF \ -DBUILD_TESTSOFF \ -DBUILD_opencv_python3ONOPENCV_EXTRA_MODULES_PATH是整个联合编译的灵魂指向 opencv_contrib 源码下的 modules 目录。CMake 会扫描这个目录下所有子模块把它当成 OpenCV 的一部分一起编译。注意你要确保它指向的是 contrib 里的 modules 目录本身而不是opencv_contrib-4.8.0这个外层目录指向外层会有模块扫描不到的问题。WITH_VTKON就是开启 viz 模块的开关。OpenCV 的 CMake 逻辑是这样先判断你有没有指定 VTK_DIR再决定 viz 模块编不编。如果WITH_VTKON但找不到 VTKCMake 会直接报错而不是默默关闭。VTK_DIR指定到 VTK 的 cmake 模块目录这个路径在编译后的输出里也能看到是确认 OpenCV 是否真的找到 VTK 的关键信息。OPENCV_ENABLE_NONFREEON这个开关要专门说。它控制一些历史上受专利保护的算法比如 SURF、BEBLID 一类。在 OpenCV 4.4 之后 SIFT 已经转到主仓库了不需要这个开关但 SURF 等还在 contrib 里所以如果你要用必须打开。多数情况下打开它没有副作用只是多编几个模块。WITH_QTON让 highgui 的界面变好看一些能和前面 VTK 的 Qt 组件配合后面你做可视化交互时体验差别明显。OPENCV_GENERATE_PKGCONFIGON会生成 opencv4.pc 文件方便使用 pkg-config 管理编译参数Linux 下做 C 项目非常省事。4.2 编译、安装与环境变量配置完成后在输出里搜一下VTK和contrib应该能看到类似这样的关键行VTK: YES OpenCV modules: ... viz ... xfeatures2d ...尤其注意有没有opencv_viz出现在将要生成的模块列表里。如果没有多半是 VTK_DIR 没配对回去查。另外To be built那一栏如果出现opencv_xfeatures2d说明 contrib 识别成功。确认无误后开始编译cmake --build build-opencv --parallel 8 cmake --install build-opencvOpenCV 全量编译比 VTK 更耗时我第一次在 8 核机器上编了大概 35 分钟。如果磁盘空间不够中途会在写 .o 文件的时候报 no space left务必保证还有 15G 以上的空闲空间。装完之后OpenCV 会出现在/opt/opencv-4.8.0下里面目录结构大致是 bin、lib、include、share。环境变量这块千万别漏。C 项目编译时依赖 OpenCV 的 cmake 配置路径运行时依赖动态库路径。我个人在~/.bashrc里追加了这几行export OpenCV_DIR/opt/opencv-4.8.0/lib/cmake/opencv4 export LD_LIBRARY_PATH/opt/opencv-4.8.0/lib:/opt/vtk-9.2.6/lib:$LD_LIBRARY_PATH export PYTHONPATH/opt/opencv-4.8.0/lib/python3.10/site-packages:$PYTHONPATH然后source ~/.bashrc。稍微解释一下OpenCV_DIR 是给后续 CMake 工程里find_package(OpenCV)用的LD_LIBRARY_PATH 用来让动态链接器找到 libopencv_world.so 和 VTK 的 soPYTHONPATH 则决定你import cv2到底导入哪个版本的 cv2没有这一行python 会优先用系统 site-packages 里可能残留的旧版 opencv-python。5. 验证编译结果确认这是你要的“全家桶”5.1 模块和版本检查编译完了第一件事不是写业务代码而是确认你编出来的确实对。C 工程验证最直接的方式是建一个最小的 CMake 工程cmake_minimum_required(VERSION 3.16) project(check_opencv LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) find_package(OpenCV REQUIRED COMPONENTS core imgproc highgui viz xfeatures2d) add_executable(check main.cpp) target_link_libraries(check PRIVATE ${OpenCV_LIBS})find_package里的viz和xfeatures2d是关键只要你编好了这两个组件都能被找到。如果找不到CMake 会直接报错告诉你 not found by name。找到之后编译出来的程序运行一下只要能正常启动不报缺 so就在动态链接层面成功了。python 侧验证也很直观import cv2 print(cv2.__version__) info cv2.getBuildInformation() print(info)重点看Modules和To be built区域出现viz、xfeatures2d字样再看VTK support是不是YES。我见过有人编译后忘了source ~/.bashrc在 python 里 import 到旧的 pip 版本白白怀疑了半天编译成果。所以验证脚本里可以先打印cv2.__file__确认路径确实是/opt/opencv-4.8.0/lib/python3.10/site-packages/cv2。5.2 跑一个交互式三维可视化 Demo验证 viz 模块能不能真正用起来我一般写一个很小的 C demo生成一个网格并显示#include opencv2/viz.hpp #include opencv2/highgui.hpp int main() { cv::viz::Viz3d window(VTK with OpenCV); cv::Mat points(200, 3, CV_32FC3); cv::RNG rng; for (int i 0; i 200; i) { float x rng.uniform(-3.0f, 3.0f); float y rng.uniform(-3.0f, 3.0f); float z rng.uniform(-3.0f, 3.0f); points.atcv::Vec3f(i) cv::Vec3f(x, y, z); } window.showWidget(Cloud, cv::viz::WCloud(points, cv::viz::Color::red())); window.showWidget(Coords, cv::viz::WCoordinateSystem(1.0)); window.spinOnce(1, true); std::cout viz OK std::endl; return 0; }这段代码简单到不需要业务逻辑但它能一次性验证 OpenCV 和 VTK 的链接关系是否畅通。跑起来你能看到一个小窗口红色点云和坐标轴可交互旋转说明 viz 模块真的在工作。如果你的场景里有相机位姿可以再加一个cv::viz::WCameraPosition显示相机锥体那才是真正的三维视觉调试神器。5.3 后续扩展的配合玩法编译这套环境通常不是为了编而编后面都会接实际需求。最常用的组合是contrib 的 xfeatures2d 提特征主仓库的 calib3d 做位姿估算viz 把位姿轨迹画出来。配合起来可以做一套 visual odometry 的可视化调试工具也可以在医学图像处理里把 CT 切片重建出的三维模型直接展示在窗口里。你如果还打算用 CUDA 加速至少先把 CPU 版本跑通再回来-DWITH_CUDAON增量编译这样排查问题时变量少一大截。6. 常见编译坑位与排查技巧实录6.1 卡死在第三方库下载ippicv 和 boostdescOpenCV 编译时会在配置阶段自动下载一些第三方文件其中两个地方最容易卡住一个是 IPP一个是 xfeatures2d 里的 boostdesc 和 vgg_generated 序列文件。现象是 CMake 配置到 90% 时长时间停在 downloading或者干脆超时报错。解决方案不要从网络侧入手而是手动把这些文件放到本地缓存目录里。IPP 的缓存目录一般在~/.cache/ippicvboostdesc 的在~/.cache/xfeatures2d。做法是从报错日志里找到它要下载的 URL 和文件名用浏览器或下载工具把文件拉下来放到对应缓存目录。然后重新运行 cmake 配置命令CMake 会检查本地文件是否匹配匹配就不再重复下载。这个方法不需要任何特殊工具纯粹是本地文件缓存安全也可靠。6.2 VTK 版本导致的视窗模块编译失败OpenCV 和不同 VTK 版本的兼容性不是完美无缺的。如果你用 VTK 9.0 或更早版本某些 OpenCV 版本下的 viz 模块会碰到 API 变更造成的编译错误比如找不到某个成员函数或者重载冲突。遇到这种报错先检查自己的 VTK 版本换成 9.2.x。社区里大量验证过 9.2 是相对安全的版本区间没必要当小白鼠去尝新版本。还有一种情况是系统自带了旧版本 VTK 的 so 或 cmake 文件导致 CMake 优先找到了错误版本。检查一下你指定的VTK_DIR是否真的是新装的 9.2.6 的路径别让系统 /usr/lib 下的旧文件混进来。这个问题的排查方法很直接把VTK_DIR指向的目录打印出来看是不是/opt/vtk-9.2.6/lib/cmake/vtk-9.2目录里 VTKConfigVersion.cmake 的版本号是多少。确认无误再重编 OpenCV。6.3 运行时报 shared library not found编译成功后cmake --build阶段可能没有任何报错但一运行 demo 就提示error while loading shared libraries: libopencv_viz.so.4.8: cannot open shared object file或者类似 VTK 的 so 找不到。这个问题的根源就是前面说的环境变量没生效。用ldd ./check看一眼动态库依赖如果某个 so 显示 not found检查对应路径是否在LD_LIBRARY_PATH里。注意改了.bashrc之后重新打开的终端才会生效当前终端要source ~/.bashrc或者重新登录。这个坑十有八九是因为新旧终端混用导致的不是编译问题。6.4 contrib 模块编译失败时的降级策略contrib 里有几十个子模块总有一两个在你当前环境下编译不过去。比如某些模块依赖新版本的库而你的系统没那么新。我的建议是不要为了一个模块卡住整个项目。在 CMake 配置时用-DBUILD_opencv_xxxOFF把你不需要的模块关掉保证核心链路先通。比如你只用 xfeatures2d、aruco、viz那就可以把 text、face、bioinspired 这类冷门模块先关掉。等主流程全部验证 OK再回头研究争不过去的模块这时候专门看它的报错信息效率高得多。编译这套 OpenCV opencv_contrib VTK 的组合我前后至少完整走过三四次每次踩的坑都不大一样但归根结底绕不开版本对齐和依赖完整这两个核心。最让我意外的反而是那些看起来无关紧要的第三方文件下载卡住的时间比真正的源码编译还长。如果你只打算记住两条经验一是 opencv 和 contrib 必须严格同版本二是 VTK 的 CMake 配置要一次性到位。这两条做好后面基本就是等进度条了。另外再分享一个提升效率的小技巧完成一次干净的编译后把当时所有 CMake 配置命令存成一个 build.sh 脚本放在项目目录里。下次要换机器或者升级依赖直接跑脚本不用回忆那些参数是干嘛的。我后来在另一台机器上重新搭环境就是靠当时存的脚本半小时不到就跑通了。这种脚本现在看已经是我的标准操作推荐你也养成这个习惯。
阅读完成 · 觉得有帮助?
咨询建站