Win10下利用VS2017+CMake编译OpenCV4.5.1并集成contrib
简介围绕 Windows 10 环境下 OpenCV 4.5.1 与 contrib 模块的重新编译资源包面向需要在 Visual Studio 2017 上配置计算机视觉开发环境的开发者特别适合需要使用 SIFT、SURF 等扩展算法的项目。压缩包内共收录 992 个文件以四百多个 hpp 头文件、四百多个 exe 可执行程序、五十多个 h 头文件以及二十多个 xml 配置文件为主体同时附有 cmake 配置脚本、dll 动态链接库、lib 静态库及多种开源许可证说明整个压缩包约四十七点六五兆字节。文件结构完整对应 CMake 配置并编译生成的 OpenCV 库目录下载后可直接在 Visual Studio 2017 中设置包含目录和库目录使用免去手工源码编译的复杂流程。资源中的 OpenCVConfig.cmake 与 OpenCVModules.cmake 等脚本也能帮助确认模块启用状态、快速调整链接选项。目前已有四百八十七人学习下载是获得带 contrib 模块完整构建产物、快速搭建视觉开发环境的实用资料。1. 为什么要在 win10 上自己折腾 OpenCV4.5.1 重新编译OpenCV4.5.1 的官方预编译包只带核心模块SIFT、SURF、脸部识别、文本检测这些常用算法全被挪进了 contrib 仓库而预编译包里默认是不包含的。很多做视觉的同行拿到预编译包跑起来才发现cv2.xfeatures2d直接报错找不到模块这时候唯一的出路就是自己把 opencv4.5.1 和 opencv4.5.1-contrib 放在一起用 CMake 重新生成工程、再用 VS2017 编译一遍。这篇笔记按我实际折腾过的流程写覆盖 cmake 配置、VS2017 编译、INSTALL 安装和典型报错排查适合第一次自己编 OpenCV 或者之前编失败过的人照着走一遍。2. 编译前的环境对齐VS2017、CMake、Python 的版本匹配2.1 为什么必须用 VS2017 而不是新版 VSOpenCV4.5.1 的 CMake 工程对编译器版本有要求VS2019 和 VS2022 虽然也能编但会遇到两个麻烦一是 CMake 检测编译器时可能把 Windows SDK 版本选到不兼容的版本二是 contrib 里部分模块比如 xfeatures2d 依赖的某些头文件在新编译器下会触发更严格的警告被当成错误。VS2017 的 v141 工具集是官方文档里明确验证过的我一般会直接装 VS2017 社区版安装时勾选「使用 C 的桌面开发」工作负载就够了。如果你机器上已经装了 VS2019也可以不改但 CMake 生成工程时要手动指定-G Visual Studio 15 2017 Win64这个生成器参数让 CMake 强制用 VS2017 的工具集。还有一个容易忽略的点VS2017 的安装路径里如果带了中文或空格CMake 解析编译器路径时偶尔会出问题。我建议统一装到C:\Program Files (x86)\Microsoft Visual Studio\2017\Community省得后面排查路径引用错误。2.2 CMake 版本选择与环境变量OpenCV4.5.1 需要 CMake 3.5 以上但实测 3.16 以后版本生成的工程文件在 VS2017 下更稳定。CMake 官网下载 Windows 版本的安装包安装时记得勾选「Add CMake to the system PATH for all users」这样命令行里能直接用cmake --version验证。装完之后打开一个命令行窗口跑一下cmake --version正常会输出类似cmake version 3.22.1的信息。如果提示找不到命令说明 PATH 没生效重开命令行或者手动把C:\Program Files\CMake\bin加到系统 PATH 里。这里有个小技巧cmake-gui 我也会一起用因为后面配置 OpenCV 的选项时图形界面比命令行改参数直观得多。2.3 Python 环境对齐决定能否生成cv2.pyd如果你打算在 Python 里用编出来的 OpenCV必须在 CMake 配置前就把 Python 装好。OpenCV 的 CMake 脚本会去检测系统里的 Python 解释器和 NumPy检测到才会生成cv2.pyd和 Python 的cv2包。我用的 Python 是 3.7 的 64 位版本和 VS2017 编译的 64 位库正好匹配。注意三件事Python 位数必须和编译目标一致x64装完 NumPy安装路径不要带中文。python --version pip show numpy第一行确认 Python 版本第二行确认 numpy 已装好。CMake 检测时如果找不到 numpy会跳过 Python 绑定模块编出来的 OpenCV 在 Python 里 import 会直接失败。2.4 源码目录规划不要把源码和构建目录混在一起OpenCV 官方推荐 out-of-source 构建就是源码目录和构建目录分开。我习惯的布局是D:\opencv\ opencv-4.5.1\ opencv_contrib-4.5.1\ build\源码放在opencv-4.5.1从 GitHub 下载的 release 源码解压后改名contrib 放在opencv_contrib-4.5.1build目录是空的专门放 CMake 生成的中间文件和最终产物。这样做的好处是想换配置时直接把 build 目录删掉重来源码保持干净。第一次编译的新手最常犯的错就是把 build 目录建在源码里最后源码目录一团乱出问题想重编都分不清哪些是原始文件。提示源码和构建目录的路径里都别带中文和空格CMake 对非 ASCII 路径的处理一直有坑。3. 用 CMake 配置 OpenCV4.5.1 contrib关键选项详解3.1 指定 OpenCV 源码目录与 contrib 模块路径打开 cmake-gui第一件事就是在「Where is the source code」里填D:/opencv/opencv-4.5.1在「Where to build the binaries」里填D:/opencv/build。填完点 Configure第一次会弹窗让你选生成器这里选「Visual Studio 15 2017 Win64」——注意是 Win64不是不带后缀的版本否则默认生成 32 位工程后面一堆坑。平台选 x64编译器用默认的 v141。Configure 跑完会输出一大段检测报告先确认几行关键信息Python 3: YES Interpreter: D:/python37/python.exe Libraries: D:/python37/libs/python37.lib numpy: D:/python37/Lib/site-packages/numpy packages path: D:/python37/Lib/site-packages如果 Python 那一列显示 NO回去检查 Python 是不是 64 位、numpy 是否装了、路径是否带中文。这些都对还检测不到把 CMake 缓存删了重新 Configure 一次。3.2 打开 contrib 模块OPENCV_EXTRA_MODULES_PATH首次 Configure 完成后搜索OPENCV_EXTRA_MODULES_PATH把D:/opencv/opencv_contrib-4.5.1/modules填进去。注意一定是 modules 子目录不是 contrib 根目录。填完再次 ConfigureCMake 会读取 contrib 每个模块的 CMakeLists把可编的模块列进 BUILD_LIST。这时你可以搜索BUILD_opencv_xfeatures2d如果显示复选框且能勾选说明 contrib 路径识别成功。contrib 里有些模块依赖第三方库比如text模块依赖 Tesseractxfeatures2d的某些算法依赖 boost。默认情况下这些模块会因为找不到依赖而被自动跳过不影响整体编译。我一般只保留常用的几个xfeatures2d、face、text如果装了 Tesseract、aruco、optflow。不需要的模块可以在生成的BUILD_opencv_xxx选项里关掉减少编译时间和磁盘占用。3.3 必调的编译选项BUILD_SHARED_LIBS、CMAKE_INSTALL_PREFIX、WITH_CUDA几个影响使用方式的选项BUILD_SHARED_LIBS勾选时生成 DLL 动态库不勾选生成静态库。我一般勾选因为动态库方便调试和替换版本而且 release 和 debug 的 DLL 可以同时存在。静态库虽然部署简单但 OpenCV 的静态库体积大、链接时间长新手遇到链接错误也更难排查。CMAKE_INSTALL_PREFIX默认是C:/opencv或者源码目录下的build/install我改成D:/opencv/install。INSTALL 步骤的产物都会装到这里后面配置开发环境就指着这个目录。WITH_CUDA如果你的显卡是 NVIDIA 的而且需要跑 DNN 模块的 GPU 加速第一次 Configure 后搜索 CUDA 相关选项并勾选。但注意 CUDA 工具包版本要和 VS2017 兼容CUDA 10.1 以上配 VS2017 是验证过的组合。没有 N 卡或者暂时不需要 GPU 加速保持不勾选省掉一大堆 CUDA 依赖的麻烦。3.4 生成 VS2017 工程第二次 Configure Generate所有选项都确认完再点一次 Configure等底部的日志区不再报红色错误。日志区如果有红色文字先排查再点 Generate。Generate 成功的标志是日志区出现Generating done此时D:/opencv/build目录下会出现OpenCV.sln解决方案文件。用 VS2017 打开这个文件就能看到 ALL_BUILD、INSTALL、opencv_world 等工程。我习惯在 Generate 之前把日志区滚动到最上面逐条扫一遍有没有WARNING级别的关键信息特别是OPENCV_EXTRA_MODULES_PATH是否真的被识别——有时候填错路径CMake 不会报错只是安静地不编译 contrib 模块这个最坑。4. 在 VS2017 里编译 OpenCV4.5.1从 ALL_BUILD 到 INSTALL4.1 切换 Release/Debug 配置与平台用 VS2017 打开OpenCV.sln先在工具栏把解决方案配置从 Debug 切成 Release平台从 Win32 切成 x64。千万别用 Debug 配置去编OpenCV 的 Debug 库运行速度差一个数量级而且很多坑是 Debug 特有的。Release 编出来的 DLL 调用 Debug 的测试程序可能报错Debug 编出来的库在 Release 程序里用也会出问题两个配置分开编译、分开安装。右键「ALL_BUILD」选择「生成」第一次编译大概要等 2040 分钟取决于 CPU 核心数。编完以后在输出窗口看到 生成: N 成功0 失败 说明编译通过了。如果失败先记下失败的工程名去第 5 章找对应的解决方案。4.2 只编需要的模块用 BUILD_LIST 控制编译范围如果不想等全部模块编译可以在 CMake 配置阶段搜索BUILD_LIST填上你需要的模块名逗号分隔例如BUILD_LISTcore,imgproc,imgcodecs,highgui,videoio,features2d,xfeatures2d,face这样生成的解决方案里只会包含这些模块的工程编译时间能缩短一半以上。注意core和imgproc是基础依赖无论如何都要留。xfeatures2d 依赖features2dface 依赖objdetect填了子模块忘了依赖模块时CMake 在生成阶段会报缺失依赖的错误按提示补上就行。4.3 常见的编译错误定位方法编译失败时VS2017 的输出窗口只会显示错误码比如C2065、LNK2019。我的排查顺序是先看错误发生在哪个工程每个 contrib 模块是一个独立工程比如opencv_xfeatures2d再双击错误信息跳到具体代码行最后去网上搜「工程名 错误码」。80% 的错误是缺少头文件路径或第三方库路径这些在 CMake 配置阶段解决比在 VS 里解决容易得多。所以编译报错时先回到 CMake 看日志比在 VS 里硬调代码有效。4.4 执行 INSTALL 得到干净的产物目录编译通过后右键「INSTALL」选「生成」。这个过程会把头文件、DLL、LIB 拷到CMAKE_INSTALL_PREFIX指定的目录我的是D:/opencv/install。INSTALL 完成后的目录结构长这样D:\opencv\install\ x64\vc15\bin\ # DLL 和 exe x64\vc15\lib\ # LIB 导入库 include\opencv2\ # 头文件注意 vc15 是 VS2017 的版本标识如果是 VS2019 会是 vc16。拿到这目录OpenCV 编译这步就算彻底完成了。后面配置 C 开发环境时头文件路径指到include库路径指到x64\vc15\libDLL 路径指到x64\vc15\bin。5. OpenCV4.5.1 编译避坑三个必踩雷区和排查清单5.1 C2065 未声明标识符contrib 模块的 Eigen 依赖缺失现象编译opencv_xfeatures2d时报大量C2065: Eigen 未声明的标识符。原因xfeatures2d 的部分算法头文件直接 include Eigen 库但 CMake 在配置阶段没有找到 Eigen只是默默绕过了相关源码导致编译阶段头文件里引用了不存在的类型。OpenCV 对可选第三方库经常是「检测不到就跳过」的策略不会主动报错。解决先从 Eigen 官网下载最新版解压到D:/opencv/eigen。回到 CMake搜索EIGEN_INCLUDE_PATH填D:/opencv/eigen重新 Configure 和 Generate再回 VS 编译。注意 Eigen 是纯头文件库不需要编译配置路径后就能用。我在第一次编译时忽略了 Eigen 警告结果在 xfeatures2d 上卡了一整天这个依赖很关键。5.2 LNK2019 无法解析的外部符号Debug 和 Release 库混用现象用编译产物写测试程序时链接报LNK2019 无法解析的外部符号 cv::imread之类。原因安装目录里同时存在 Debug 版和 Release 版的 LIB 文件一般在x64\vc15\lib下名字是opencv_world451d.libDebug带 d 后缀和opencv_world451.libRelease不带 d。程序用的是 Release 配置链接器却拿到了 Debug 版 lib或者反过来符号就解析不了。解决确认测试程序的配置和链接的 LIB 文件一致。Debug 程序链接opencv_world451d.libRelease 程序链接opencv_world451.lib。遇到此类错误时去链接器输入框检查 lib 文件名是不是带d。注意运行程序时 DLL 也要对应。Debug 程序会去找opencv_world451d.dllRelease 程序找opencv_world451.dll两个 DLL 在 bin 目录下都存在把 bin 目录加进系统 PATH 或复制到 exe 同目录即可。5.3 编译时内存不足导致 MSB6006 进程崩溃现象编译过程中 VS2017 报MSB6006: CL.exe 已退出代码为 2或者直接提示编译器进程被终止。原因OpenCV 的多个模块同时编译时内存占用非常夸张。xfeatures2d 和 dnn 模块的单文件编译能吃 2GB 以上内存如果机器只有 8GB 内存又开了很多程序编译器进程会被系统杀掉。解决在 VS2017 菜单里选「工具 → 选项 → 项目和解决方案 → VC 项目设置」把「构建并行项目数」从自动改成 1 或 2降低同时编译的项目数。这个选项也叫「Maximum concurrent C compilations」调成 2 能让内存占用减半代价是编译时间变长。我就是用 16GB 内存的机器跑并行编译翻车后才学乖的现在编 OpenCV 一律限成 2 个项目并行。5.4 排查清单一分钟定位 80% 的报错编译 OpenCV 的报错九成都集中在配置阶段。按这个顺序排查CMake 日志区有没有红色 ERROR有就先解决WARNING 记录一下后面编译出问题再回头看。OPENCV_EXTRA_MODULES_PATH是否指向 modules 目录。Python 检测是否 YESNumPy 是否识别。Eigen 路径是否配置如果BUILD_opencv_xfeatures2d是灰的或者编译报 Eigen 缺失。生成器是否选了Visual Studio 15 2017 Win64平台是不是 x64。编译时并行项目数是否过高。前三条在 cmake-gui 的日志区一眼能看完后三条需要点开具体的搜索项确认。这套流程下来我第二次在另一台机器上编译全程没踩坑第一次踩的所有雷全集中在这六个点上。6. 验证编译产物从 cv2.pyd 到 C 的 SIFT 调用编译和安装完成后最重要的环节是验证产物可用。先验证 Python 版本——找到D:/opencv/install/x64/vc15/bin下生成的cv2.pyd文件把它复制到 Python 的Lib\site-packages目录然后启动命令行import cv2 print(cv2.__version__) # 验证 contrib 模块是否编进来 sift cv2.SIFT_create() print(sift)输出4.5.1且没有报错说明 Python 绑定正常。如果import cv2报错ModuleNotFoundError检查是不是把cv2.pyd复制到了python.exe对应的 site-packages。如果报错依赖 DLL 找不到把bin目录加到系统 PATH。这里能顺手验证 contrib 有没有真的编进去——调用cv2.SIFT_create()是最快的判断方式因为它只在有 xfeatures2d 时才能用。C 侧验证更直接新建一个 VS2017 空项目在项目属性里配好 include 和 lib 路径链接器输入框填opencv_world451.lib写一段读图和显示图的代码#include opencv2/opencv.hpp #include iostream using namespace cv; int main() { Mat img imread(D:/test.jpg); if (img.empty()) { std::cerr 图片读取失败检查路径和 DLL std::endl; return -1; } // 用 SIFT 检测关键点验证 contrib 模块 PtrSIFT sift SIFT::create(); std::vectorKeyPoint kps; sift-detect(img, kps); std::cout 检测到关键点数量: kps.size() std::endl; return 0; }编辑器在imread和SIFT上方没有红线编译通过、程序输出关键点数量就说明整套环境没问题。SIFT::create()是 OpenCV4.4 之后的写法4.5.1 里已经不用xfeatures2d::SIFT那套了如果你看到的是旧教程里的写法记得年份问题——新版 API 更简洁。运行这个测试程序时把D:/opencv/install/x64/vc15/bin下的opencv_world451.dll复制到 exe 同目录或者直接用 PATH 指向 bin 目录。图像显示是黑盒验证的关键步骤——如果图像能弹出来说明 highgui 模块的 UI 依赖如 Windows 的 GDI都正常。最后想提醒的一点OpenCV 编译是一件「一次性折腾、长期受益」的事。把编译产物和源码目录都留着占空间大概 10GB 左右以后升级模块、切换配置都用得着。另外建议保留一份 CMake 配置的截图或者记录文件免得下次重装系统后不再想折腾第二遍。希望这些经验能让你少走几步弯路。本文还有配套的精品资源点击获取