资讯动态

Ubuntu 20.04源码编译OpenCV 3.4.16:SLAM十四讲环境搭建与多版本共存指南

发布时间:2026/10/21 22:49:54 来源:尧图企业网站定制
1. 为什么在Ubuntu 20.04上装OpenCV 3.4.16这件事值得单独写一篇如果你正在跟着《视觉SLAM十四讲》做练习大概率会在第几讲的时候撞上一堵墙书里的示例代码依赖OpenCV 3.x而你手头的Ubuntu 20.04默认软件源里只有OpenCV 4.2。直接apt install libopencv-dev装出来的版本编译书里的例程时会报一堆CV_LOAD_IMAGE_UNCHANGED未定义、cv::xfeatures2d找不到之类的错误。这不是你代码写错了是版本不匹配。OpenCV 3.4.16是3.4.x系列的后期版本它对C11的支持比较完善同时保留了SLAM十四讲里大量用到的旧版API比如cv::ORB、cv::DMatch、cv::drawMatches这些在4.x里被改过签名或者挪了头文件的接口。所以对SLAM初学者来说3.4.16是一个能跑通书里代码的稳妥选择。但问题在于Ubuntu 20.04的gcc 9、CMake 3.16、Python 3.8这套组合和OpenCV 3.4.16发布时的环境已经有代差了。直接源码编译会遇到几个经典坑-Werror导致的编译中断、xfeatures2d模块需要额外下载、Python绑定路径找不到、以及和系统自带OpenCV 4的冲突。这篇就把我实际在Ubuntu 20.04上从零编译安装OpenCV 3.4.16的完整过程拆开讲包括每一步为什么这么做、参数怎么定、踩过的坑怎么绕。适合的读者正在学SLAM十四讲、需要在Ubuntu 20.04上跑通旧版OpenCV例程的人或者任何需要在一个较新的系统上编译一个较老版本OpenCV的人。整个过程大概需要30到60分钟取决于机器性能。2. 编译前的环境盘点与依赖取舍2.1 先搞清楚系统里已经有什么动手之前先确认两件事系统里有没有已经装好的OpenCV以及你的编译工具链版本。很多人编译失败不是因为步骤错而是因为系统里已经有一个OpenCV 4编译出来的3.4.16和它打架。# 查看系统已安装的OpenCV版本 pkg-config --modversion opencv4 2/dev/null pkg-config --modversion opencv 2/dev/null # 查看gcc和cmake版本 gcc --version cmake --version如果pkg-config --modversion opencv4输出了4.2.x说明系统里有apt装的OpenCV 4。这个不用卸载但后面编译3.4.16时要把安装路径和它隔离开否则头文件和库会混在一起。我的做法是把3.4.16装到/usr/local下而apt装的4.2在/usr下通过CMAKE_INSTALL_PREFIX控制再用PKG_CONFIG_PATH切换。2.2 依赖包一次装齐别边编边补OpenCV编译过程中如果缺依赖CMake阶段会提示但有些是可选的不装也能过只是对应功能没有。对SLAM用途来说下面这些是必须的sudo apt-get update sudo apt-get install -y build-essential cmake git pkg-config sudo apt-get install -y libgtk-3-dev libavcodec-dev libavformat-dev libswscale-dev sudo apt-get install -y libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev sudo apt-get install -y libdc1394-22-dev libv4l-dev sudo apt-get install -y python3-dev python3-numpy这里解释几个关键依赖的作用。libgtk-3-dev是给highgui模块用的没有它imshow就没法用SLAM调试时看特征点匹配图全靠它。libtbb-dev是并行加速库ORB特征提取这种计算密集操作会用到。libv4l-dev和libdc1394-22-dev是摄像头相关的如果你要用真实相机跑SLAM就得装。python3-dev和python3-numpy是为了生成Python绑定虽然SLAM十四讲主要是C但有时候用Python快速验证算法很方便。注意Ubuntu 20.04默认的Python是3.8OpenCV 3.4.16对Python 3.8的支持需要额外注意后面编译参数里会专门处理。2.3 关于xfeatures2d模块的取舍SLAM十四讲里有些章节会用到SIFT、SURF这些特征在OpenCV 3.x里它们被放在opencv_contrib的xfeatures2d模块中主仓库里没有。所以你需要同时下载主仓库和contrib仓库版本必须严格对应都是3.4.16。mkdir -p ~/opencv_build cd ~/opencv_build git clone -b 3.4.16 https://github.com/opencv/opencv.git git clone -b 3.4.16 https://github.com/opencv/opencv_contrib.git用-b 3.4.16指定分支确保两个仓库版本一致。如果只下主仓库编译出来的OpenCV没有SIFT书里相关代码会报错。contrib仓库比较大下载慢的话可以只保留需要的模块但为了省事建议全下。3. CMake配置阶段参数怎么定为什么这么定3.1 建立独立的构建目录不要在源码目录里直接cmake这是基本习惯。源码目录保持干净构建产物全放到build子目录出问题直接删掉重来。cd ~/opencv_build/opencv mkdir build cd build3.2 核心CMake参数逐条拆解下面这条命令是我实测能跑通的配置每个参数都有理由cmake -D CMAKE_BUILD_TYPERELEASE \ -D CMAKE_INSTALL_PREFIX/usr/local \ -D OPENCV_EXTRA_MODULES_PATH~/opencv_build/opencv_contrib/modules \ -D INSTALL_PYTHON_EXAMPLESOFF \ -D INSTALL_C_EXAMPLESOFF \ -D BUILD_EXAMPLESOFF \ -D BUILD_opencv_python3ON \ -D PYTHON3_EXECUTABLE/usr/bin/python3 \ -D PYTHON3_INCLUDE_DIR/usr/include/python3.8 \ -D PYTHON3_LIBRARY/usr/lib/x86_64-linux-gnu/libpython3.8.so \ -D PYTHON3_NUMPY_INCLUDE_DIRS/usr/lib/python3/dist-packages/numpy/core/include \ -D WITH_CUDAOFF \ -D WITH_OPENCLOFF \ -D ENABLE_PRECOMPILED_HEADERSOFF \ -D OPENCV_GENERATE_PKGCONFIGON \ ..逐条说。CMAKE_BUILD_TYPERELEASE开优化SLAM跑起来快很多别用Debug。CMAKE_INSTALL_PREFIX/usr/local把安装位置和apt的/usr隔开。OPENCV_EXTRA_MODULES_PATH指向contrib的modules目录这是启用xfeatures2d的关键。BUILD_EXAMPLESOFF和INSTALL_C_EXAMPLESOFF是为了省编译时间例程对SLAM用途没帮助。BUILD_opencv_python3ON开Python绑定后面三个PYTHON3_*参数是手动指定路径因为Ubuntu 20.04上CMake有时候找不到Python 3.8的头文件。WITH_CUDAOFF是因为大多数人没有NVIDIA显卡开了反而编译报错。ENABLE_PRECOMPILED_HEADERSOFF这个很关键Ubuntu 20.04的gcc 9配合预编译头会出问题关掉能避免一堆莫名其妙的编译错误。OPENCV_GENERATE_PKGCONFIGON会生成opencv.pc文件方便后面用pkg-config管理编译选项。3.3 CMake输出里要重点看什么cmake跑完后终端会打印一长串配置结果。别急着往下走重点看这几行-- OpenCV modules: -- To be built: core flann imgproc ... -- Unavailable: ... -- Python 3: -- Interpreter: /usr/bin/python3 (ver 3.8.x) -- Libraries: /usr/lib/x86_64-linux-gnu/libpython3.8.so -- numpy: /usr/lib/python3/dist-packages/numpy/core/includeTo be built列表里要能看到xfeatures2d如果它在Unavailable里说明contrib路径写错了或者版本不匹配。Python 3那几行要确认路径都找到了如果显示NO后面Python绑定就生成不了。提示如果cmake报错说找不到某个依赖先看错误信息里提到的包名用apt装对应的-dev包然后删掉build目录重新cmake。不要在原build目录里反复cmake缓存会干扰。4. 编译与安装时间、报错与应对4.1 用几个核怎么定编译OpenCV是个体力活核越多越快。先看CPU核数nproc假设输出是8那就用-j8。但注意如果内存不够核开太多会OOM。经验值是每核至少1.5GB内存。8核16GB内存可以-j88核8GB内存建议-j4。make -j$(nproc)编译时间参考8核机器大概15到25分钟4核大概40分钟。期间终端会刷大量编译信息只要不出现Error就正常。4.2 最常见的三个编译报错报错一error: CODEC_FLAG_GLOBAL_HEADER was not declared这是FFmpeg版本较新导致的OpenCV 3.4.16的cap_ffmpeg_impl.hpp里用了旧宏。解决办法是找到报错的文件把相关代码注释掉或者更稳妥的做法是在cmake时加-D WITH_FFMPEGOFF。SLAM用途基本不需要视频编解码关掉没影响。报错二error: numeric_limits is not a member of std这是gcc 9头文件包含变严格导致的某些源文件缺#include limits。解决办法是找到报错文件在开头手动加上这个include。这类错误通常出现在contrib模块里遇到一个补一个。报错三Python绑定相关的undefined reference如果PYTHON3_LIBRARY路径不对链接阶段会报错。回到cmake阶段确认路径用find /usr/lib -name libpython3.8*找到实际位置。注意编译过程中如果报错中断修完问题后直接重新make即可已经编译好的目标文件不会重编能省时间。但如果改了cmake参数建议删掉build目录重来。4.3 安装与刷新链接缓存编译完成后sudo make install sudo ldconfigldconfig刷新动态链接库缓存让系统能找到新装的库。不做这一步运行程序时会报error while loading shared libraries: libopencv_core.so.3.4。安装完成后库文件在/usr/local/lib头文件在/usr/local/include/opencv2pkg-config文件在/usr/local/lib/pkgconfig。5. 验证安装别只看版本号要跑通实际代码5.1 用pkg-config确认编译环境export PKG_CONFIG_PATH/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH pkg-config --modversion opencv如果输出3.4.16说明pkg-config能找到。但这里有个坑系统里同时有OpenCV 4时pkg-config --modversion opencv4可能还是4.2这正常因为两个版本的pc文件名不同。编译SLAM代码时用pkg-config --cflags --libs opencv不带4就会指向3.4.16。5.2 写一个最小测试程序光看版本号不够要实际编译运行一个用到核心功能的程序。建一个test_opencv.cpp#include opencv2/opencv.hpp #include opencv2/xfeatures2d.hpp #include iostream int main() { cv::Mat img cv::Mat::zeros(480, 640, CV_8UC3); cv::circle(img, cv::Point(320, 240), 100, cv::Scalar(0, 255, 0), 2); cv::Ptrcv::Feature2D orb cv::ORB::create(); std::vectorcv::KeyPoint kps; orb-detect(img, kps); std::cout ORB keypoints: kps.size() std::endl; cv::Ptrcv::xfeatures2d::SIFT sift cv::xfeatures2d::SIFT::create(); std::cout SIFT created OK std::endl; cv::imwrite(test_out.png, img); return 0; }编译命令g test_opencv.cpp -o test_opencv pkg-config --cflags --libs opencv ./test_opencv如果输出ORB keypoints: 0因为图是纯黑加个圆特征点少正常和SIFT created OK并且生成了test_out.png说明核心模块、xfeatures2d、highgui都正常。5.3 和SLAM十四讲代码对接时的路径问题书里的代码通常用CMake构建CMakeLists.txt里写的是find_package(OpenCV REQUIRED)。在Ubuntu 20.04上这个命令可能找到系统的OpenCV 4而不是你装的3.4.16。解决办法是在CMakeLists.txt里显式指定set(OpenCV_DIR /usr/local/lib/cmake/opencv4) find_package(OpenCV 3.4 REQUIRED)注意OpenCV 3.4.16的cmake配置文件放在/usr/local/lib/cmake/opencv4目录下虽然目录名带4但里面是3.4的配置。这是OpenCV 3.4.x后期版本的一个命名习惯别被目录名误导。6. 多版本共存时的环境切换经验6.1 为什么会出现编译过了但运行报错系统里同时有OpenCV 4.2apt装的在/usr/lib和3.4.16手动装的在/usr/local/lib时编译阶段用pkg-config指定了3.4的头文件但运行阶段动态链接器可能加载了4.2的库导致symbol lookup error。这是因为/usr/lib在链接器搜索路径里的优先级有时高于/usr/local/lib。验证方法ldd ./test_opencv | grep opencv看输出的libopencv_core.so.3.4指向哪个路径。如果指向/usr/lib下的4.2版本就说明加载错了。6.2 三种隔离方案对比方案做法优点缺点环境变量法设置LD_LIBRARY_PATH/usr/local/lib简单不改系统每次开终端要设容易忘卸载系统版apt remove libopencv-dev彻底无冲突影响其他依赖OpenCV4的软件容器隔离用Docker跑特定环境最干净学习成本高SLAM调试不便对SLAM学习场景我推荐环境变量法。在~/.bashrc里加一行export LD_LIBRARY_PATH/usr/local/lib:$LD_LIBRARY_PATH export PKG_CONFIG_PATH/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH这样每次开终端自动生效。如果某个程序确实需要OpenCV 4临时unset LD_LIBRARY_PATH再运行即可。6.3 一个容易忽略的坑Python绑定的路径如果你用Python验证SLAM算法import cv2时可能导入的是系统Python的OpenCV 4。检查import cv2 print(cv2.__version__) print(cv2.__file__)如果版本是4.2说明Python的模块搜索路径里系统路径优先。解决办法是在Python脚本开头手动插入路径import sys sys.path.insert(0, /usr/local/lib/python3.8/site-packages) import cv2或者设置PYTHONPATH环境变量。OpenCV 3.4.16的Python模块安装在/usr/local/lib/python3.8/site-packages/cv2下。7. 编译参数调优与常见问题速查7.1 缩短编译时间的几个实用调整如果只是跑SLAM十四讲很多模块用不上可以在cmake时关掉-D BUILD_opencv_javaOFF \ -D BUILD_opencv_jsOFF \ -D BUILD_opencv_appsOFF \ -D BUILD_TESTSOFF \ -D BUILD_PERF_TESTSOFF \ -D BUILD_DOCSOFFBUILD_TESTS和BUILD_PERF_TESTS关掉能省不少时间测试代码量很大。BUILD_opencv_apps是那些opencv_annotation之类的命令行工具学习阶段用不到。7.2 问题速查表现象可能原因解决cmake找不到xfeatures2dcontrib路径错或版本不匹配确认OPENCV_EXTRA_MODULES_PATH指向contrib/modules分支都是3.4.16make报CODEC_FLAG错误FFmpeg版本新加-D WITH_FFMPEGOFF重新cmake运行报so找不到ldconfig没跑或LD_LIBRARY_PATH没设sudo ldconfig设环境变量Python导入的是4.2模块搜索路径优先系统路径手动sys.path.insert或设PYTHONPATH编译SLAM代码报CV_LOAD_IMAGE未定义头文件被OpenCV4覆盖确认CMakeLists里OpenCV_DIR指向/usr/localmake -j太多核卡死内存不足减少核数如-j47.3 关于是否值得升级到OpenCV 4的思考有人会问既然OpenCV 4更新为什么不直接用4对SLAM十四讲来说书里的代码是基于3.x写的4.x里很多API变了比如cv::xfeatures2d::SIFT在4.x里移到了主仓库的cv::SIFTCV_LOAD_IMAGE_COLOR被cv::IMREAD_COLOR取代。如果你把书里所有代码都改一遍适配4.x当然可以但那不是学习SLAM的重点改API的时间不如用来理解算法。所以对跟着书学的人来说装3.4.16是性价比最高的选择。等你把SLAM原理搞懂了再迁移到4.x就是顺手的事。8. 我实际踩过的两个坑和最终建议第一个坑是ENABLE_PRECOMPILED_HEADERS。第一次编译时没关这个选项make到30%左右报了一堆internal compiler error看起来像gcc崩溃。查了半天才发现是预编译头和gcc 9的兼容问题。关掉之后一次过。这个坑的隐蔽性在于报错信息完全不提预编译头容易往代码方向查。第二个坑是Python绑定的numpy路径。Ubuntu 20.04的numpy装在/usr/lib/python3/dist-packages/numpy但cmake默认可能去找/usr/local/lib/python3.8/site-packages/numpy找不到就静默跳过Python绑定cmake输出里Python那栏显示NO但不报错。等你编译完想import cv2才发现没有。所以cmake完一定要回头看Python那几行是不是都找到了。最后给一个建议整个编译过程最好在tmux或screen里跑因为编译要二三十分钟万一SSH断了编译进程就没了。用tmux new -s opencv开个会话断了重连tmux attach -t opencv编译继续跑。这个习惯在编译任何大型库时都值得养成。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑