Linux下OpenCV 4.2与contrib源码编译:缺失文件修复与自定义Tracker
简介面向在Linux环境下进行计算机视觉开发的工程师和研究者该资源打包了OpenCV 4.2主库及其扩展模块opencv_contrib。针对官网版本在Linux编译时频发的头文件缺失、依赖文件不完整等问题资源已提前修正相关配置可直接构建通过省去手工排查的繁琐过程。压缩包共8752个文件大小146.06MB涵盖源码、头文件、构建脚本、测试图片与模型数据具体包括cpp/py示例、hpp/h头文件、cmake脚本、Java与C封装、OpenCV Engine接口定义、Tracker扩展教程、跨平台工程文件等为源码分析、二次开发和算法验证提供充足素材。包内附带的官方文档、标记数据与多平台配置也可作为OpenCV学习的目录式参考基线。已有493人学习下载适合需要稳定编译环境、快速上手OpenCV 4.2扩展能力的开发者。1. opencv4.2 与扩展库 opencv_contrib 的编译困境如果你在 Linux 下从源码编译 OpenCV并把 opencv_contrib 4.2 目录指给 CMake大概率会在编译中段撞上“找不到头文件”或“缺少某些源文件”的错误。我最初也被这类问题卡住官方仓库在 4.2 分支上并没有完全同步 contrib 的所有改动导致 Linux 下直接编译时xfeatures2d、tracking、freetype 等扩展模块会有文件缺失的情况。这里分享的 opencv4.2 资源是经过修改的版本补上了缺失文件并且把 opencv_contrib 一并整理好在 Linux 下可以完整编译通过。适合需要自定义 contrib 模块做视觉开发的工程师也适合运维同学在离线环境交付“源码补丁”这类部署场景。2. 为什么 opencv_contrib 在 Linux 下会缺文件编译模型与版本对齐2.1 OpenCV 的模块边界main 和 contrib 如何一起编译OpenCV 的主仓库把 core、imgproc、video、objdetect 等基础模块放在modules/目录下而扩展模块放在独立的opencv_contrib/modules/目录下。编译时主仓库的 CMake 并不会自动搜索 contrib必须通过OPENCV_EXTRA_MODULES_PATH这个变量把 contrib 的 modules 路径交给 OpenCV 的主构建系统。这个机制本身并不复杂复杂的是两个仓库在同一个版本标签上的时间点不一定完全一致。在 opencv4.2 这个版本上官方 contrib 里有些模块会引用主仓库尚未同步过来的头文件或者是 contrib 内部不同模块之间互相引用时头文件路径写的是opencv2/xxx.hpp但该文件恰恰没有跟随源码包一起发布。这些情况在 Windows 上可能不明显因为预编译包帮你绕过了源码编译在 Linux 上使用源码安装时所有依赖都靠 CMake 现场展开文件缺失问题就会直接暴露。另一个常见的误导是直接使用 GitHub 上最新 master 分支的 contrib 与 4.2 主仓库搭配。master 分支是给最新版 OpenCV 准备的里面可能调用了 4.2 中不存在的 API。此资源把 opencv4.2 与配套的 opencv_contrib 统一整理过版本偏差导致的头文件缺失规划是重点处理范围。2.2 官方 4.2 版本贡献中缺失的典型报错下表是官方 4.2 contrib 在 Linux 下最常出现的几类问题你在用官方源码编译时可以直接对比日志判断原因。报错关键字出现原因常见影响模块opencv2/xfeatures2d.hpp: No such file主仓库 include 目录未生成或未包含该头文件xfeatures2dboostdesc_bgm.i: No such filecontrib 中训练数据文件缺失boostdescvgg_generated_48.i: No such file部分检测器需要的外部描述子文件缺失vgg featurestracking.hpp: No such filetracking 模块头文件引用路径不对trackingOPENCV_OPENCL_RUNTIME not definedOpenCL 运行时相关头文件不一致core、videoio官方源码编译时上述问题通常不会一次性全出而是先报第一个错你手动从网上找来对应文件放到源码树里再编译又会报第二个错。这种循环很消耗时间特别是云服务器上没有图形界面、无法直接访问 GitHub 时更麻烦。2.3 补齐文件链路的两种改法改 CMakeLists 还是补头文件我一般会优先用“补头文件”的方式解决因为它对原结构侵入最小。做法是从 opencv_contrib 的当前 master 或者相邻版本的模块目录中找到同名头文件复制到编译失败的模块的include/opencv2/路径下。例如 xfeatures2d 这个模块需要检查opencv_contrib/modules/xfeatures2d/include/opencv2/xfeatures2d.hpp是否存在如果存在说明问题出在 CMake 没有找到该目录那么就可以在xfeatures2d/CMakeLists.txt里补充 include 路径。也有小概率是头文件真的不在源码包里需要用 git 从官方仓库对应提交中恢复。这个资源的做法就是把这类文件直接在源码包里补齐并同步修正了 contrib 下多个CMakeLists.txt中遗漏的安装路径配置。这样做的直接收益是编译流程不再是“报错-搜文件-放置-重编”而是可以一直跑到make install结束。下面是一段可以作为参考的临时补丁写法适用于多数 contrib 模块在CMakeLists.txt的ocv_glob_modules或 include 配置处显式指定头文件目录。# 在 opencv_contrib/modules/tracking/CMakeLists.txt 中追加 set(TRACKING_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/src ) target_include_directories(${OPENCV_MODULE} PUBLIC ${TRACKING_INCLUDE_DIRS})这段 CMake 配置的作用是把当前模块源码目录下的include路径交给编译系统确保#include opencv2/tracking.hpp这类写法能够正确定位到头文件。OPENCV_MODULE是 OpenCV 内部定义的变量指向当前正在构建的模块目标。3. Linux 下 opencv4.2 opencv_contrib 源码编译的可执行步骤3.1 依赖安装编译前先解决系统库OpenCV 4.2 对系统库有最低要求Ubuntu 18.04 之后的版本基本都能满足。以下是我常用的依赖清单适用于 Ubuntu/Debian 系 Linux 发行版本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 libv4l-dev sudo apt-get install -y libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev sudo apt-get install -y libopenblas-dev libatlas-base-dev sudo apt-get install -y python3-dev python3-numpylibgtk-3-dev是 GUI 和imshow必须的依赖libavcodec-dev、libavformat-dev、libswscale-dev属于视频解码链路不安装会导致VideoCapture打不开部分 MP4 文件libtbb-dev提供线程构建模块能提升运行速度python3-dev和python3-numpy用于生成 Python 绑定。如果你不需要 GUI 相关功能可以把-DWITH_GTKOFF加进 CMake 配置但这部分依赖仍然建议保留便于后续调试。3.2 CMake 配置参数与完整命令把源码解压后我通常建立一个独立的build目录避免污染源码目录。目录结构如下opencv4.2/ ├── modules/ ├── opencv_contrib/ │ └── modules/ └── build/进入build目录执行 CMake 配置。下面是我基于这个资源编译时使用的命令可以直接复制调整cd opencv4.2/build cmake -D CMAKE_BUILD_TYPERELEASE \ -D CMAKE_INSTALL_PREFIX/usr/local \ -D OPENCV_EXTRA_MODULES_PATH../opencv_contrib/modules \ -D WITH_TBBON \ -D WITH_OPENMPON \ -D WITH_GTKON \ -D WITH_V4LON \ -D WITH_FFMPEGON \ -D BUILD_opencv_python3ON \ -D BUILD_NEW_PYTHON_SUPPORTON \ -D BUILD_opencv_worldOFF \ -D INSTALL_C_EXAMPLESOFF \ -D INSTALL_PYTHON_EXAMPLESOFF ..这里的OPENCV_EXTRA_MODULES_PATH是本次编译的核心参数它告诉主仓库去opencv_contrib/modules里读取扩展模块。BUILD_opencv_world如果开启会把所有模块编进同一个libopencv_world.so我一般关闭因为运维环境里单独链接某个.so更灵活如果希望部署包体积小、只有一个库则可以把BUILD_opencv_world打开。CMake 配置完成后终端会列出即将编译的模块清单。务必检查清单是否包含xfeatures2d、tracking、text、dnn等扩展模块如果只有主模块说明OPENCV_EXTRA_MODULES_PATH没有生效。3.3 make 编译和 install 后的模块核对配置完成后开始编译。OpenCV 的编译时间与机器 CPU 核心数强相关我通常先看核数再用nproc获取结果传给makemake -j$(nproc)nproc来自 coreutils返回当前可用 CPU 线程数。-j后面的数字越大编译越快但内存也会随之升高。一个比较保守的做法是根据内存大小来限制并行度8GB 内存的机器用make -j416GB 以上再考虑全核并行。如果在编译中段出现internal compiler error或Killed大多是内存被耗尽降低-j参数即可。编译完成后执行安装sudo make install sudo ldconfig安装结束后可以用pkg-config验证编译是否成功pkg-config --modversion opencv4如果输出4.2.0说明主库没有明显问题。再检查 contrib 模块是否齐全可以看安装目录下的.so文件ls /usr/local/lib/libopencv_*.so | grep -E tracking|xfeatures2d看到libopencv_tracking.so和libopencv_xfeatures2d.so说明扩展模块已编译进来。3.4 头文件找不到的具体修法以 xfeatures2d 为例官方源码最典型的错误是编译到opencv_contrib/modules/xfeatures2d时提示fatal error: boostdesc_bgm.i: No such file or directory这类.i文件其实是训练好的特征描述子不属于标准 C/C 头文件但编译阶段需要被包含。官方 4.2 的源码包因为文件列表不完整导致部分资源没有下拉。该资源的修改方式是把缺失的.i文件放回opencv_contrib/modules/xfeatures2d/src/目录同时把多余的旧版本.i文件清理掉。如果你拿到的是原始官方源码可以用下面的方式从已修复的源码包中直接复制对应文件然后重跑编译cp opencv4.2/opencv_contrib/modules/xfeatures2d/src/boostdesc_bgm.i \ opencv4.2/opencv_contrib/modules/xfeatures2d/src/ cp opencv4.2/opencv_contrib/modules/xfeatures2d/src/vgg_generated_48.i \ opencv4.2/opencv_contrib/modules/xfeatures2d/src/复制后不需要重新执行 cmake只要再次执行make -j$(nproc)即可继续之前的编译进度。如果错误提示的是opencv2/xfeatures2d.hpp找不到则需要检查编译单元是否能够访问到该头文件路径方法是对应模块的CMakeLists.txt中加入如下路径include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)修改 CMake 文件后必须重新执行 cmake 配置因为include_directories是在配置阶段写入构建规则的。重新配置后增删文件引起的编译错误大多数会消失。4. 在 opencv4.2 基础上添加自定义 Tracker 方法4.1 Tracker 模块的接口要求与最小编译单元opencv_contrib 里的 tracking 模块提供了视频目标跟踪的基础接口核心类是cv::Tracker。OpenCV 4.2 的目标跟踪框架要求自定义跟踪器继承cv::Tracker并实现initImpl和updateImpl两个纯虚函数。前者负责用第一帧图像和目标边界框初始化状态后者负责在后续帧中更新目标的位置。一个最简自定义跟踪器的骨架如下#include opencv2/core.hpp #include opencv2/tracking.hpp #include opencv2/imgproc.hpp using namespace cv; class MyTracker : public cv::Tracker { public: static PtrMyTracker create(); protected: bool initImpl(const Mat image, const Rect2d boundingBox) override { // 保存初始目标区域用于模板匹配 initialBox boundingBox; return true; } bool updateImpl(const Mat image, Rect2d boundingBox) override { // 这里用一个最简单的策略位置不变保持初始框 boundingBox initialBox; return true; } private: Rect2d initialBox; }; PtrMyTracker MyTracker::create() { return makePtrMyTracker(); }initImpl接收第一帧图像和初始目标框返回false表示初始化失败。updateImpl接收当前帧输出新的目标框返回false表示跟踪丢失。真实项目中updateImpl内部通常会计算直方图、光流或者深特征这里只做结构演示。这段代码可以直接编译成.so也可以直接放进独立的测试工程中调用。4.2 两个落地方案修改 contrib 与独立 .cpp第一种方式是把自定义 Tracker 的源文件直接放进opencv_contrib/modules/tracking/src目录然后在opencv_contrib/modules/tracking/include/opencv2/tracking.hpp中声明create工厂函数最终随整个 OpenCV 一起编译。优点是后续调用时直接通过Tracker::create(MyTracker)获取实例与其他内置 Tracker 一致。第二种方式是独立工程不碰 OpenCV 源码。对多数业务场景来说这种方案更干净。先编写独立文件再通过 CMake 链接到以安装的库。我这里用第二种方式演示CMake 文件写法如下cmake_minimum_required(VERSION 3.10) project(my_tracker_demo) find_package(OpenCV REQUIRED) add_executable(demo main.cpp my_tracker.cpp) target_link_libraries(demo ${OpenCV_LIBS})find_package(OpenCV REQUIRED)会搜索 OpenCVConfig.cmake设置OpenCV_INCLUDE_DIRS和OpenCV_LIBS。如果你将 OpenCV 安装到/usr/localcmake 会自动找到如果安装到自定义目录需要手动给CMAKE_PREFIX_PATH指向安装前缀。4.3 验证新跟踪器能否被 selectROI 调用为了保证自定义跟踪器能接进 OpenCV 的原生流程我会用selectROI手动框选目标再用自定义类跑一遍。下面这个例子可以验证初始化逻辑是否正确#include opencv2/highgui.hpp #include opencv2/tracking.hpp #include opencv2/videoio.hpp #include iostream using namespace cv; using namespace std; // 假设 MyTracker 已经单独声明 int main(int argc, char** argv) { VideoCapture cap(0); if (!cap.isOpened()) { cerr camera not opened endl; return 1; } Mat frame; cap.read(frame); Rect2d box selectROI(tracker, frame, true, false); PtrTracker tracker MyTracker::create(); tracker-init(frame, box); while (cap.read(frame)) { Rect2d updatedBox; bool ok tracker-update(frame, updatedBox); rectangle(frame, updatedBox, Scalar(0, 255, 0), 2); imshow(tracker, frame); if (waitKey(1) 27) break; } return 0; }这里tracker-init(frame, box)调用会对内置框架进行若干初始化检查包括目标框是否超出图像边界、图像通道数是否合法等。如果自定义类的initImpl中不做必要验证在线段中可能出现坐标突破图像范围的情况因此initImpl中至少限制一下boundingBox不能小于 0 或大于图像尺寸。实际业务中我一般把MyTracker::create()的声明放到opencv2/tracking.hpp的cv命名空间中这样在调用侧不需要暴露任何内部数据。5. 编译产物验证与离线环境部署细节编译完成后先用一个综合命令确认 OpenCV 和 contrib 的版本与模块完整度opencv_version --verboseopencv_version是安装时生成的工具默认路径在/usr/local/bin。执行后输出的内容应当包含版本号4.2.0并列出所有已编译的模块名称。检查其中是否有xfeatures2d、tracking、text这三个模块是官方 contrib 中较容易编译失败的。如果opencv_version --verbose输出不全还可以直接查看安装的 pkg-config 文件cat /usr/local/lib/pkgconfig/opencv4.pc这里的Libs:字段会列出 OpenCV 在编译时链接的所有库。若发现缺少opencv_tracking说明 tracking 模块没有被编入常见原因是OPENCV_EXTRA_MODULES_PATH路径写错或 CMake 阶段该模块被自动禁用。对于运维侧部署源码编译后的产物通常要复制到目标机器使用。需要注意保留/usr/local/lib下的 OpenCV 动态库并更新动态链接器缓存echo /usr/local/lib | sudo tee /etc/ld.so.conf.d/opencv4.2.conf sudo ldconfig这一条会避免运行时报错libopencv_core.so.4.2 not found。如果目标机器上没有编译器直接从编译机同步/usr/local/lib、/usr/local/include/opencv4和/usr/local/bin三个目录即可不需要重装整套源码。注意源机和目标机的 glibc 版本要接近否则动态库加载时仍可能出现符号找不到问题。如果你的项目之前在官方原版上无法编译现在替换成这个修复后的 opencv4.2 源码包建议把老项目的CMakeCache.txt删除重新配置避免 CMake 缓存了错误的头文件路径。执行下面对缓存清理的命令再重新走一遍 3.2 节中的 cmake 流程。rm -rf build/CMakeCache.txt最后当前资源中带有的README.android和多个Package.appxmanifest文件主要服务于 Android 与 Windows 平台的工程结构参考。Linux 场景下可以直接忽略它们不影响源码编译与后续的视觉应用开发。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联
返回资讯列表 →