ARTICLE DETAIL

资讯详情

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

Windows下用VS2017与CMake编译OpenCV 4.5.1:完整集成contrib与SIFT指南

Windows下用VS2017与CMake编译OpenCV 4.5.1:完整集成contrib与SIFT指南 简介OpenCV 4.5.1与contrib模块的完整Windows编译包面向需要借助Visual Studio 2017和CMake搭建计算机视觉开发环境的开发者提供可直接复用的库文件与配置结果。压缩包共992个文件约47.65MB核心内容包括454个hpp头文件、58个h头文件用于声明各类APIOpenCVConfig.cmake、OpenCVModules.cmake及配套的cmake配置方便在VS2017中一键引用3个dll和2个lib提供运行时与链接所需的动态/静态库另有大量可执行工具、xml模型、txt说明和setup_vars_opencv4.cmd脚本便于快速验证安装和设置环境变量。相比手动下载源码并用CMake长时编译这套资源省去了繁琐的contrib模块整合过程拿到后即可配置项目同时保留license等开源合规文件。包内contrib模块覆盖SIFT、SURF等经典特征检测算法并附带contrib专属头文件与少量示例代码如BEBLID.cpp适合中高级C开发者直接集成、调试计算机视觉应用。目前已有487人学习下载适合需要快速获取可用OpenCV contrib环境的中高级开发者。1. 为什么非得自己编译 OpenCV 4.5.1预编译包没有的 contrib、SIFT 和 CUDA在 win10 上第一次跑 SIFT 特征匹配我就被预编译版 OpenCV 治了一回官方 4.5.1 release 包装完头文件里根本没有 xfeatures2dSIFT::create() 直接报符号找不到。原因很简单——SIFT、SURF 这些非自由特征算法和大量前沿模块都在 OpenCV contrib 仓库里预编译包默认不带。用 vs2017 cmake 重新编译 OpenCV 4.5.1把 contrib 编进去这件事看起来像折腾其实是给后续开发买保险模块齐、位宽对、环境可控。这是一次完整重编译的记录适合在 Windows 上做计算机视觉、又需要 SIFT 或 aruco 等 contrib 模块的人按步骤复现。预编译包能凑合用的日子止步于你第一次写出#include opencv2/xfeatures2d.hpp的那一刻。2. 源码准备与版本对齐clone 两个仓库之前先处理好的三个前置项2.1 版本对齐OpenCV 与 contrib 必须同 tag很多第一次编译的人上来就 clone 两个仓库结果 Configure 也过了编译到一半就翻车报错大多指向某个头文件找不到或符号冲突。真正的坑往往不是编译过程而是版本没对齐。OpenCV 主仓和 opencv_contrib 是独立仓库但每个 release 都有对应的 tag主仓 4.5.1contrib 也要落在 4.5.1。如果你拿主仓的 4.5.1 去配 contrib 的 masterxfeatures2d 这类模块的接口很早就变了C 符号对不上编译器根本过不去。我一般这么拉源码# 拉取主仓和 contrib 仓库 git clone https://github.com/opencv/opencv.git git clone https://github.com/opencv/opencv_contrib.git cd opencv git checkout 4.5.1 # 主仓切到 4.5.1 tag cd ../opencv_contrib git checkout 4.5.1 # contrib 同步切到 4.5.1不能留在 master这里git checkout 4.5.1是关键两个仓库必须处于同一个发布点。如果网络条件一般可以在 clone 时加--depth 1 --branch 4.5.1只拉单分支能省不少时间对编译没有影响。拉完后用git tag | grep 4.5确认 tag 存在再git describe看一眼当前指针别等到编译报错了才回头查版本。版本不对齐的另一个隐藏问题是 ABI 兼容。contrib 里的 xfeatures2d 在 4.x 中期改过描述子接口compute和detectAndCompute的签名有过调整一旦你主仓用的是 4.5.1、contrib 用的是滚动版那些接口声明对不上编出来的库可能在运行时直接崩。与其后面追着报错改不如一开始就把 tag 定格。拉完代码先别急着打开 CMake在opencv_contrib目录里执行git log --oneline -1看一眼提交确认真的是对应 4.5.1 发布的那一次这一步三十秒能省下后面半小时排错。2.2 目录与磁盘三个文件夹的容量账源码怎么放看起来是小事踩过坑才知道影响很大。我的习惯是在某个根目录建一个opencv_build里面并列放opencv和opencv_contrib两个源码目录再加两个输出目录build用来放 CMake 生成的中间文件install用来放最终安装产物。mkdir opencv_build cd opencv_build mkdir build install这样手动删掉 build 重来的成本很低。磁盘空间要提前盘算源码约 1Gbuild 目录里装着所有中间 obj 和 lib全模块编译完能到 812Ginstall 再占 12G。如果机器上还留着别的编译缓存建议先腾 20G 出来避免编译到一半被磁盘写满那个翻车基本没有后悔药。另外一条硬性约定源码路径里不要有中文也别放在带空格的目录下。CMake 在 Windows 上对含中文的路径处理时好时坏vs2017 的某些工具链还会在资源文件路径上出编码错。路径越纯越好比如F:/opencv_build这是我踩过坑之后养成的习惯。一个常被忽略的点install 目录不要和 build 目录混在一起。有人图省事把CMAKE_INSTALL_PREFIX直接指到build/install结果每次重新编译前删 build 时把上个版本的库也删了出现「上次还能链接这次文件都没了」的诡异问题。把 install 独立出来重编译全程不碰它旧版本库还能继续用是给自己留的一条后悔药。2.3 环境检查与 CMake 版本VS2017 工作负载和生成器名动手前先把工具链确认一遍省得 Configure 一半才发现环境不对。Visual Studio 2017 要装 C 桌面开发工作负载只装主程序是不够的编译器、Windows SDK 和 MSBuild 都在这一个负载里。装的时候勾这一个就够别把整套全选上后面维护负担大。另一个容易误导的说法是找 vs2017 离线安装包去补装组件我实际试下来直接打开 VS Installer 勾负载比找离线包要稳官方安装器会自己处理依赖离线包反而经常缺这个缺那个。其次是 CMake 版本。OpenCV 4.5.1 要求 CMake 3.5.1 以上实际用 3.15 以上会比较舒服新版对 VS2017 生成器的支持更完整。cmd 里快速验证一下cmake --version cmake --help | findstr Visual Studio第一条看版本第二条用来确认当前 CMake 支持的 VS 生成器。生成器名称是Visual Studio 15 2017注意这里写 15 而不是 2017 的年份缩写。新版 CMake 推荐在命令行里用-A x64指定架构而不是在生成器名后面加Win64两套写法都能用命令行里统一用-A x64更不容易记混。还有一个容易忽略的检查项确认本机没有多个 Visual Studio 版本同时干扰。装了 VS2017 又装了 VS2019 的机器上CMake 默认选的是注册表里最新的如果不显式指定生成器最后编译出来的可能是 v142 工具链。这个问题在链接阶段才会暴露表现为一堆 LNK2038 运行时库版本不匹配。所以在命令行里显式写-G Visual Studio 15 2017不只是写给人看的也是给 CMake 划边界。配置阶段还会自动探测机器上的 Python、Java、Qt对纯 C 项目这三个可以在配置里关掉能省掉大量编译时间。3. CMake 配置与编译参数从 OPENCV_EXTRA_MODULES_PATH 到 Build 策略3.1 OPENCV_EXTRA_MODULES_PATH真正决定 contrib 启用的开关很多老教程说要在 CMake 里勾WITH_OPENCV_CONTRIB我在新版 CMake 配置界面里搜了好久都没找到这个选项——不是眼瞎是新版 OpenCV 根本不存在这个开关了。contrib 是否生效只取决于一个变量OPENCV_EXTRA_MODULES_PATH它的值是 opencv_contrib 仓库下的 modules 目录配置后 CMake 会自动扫描 modules 下每个子文件夹并加到构建列表里。如果用的 CMake GUI流程是这样Source填 opencv 源码目录Build填事先建好的 build 目录第一次点Configure弹出生成器选择框选Visual Studio 15 2017架构选 x64完成后再在变量列表里搜OPENCV_EXTRA_MODULES_PATH把它改成 contrib 的 modules 路径再点一次Configure。这一步之后的输出信息里会出现一长串以opencv_开头的模块名包括 xfeatures2d、aruco、dnn_superres、face 等这说明 contrib 已经进来了。命令行写法更直接后续重配也好复制# -S 指定源码目录-B 指定构建目录-G 指定生成器 cmake -S opencv -B build -G Visual Studio 15 2017 -A x64 ^ -DOPENCV_EXTRA_MODULES_PATHF:/opencv_build/opencv_contrib/modules ^ -DCMAKE_INSTALL_PREFIXF:/opencv_build/install ^ -DBUILD_opencv_worldON ^ # 合并成一个 world 库链接省事 -DBUILD_EXAMPLESOFF ^ -DBUILD_TESTSOFF ^ -DBUILD_PERF_TESTSOFF ^ -DWITH_CUDAOFF参数说明CMAKE_INSTALL_PREFIX决定最终库装到哪里后面配 VS 工程和 CMake find_package 都靠它BUILD_opencv_worldON把几百个模块合并成一个 opencv_world451 库项目里链接配置从十几条变成一条建议常开BUILD_EXAMPLES、BUILD_TESTS、BUILD_PERF_TESTS全部 OFF能砍掉一大半编译量对生产库没有影响。-A x64指定 64 位如果写-A Win32出来的库是 32 位后面链接时容易踩坑。一个常见误用是把OPENCV_EXTRA_MODULES_PATH填成 opencv_contrib 的仓库根目录比如F:/opencv_build/opencv_contrib。CMake 不会报错但扫描 modules 时找不到任何子模块于是整个 contrib 静默失效。最坑的是这种失效没有明显提示你会在编译后才发现 SIFT 还是不存在。判断方法很简单Configure 完成后立即看日志里的opencv_contrib_modules列表里面有几十个模块名字才对没有就说明路径填错了。确认之后建议把BUILD_opencv_python3和BUILD_opencv_java都关掉纯 C 用户用不上还能再砍掉一些编译时间。3.2 功能开关取舍CUDA、TBB、Eigen 用不用编译 OpenCV 最大的自由度在开关组合上这里给一张我常用的取舍表按「纯 CPU 默认方案」和「要加速的增强方案」两档说明选项默认值我的建议影响WITH_CUDAOFF有 NVIDIA 显卡且装好 CUDA Toolkit 再开开启后要填 CUDA_ARCH_BIN填错编译直接报错WITH_TBBOFF纯 CPU 建议开并行加速但要额外下载 TBB 源码WITH_EIGENOFF建议 ON部分 contrib 模块的数学库依赖不装也能编但性能差点WITH_OPENMPOFF也可以开老牌并行方案VS2017 里配置简单BUILD_opencv_worldOFF建议 ON否则会有几十个 lib项目链接配置繁琐BUILD_SHARED_LIBSON保持默认生成 dll调试时替换单文件方便注意 CUDA 不是想开就开。机器上没有装 CUDA Toolkit 就直接WITH_CUDAONConfigure 那一步就会报找不到 CUDA日志会停在 nvcc 相关的检查上。就算装好了还要填CUDA_ARCH_BIN代表显卡的计算能力比如 GTX 1660 是 7.5。如果不填新版本 CMake 会尝试自动探测偶尔会探测失败日志里出现Unsupported gpu architecture就表示要手动填了。TBB 和 OpenMP 是两条路TBB 是 Intel 的线程库对多核 CPU 的算子并行效果好但需要额外下载源码OpenMP 是编译器内置支持VS2017 里勾一个开关就行。我的经验是如果只是做常规图像处理和特征提取这两个不开影响也不大OpenCV 自带的多线程优化已经够用如果是跑大分辨率图像或批量处理再回来开 TBB 值得。开关改完后记得重新 Configure 而不是直接 Generate——CMake 只有在 Configure 阶段才会重新检测新依赖。很多人改了 WITH_CUDA 直接点 Generate日志没报错但编译时找不到 cuda_runtime.h白白浪费一次全量编译。Configure 时留意窗口左下角有没有红色的 error输出末尾几行通常会给出明确的失败原因顺着那个去改参数比反复试要快。3.3 Generate 与编译ALL_BUILD 和 INSTALL 的先后顺序Configure 全部通过后点Generatebuild 目录里会出现OpenCV.sln。打开它默认会有几十个项目别直接按 F7 盲编译——正确顺序是先编ALL_BUILD再编INSTALL。ALL_BUILD 会把所有模块编译成库INSTALL 才把这些库、头文件、cmake 配置文件按CMAKE_INSTALL_PREFIX复制到 install 目录。只编 ALL_BUILD 不编 INSTALLinstall 目录永远是空的外部项目根本引用不到。VS 界面里操作是右键ALL_BUILD→ 重新生成先 Release 编译一遍再把配置切到 Debug 编译一遍最后分别右键INSTALL→ 生成。命令行方式我更喜欢因为可以在不打开 IDE 的情况下跑# 先编 Release 的 ALL_BUILD 和 INSTALL cmake --build build --config Release --target ALL_BUILD -- /m:16 cmake --build build --config Release --target INSTALL # 再编 Debug 版本两条不能省 cmake --build build --config Debug --target ALL_BUILD -- /m:16 cmake --build build --config Debug --target INSTALL-- /m:16是传给 MSBuild 的并行编译参数16 表示 16 个进程同时编具体数字按 CPU 逻辑核心数填8 核机器填 8 就行。注意到我把 Debug 也编了一遍——Debug 和 Release 生成的库文件名差一个d后缀opencv_world451.lib对应 Releaseopencv_world451d.lib对应 Debug两者互不覆盖必须各编各的。第一次全量编译的时间跨度很大只编 Release 的话在一小时到两小时之间如果有 CUDA 会再久一些。编到中途报错不要慌张先看是哪个项目失败再用后面避坑清单对号入座。提示每次重编译时如果换了分支或改了 cmake 选项建议先清空 build 目录里的 CMakeCache.txt 再 Configure避免旧配置残留影响判断。3.4 install 目录里应该长什么样从 LICENSE 到 OpenCVConfig.cmake编译安装完成后install 目录应该有四个核心子结构include/opencv2下是全部头文件x64/vc15/bin下是 DLLx64/vc15/lib下是 libshare/OpenCV下是一堆 CMake 配置文件。share/OpenCV里那几个文件特别关键OpenCVConfig.cmake、OpenCVConfig-version.cmake是外部项目用find_package(OpenCV)时读取的入口OpenCVModules.cmake和OpenCVModules-debug.cmake记录每个模块的实际路径setup_vars_opencv4.cmd是个批处理脚本运行一次就把 bin 目录加进当前终端会话的 PATH。后面如果写 CMake 工程OpenCV_DIR直接指向install/share/OpenCV就能被顺利找到。编译时带出来的ade-LICENSE、ittnotify-LICENSE.BSD在etc/licenses下是第三方组件 ade 和 Intel ittnotify 的版权声明。而源码里的BEBLID.cpp是 contrib 中 xfeatures2d 模块的一个源文件——BEBLID 是 2020 年后加入的高性能二值描述子它在源码里和 SURF、SIFT 并列编译完会进opencv_xfeatures2d模块。看到这些文件基本可以确认 install 结构是完整的外部项目可以开始配置了。4. 避坑指南重编译 OpenCV 最常翻车的五个地方重编译 OpenCV 的报错有个特点信息五花八门根因就那么几个。下面五条是我在不同机器上反复踩过的坑每一条按「现象 → 原因 → 解决」写清楚方便你对号入座。4.1 Configure 卡在下载 ippicv日志停在 fetch 相关行现象第一次 Configure 时界面长时间不动或者日志最后几行停在ippicv、face_landmark_model相关的下载提示等待很久后直接报错退出报错形式类似cmake error at .../ippicv.cmake。原因OpenCV 在配置阶段会从外部下载第三方组件其中 ippicv 体积很大网络波动时下载超时而 CMake 的错误信息很含糊容易被误当成配置参数错误。这些下载动作发生在 Configure 阶段跟你的编译器配置没有任何关系。解决手动把报错里提到的文件下载到本地缓存目录。缓存目录一般在F:/opencv_build/.cache/opencv4和 build 目录平级CMake 会优先读这里的文件。把下载好的压缩包按 CMake 提示的文件名放进去再重新 ConfigureCMake 就会直接用缓存不再到外网拉取。4.2 编译 xfeatures2d 报 fatal error找不到 boostdesc_bgm.i 或 vgg_generated_48.i现象编译到 opencv_xfeatures2d 这个项目时报错类似fatal error C1083: 无法打开文件 boostdesc_bgm.i有时候一串好几个文件一起报缺。原因contrib 仓库里有一部分特征描述子训练数据文件没有直接提交到 Git编译时需要单独下载。这属于非自由数据的许可限制问题不是编译参数配错也不是源码路径问题。常见缺失文件包括boostdesc_bgm.i、vgg_generated_48.i等十几个。解决根据报错列出的文件名把所有缺失的boostdesc_*.i和vgg_generated_*.i手动下载后放进opencv_contrib/modules/xfeatures2d/src/目录然后重新 Configure 再编译。一次放齐后面不会再报同类错误。4.3 按老教程找 WITH_OPENCV_CONTRIB发现 CMake 里根本没有这个选项现象网上不少教程说「勾选 WITH_OPENCV_CONTRIB 以包含 contrib 模块」但在 4.5.1 的 CMake 配置界面里搜不到这个变量配置过程也没有任何地方让你确认 contrib 是否加载。原因新版 OpenCV 取消了独立的 contrib 开关只通过OPENCV_EXTRA_MODULES_PATH自动识别。很多参考资料停留在旧版写法上早期版本确实有这个开关后来被路径识别取代了。解决不要依赖开关名改用路径判断——确认OPENCV_EXTRA_MODULES_PATH指向的是opencv_contrib/modules而不是仓库根目录。Configure 后立刻看编译日志一长串opencv_xfeatures2d、opencv_aruco出现就说明加载成功。4.4 Release 包正常Debug 工程链接 opencv_world451d.lib 失败现象Release 编译、运行都没问题切到 Debug 后链接器报无法打开 opencv_world451d.lib有时还会伴随一串 LNK2019 未解析的外部符号。原因库目录下只有 Release 版 libDebug 版带d后缀的库没生成。VS 里 Debug 和 Release 是两套独立输出互不覆盖不各自编一遍就没有对方的产物。解决把 Debug 和 Release 分别跑一遍ALL_BUILD和INSTALL确保 install/lib 下同时存在opencv_world451.lib和opencv_world451d.lib。延伸一个相关坑即便 Debug 的库生成了工程里附加依赖项写的却是opencv_world451.lib而不是opencv_world451d.lib链接器同样会报错。反过来 Release 工程写了带d的也一样——VS 工程属性里 Debug 和 Release 各自维护一份附加依赖项别图省事只填一个。4.5 程序运行时提示找不到 opencv_world451.dll现象编译链接全通过双击 exe 或启动调试时系统提示找不到opencv_world451.dll程序直接退出。原因DLL 不在运行目录也不在系统 PATH 中。install 目录里的 bin 路径没有被全局加入环境变量或者 VS 调试器启动时使用的 PATH 里没有该目录。解决最简单的方式是每次开发前运行install/setup_vars_opencv4.cmd它会自动把x64/vc15/bin追加到当前终端会话的 PATH。也可以在 Windows 系统环境变量里永久加这一项。确认平台别搞错64 位程序配的是x64/vc15/bin不是 x86 目录。如果用的是 VS Code 的 cmake 插件做远程开发环境变量作用域又不一样可以在.vscode/settings.json里补cmake.environment相关的 PATH 配置本地开发机还是直接配系统 PATH 最省心。提示setup_vars_opencv4.cmd 只在当前 cmd 会话生效别指望运行一次永久改环境变量想做全局生效还是去系统属性里加。5. 验证与落地从 hello world 到环境变量的最后一个坑5.1 最小验证程序SIFT 建不出来就是白编了编译完心里最没底的是「到底有没有成功」。我的做法是写一个 30 行的冒烟测试专门验证两件事contrib 真的被编进去了、链接器能找到完整的库。工程文件用 CMake 最省事因为 install 目录里已经有 OpenCVConfig.cmake 了。cmake_minimum_required(VERSION 3.15) project(opencv_smoke_test) find_package(OpenCV REQUIRED) add_executable(smoke smoke.cpp) target_link_libraries(smoke ${OpenCV_LIBS})#include opencv2/opencv.hpp #include opencv2/xfeatures2d.hpp #include iostream int main() { auto sift cv::xfeatures2d::SIFT::create(); if (!sift) { std::cerr SIFT create failed std::endl; return 1; } cv::Mat img cv::imread(test.jpg); std::vectorcv::KeyPoint kps; sift-detect(img, kps); std::cout keypoints: kps.size() std::endl; return 0; }config 阶段要手动指定 OpenCV_DIR 指向 install/share/OpenCVcmake -DOpenCV_DIRF:/opencv_build/install/share/OpenCV ..。这段验证代码的逻辑是先创建 SIFT 实例这一步失败说明 xfeatures2d 没编进来再读一张测试图做检测输出 keypoint 数量。能输出一个非零数字整个编译链路就通了。5.2 环境变量和项目属性最后一次配置到底改哪里如果不想用 CMake 而是直接在 VS 工程里引需要改三个地方。VC 目录里包含目录加install/include库目录加install/x64/vc15/lib链接器输入里加opencv_world451.lib运行前确认 PATH 里有install/x64/vc15/bin。三个都改对才算配好漏任何一环都会被一个 LNK 或启动报错弹回来。我一般会在开发机的系统环境变量里永久加上 bin 路径然后每次新开项目只需要改前两个。最后分享一个更稳的验证方式开一个 cmd先执行install/setup_vars_opencv4.cmd再在同一窗口里运行冒烟测试生成的 exe。这样做的好处是连 PATH 是否正确都顺带验证了能跑通就是全链路无死角。我最初只编了 Release结果调试程序时被那一堆 opencv_world451d.lib 的 LNK2019 折腾了半个下午。从那以后每次重编译我的习惯固定下来先 Debug 和 Release 各 INSTALL 一遍再跑冒烟测试最后才开真正的业务工程。顺序看着不起眼但能替你过滤掉一多半后续翻车。希望帮到你。本文还有配套的精品资源点击获取
返回列表