简介:OpenCV 3.2.0配合Visual Studio 2015编译好的整合包,面向需要在VS2015环境中进行图像处理与计算机视觉项目开发的工程师、学生及研究人员。压缩包内共456个文件,核心组件包括280个hpp头文件、57个h头文件、42个dll动态运行库、41个lib链接库,以及cmake配置脚本和xml数据文件等,压缩后仅28.3MB,轻量且实用。目前已有496人学习下载,该版本专为VS2015用户优化,可直接集成至开发环境,省去大量环境配置时间。资源中特别整合了opencv_contrib-3.2.0扩展模块,涵盖aruco二维码识别、optflow光流估计、xfeatures2d特征检测等增强功能,并优化了VideoWriter编码支持,DNN模块支持TensorFlow与Caffe模型导入。使用时可省去手动下载源码、配置CMake及漫长编译的步骤,按需设置包含目录和库目录即可编译运行,帮助开发者将精力集中于算法实现与项目落地,适合需要快速搭建OpenCV开发环境的视觉领域实践者。
1. 为什么非要把 OpenCV 3.2.0 和 opencv_contrib-3.2.0 一起从源码编译
接手一个 2017 年左右的视觉项目,大概率会撞上这套组合:opencv3.2.0 + vs2015 + 需要包含 opencv_contrib-3.2.0 编译出的扩展模块。官方预编译包只带主仓库模块,xfeatures2d(SIFT/SURF)、face、text 全在 contrib 里,缺了它们,代码一编译就是 opencv2/xfeatures2d.hpp 找不到头文件。
于是只剩一条路:拿源码自己编。把 OpenCV 3.2.0 与 opencv_contrib-3.2.0 一起交给 CMake,生成 VS2015 的解决方案,编出带扩展模块的库。整个过程不复杂,但版本错一个、路径差一层,CMake 到 MSBuild 全链路都会跟着翻车。
下面按顺序走:前置工具链、CMake 配置、VS2015 命令行编译、产物验证,最后是 5 个高频踩坑和一段能跑通的 SIFT 测试代码。正卡在自编译这一步的话,按文中的参数来,会比对着零散教程拼快得多。
2. 编译 OpenCV 3.2.0 的前置条件:版本匹配与工具链选择
自编译不是双击安装包,动手前先理顺整条链:源码版本、CMake、Windows SDK、编译器 ABI。这个顺序选反了,后面 CMake 配置阶段会反复报错,而报错信息多半不直接告诉你是版本问题。
2.1 为什么选 VS2015:编译器 ABI 与 CMake 生成器的对应关系
OpenCV 在 Windows 上编出来的库与 MSVC 编译器版本强绑定。VS2015 对应 MSVC 14.0,编译出来的库和静态库的 C++ ABI 用的是 VC14 的规则;换用 VS2017 或 VS2019 再编一次,虽然源码一样,生成的 .lib/.dll 里 _MSC_VER 变成了 1910 或 1920,老项目链接时直接给你报 LNK2038。老项目如果本身就是 vs2015 工程,正确的做法就是继续用 VS2015 编,而不是顺手用新版 IDE 重编一遍。
这一阶段 CMake 侧唯一的动作是把生成器选对。CMake GUI 的 Generator 下拉里选择 "Visual Studio 14 2015 Win64";命令行里对应参数为 -G "Visual Studio 14 2015 Win64"。注意 "Win64" 后缀千万别丢,不带它默认生成 32 位的 Win32 工程。一旦生成的是 x86 工程,后面链接 64 位第三方库基本没有成功的空间。
另外,VS2015 的编译器工具链需要从命令行调起来时,走 vcvarsall.bat 而不是直接裸用 cl.exe。常见做法是安装完 VS2015 后用开发者命令提示符,脚本路径在 VC 目录下面,第 4 章会给出具体调用。
2.2 获取源码与配套版本:opencv 3.2.0 与 opencv_contrib 3.2.0 必须同 tag
源码准备阶段最常见的问题是版本漂移。contrib 仓库的 master 分支和主仓库的 3.2.0 差距很大,master 里的代码会调用主仓库新版本 API,放到 OpenCV 3.2.0 上编译就是几百个 C++ 编译错误。所以主仓库与 opencv_contrib 必须同时切到 3.2.0 这个 tag。
用 git 的写法:
git clone <opencv仓库地址> opencv-3.2.0 cd opencv-3.2.0 git checkout 3.2.0 cd .. git clone <opencv_contrib仓库地址> opencv_contrib-3.2.0 cd opencv_contrib-3.2.0 git checkout 3.2.0没有 git 环境也没关系,直接把 opencv-3.2.0.zip 与 opencv_contrib-3.2.0.zip 解压到同一个父目录,注意解压后的文件夹名字里不要有中文、空格,盘符路径也统一用 D:/ 这种正斜杠,省得 CMake 解析反斜杠时出错。
解压后的目录结构建议是:
| 路径 | 作用 |
|---|---|
| D:/source/opencv-3.2.0 | 主仓库源码,CMake 的源码目录指向这里 |
| D:/source/opencv_contrib-3.2.0 | 扩展模块源码 |
| D:/source/opencv_contrib-3.2.0/modules | 扩展模块实际所在目录,CMake 变量 OPENCV_EXTRA_MODULES_PATH 必须指到这里 |
注意最后一行,"modules" 子目录是很多人的第一个坑:OPENCV_EXTRA_MODULES_PATH 指向的是 contrib 仓库里的 modules 目录,而不是 contrib 仓库根目录。填错的话 CMake 配置整个过程都正常,但 OpenCV 自己扫描模块时一个扩展模块都发现不了。
2.3 依赖项取舍:CMake 版本、Python、TBB 怎么定
依赖项不是越多越好,自编译第一原则是“能关就关”。CMake 选择 3.10~3.15 这个区间比较省心;太老的版本对 VS2015 支持不够友好,太新的版本在策略判断上偶尔会和 3.2.0 的 CMakeLists 起冲突。它们导致的都是出乎意料的配置错误,排查成本远高于收益。
Python 绑定是最容易引入麻烦的一项。OpenCV 3.2.0 的绑定代码是针对 Python 2.7/3.5 时代写的,机器上装的是 Python 3.11 时,CMake 的 FindPythonInterp 能找到解释器,但编译 python 相关模块时大概率会失败。没有 Python 接口需求就直接关掉,反正 C++ 项目用不到。
TBB、FFmpeg、MSMF 这三个选项也要单独定。做纯图像处理/离线算法时,建议把 WITH_TBB、WITH_FFMPEG、WITH_MSMF 三个都设为 OFF。TBB 关了不影响并行性,OpenCV 自带并行实现;FFmpeg 和 MSMF 关了只是视频解码能力受限,图像编解码能力仍然是内置的。这样从 CMake 阶段就避开一批视频 I/O 的外部依赖,后续编译失败概率大幅下降。关于 Java 和 OpenCL,BUILD_JAVA 也可以关掉,BUILD_OPENCL 保留默认即可。
所以前置条件的结论很直接:工具链锁死 VS2015,版本锁死 3.2.0,依赖精简到图像算法必需的那部分。剩下的事情交给 CMake。
3. CMake 配置流程:把 opencv_contrib 模块接进 VS2015 工程
3.1 用 CMake GUI 配置 OpenCV 3.2.0:源码目录与输出目录的选择
源码就位后,打开 CMake GUI。“Where is the source code” 填 D:/source/opencv-3.2.0;“Where to build the binaries” 填 D:/source/opencv-3.2.0/build-vs2015-x64。输出目录新建一个独立目录,不要直接在源码目录里 in-source 编译。虽然 OpenCV 3.2.0 版本对 in-source 编译不禁止,但一旦配置错误想重来,源码目录里会残留大量 CMake 缓存文件,很难手工清理干净。
点 Configure,弹出生成器选择窗口,选 “Visual Studio 14 2015 Win64”。第一次 Configure 跑完以后,CMake 会把 OpenCV 各模块的开关以 BUILD_opencv_xxx 的形式列出来,界面上可能出现红色变量,这个是 CMake 在提示你还有没确认的变量,不需要紧张,改完参数后再点一次 Configure 红色就消掉了。
3.2 必调的 6 个编译参数:OPENCV_EXTRA_MODULES_PATH / BUILD_opencv_world / CMAKE_INSTALL_PREFIX
CMake GUI 左侧列表选到 OPENCV_EXTRA_MODULES_PATH,值填 D:/source/opencv_contrib-3.2.0/modules。填完以后,先别急着 Generate,把下面几个参数也一起定下来。
| 参数 | 推荐值 | 说明 |
|---|---|---|
| OPENCV_EXTRA_MODULES_PATH | D:/source/opencv_contrib-3.2.0/modules | 必须指向 modules 子目录,否则扩展模块一个都不会被编译 |
| BUILD_opencv_world | ON | 把主模块和扩展模块合并成一个 opencv_world320 库,链接期只需加一个 .lib |
| BUILD_SHARED_LIBS | ON | 生成 DLL 动态库,方便后续部署替换 |
| BUILD_TESTS / BUILD_PERF_TESTS | OFF | 跳过测试和性能测试的编译,省大量时间 |
| BUILD_opencv_python2 / BUILD_opencv_python3 | OFF | 避开 Python 版本兼容问题 |
| CMAKE_INSTALL_PREFIX | D:/opencv320/install | 编译产物集中安装到这个干净目录,后续所有项目都引用这里 |
对应命令行:
cd D:/source/opencv-3.2.0 mkdir build-vs2015-x64 cd build-vs2015-x64 cmake -G "Visual Studio 14 2015 Win64" \ -DOPENCV_EXTRA_MODULES_PATH=D:/source/opencv_contrib-3.2.0/modules \ -DBUILD_opencv_world=ON \ -DBUILD_SHARED_LIBS=ON \ -DBUILD_TESTS=OFF \ -DBUILD_PERF_TESTS=OFF \ -DBUILD_opencv_python2=OFF \ -DBUILD_opencv_python3=OFF \ -DCMAKE_INSTALL_PREFIX=D:/opencv320/install \ ..上面的..是源码目录的位置,和-G放在一起时,CMake 会在当前目录生成 opencv.sln。每行结尾的\是 bash 环境下的续行符,Windows cmd 环境下改成^,或者直接写成一行。
需要注意一点:BUILD_opencv_world 默认可能是 OFF,所以自编译的人容易忽略。我一般配置完第一件事就是确认它被勾选。如果不开 world,安装目录 lib 下会出现几十个 opencv_*.lib,你在新工程里要么写一堆 target_link_libraries,要么手动一条条加,非常折磨。world 模式则链一个 opencv_world320.lib 就够了。
3.3 生成 VS2015 工程后必须确认的 3 件事
点击 Generate 生成 opencv.sln 后,先别急着编,花两分钟做三个确认。
第一,看 CMake 输出里 OpenCV modules 一栏。正常情况下应该出现一行 “To be built” 列表,里面除了 core、imgproc、highgui 等主模块,还应该有 opencv_xfeatures2d、opencv_face、opencv_text 这类 contrib 模块。如果 “To be built” 全是主模块,说明 OPENCV_EXTRA_MODULES_PATH 没有被正确读取,回到 3.2 检查路径。
第二,确认 build-vs2015-x64 下生成了 opencv.sln,且解决方案里有一个 INSTALL 项目。没有 INSTALL 项目说明安装环节配置失败,常见原因是 CMAKE_INSTALL_PREFIX 指向的路径不存在或者没有写权限。改一个可写的路径,重新 Configure 后再 Generate。
第三,查看 CMakeCache.txt 里 OPENCV_EXTRA_MODULES_PATH 变量的实际值。路径末尾不要有多余斜杠,也不要用 windows 风格的反斜杠。用grep OPENCV_EXTRA_MODULES_PATH CMakeCache.txt在 build 目录里快速确认。如果看到的值和你填的不一样,以 CMakeCache.txt 为准,并把缓存删掉重新 Configure。CMake GUI 的变量表偶尔会因为上次配置缓存而显示旧值,清除 build 目录重新来反而更快。
提示:build 目录被删掉后重新 Configure,OpenCV 的全部模块列表会重新扫描一次,耗时几分钟但非常值得,手动改缓存只会越改越乱。
4. 用 VS2015 命令行把 OpenCV 3.2.0 编译出来:Release x64 全流程
4.1 打开 VS2015 的 x64 命令行环境
生成工程之后,编译阶段不建议直接在 VS 的 GUI 里点 Build。原因有两个:一是 Release 和 Debug 配置容易在手动切换时点错,二是编译整个 OpenCV 需要几分钟到半小时,GUI 里看输出日志不如命令行直观。所以先打开一个 cmd 窗口,把 vcvarsall.bat 调用起来。
VS2015 安装完成后会设置 VS140COMNTOOLS 环境变量,指向 Common7\Tools 目录。利用它拼出 vcvarsall.bat 的路径:
call "%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat" amd64参数 amd64 表示把 cl.exe、link.exe、msbuild 全部切到 x64 工具集。注意不要用 x86_amd64 这种交叉编译写法,那会引入一个额外的中间层,对编译大型项目没有好处。执行完这条命令后,输入 cl 应该能看到 Microsoft C/C++ Optimizing Compiler 的版本信息,版本号 14.0 开头是正常的。
4.2 编到 INSTALL target:cmake --build 与关键参数
在 build 目录下执行:
cd D:/source/opencv-3.2.0/build-vs2015-x64 cmake --build . --config Release --target INSTALL -- /m:2这条命令的意思是:用 CMake 构建当前目录下的工程,构建配置为 Release,构建目标为 INSTALL(对应 opencv.sln 里的 INSTALL 项目),并通过--把 /m:2 传给底层 MSBuild,让编译最多同时跑 2 个任务。
参数细节有几个要注意的地方。--config Release 只对 VS 这种多配置生成器有意义,单配置生成器(比如 MinGW Makefiles)会忽略它,这里是 VS2015 生成器,必须在构建时指定。--target INSTALL 不是必须的,但建议用;它会在编译全部完成之后自动执行安装步骤,把头文件、库、DLL 统一复制到 CMAKE_INSTALL_PREFIX 设定的目录。如果只编 ALL_BUILD,产物会散落在 build 目录的 bin/ 和 lib/ 下面,收集起来非常麻烦。
/m:2 是 MSBuild 的并行度。OpenCV 全量编译时,contrib 里 xfeatures2d、freetype 这类模块单个编译单元非常吃内存,并行度开太高很容易把内存耗尽。8 核机器上 /m:2 差不多是“稳定优先”的选择,16G 内存可以尝试 /m:4。这一步我会预留半小时到一个小时,具体看机器,编完输出结尾会提示 BUILD SUCCESSFUL。
4.3 检查安装结果:include / lib / bin 三样产物
安装完成后打开 D:/opencv320/install,目录结构应该是清晰的:
ls D:/opencv320/install/include/opencv2 ls D:/opencv320/install/x64/vc14/lib ls D:/opencv320/install/x64/vc14/bininclude/opencv2 下能看到 opencv2/xfeatures2d.hpp、opencv2/face.hpp 等扩展模块头文件;lib 下应该有 opencv_world320.lib 或者一串 opencv_*.lib(取决于 BUILD_opencv_world 是否生效);bin 下应该有 opencv_world320.dll。目录名 x64/vc14 的具体写法取决于编译器版本,VS2015 对应 vc14,如果你装的是 VS2017 则可能是 vc15,找到实际存在的目录即可。
如果 bin 目录里找不到 opencv_world320.dll,但 lib 里有 .lib,很可能是 BUILD_opencv_world 没生效,或者编译过程中断了。回 CMake 里确认配置,重新走一遍 Generate 后再构建。
5. OpenCV 3.2.0 编译避坑指南:5 个常见翻车现场与排查
自编译 OpenCV + contrib,说难不难,但每一步都有玄学一样的坑。下面是我实际遇到并解决过的 5 个问题,按场景写清楚现象、原因和解决动作。
5.1 CMake 配置成功,contrib 模块却一个都没出现
现象:Configure 和 Generate 都顺利完成,但 “To be built” 列表里只有 core、imgproc 这些主模块,xfeatures2d、face、text 完全消失。
原因:OPENCV_EXTRA_MODULES_PATH 填到了 opencv_contrib-3.2.0 根目录,而不是 modules 子目录;或者路径中间夹了反斜杠,CMake 解析后指向不存在的位置。CMake 不会为这个路径报错,干脆把整个 contrib 扫描结果置空。
解决:把值改成 D:/source/opencv_contrib-3.2.0/modules,路径分隔符统一用正斜杠,然后删掉 build 目录重新 Configure,别在旧缓存上改,旧缓存非常容易残留错误路径。
5.2 编译到 xfeatures2d 时报大量 C++ 语法错误
现象:编译进度走到 xfeatures2d 或 face 模块时,编译器报出一堆模板推演失败、成员不存在之类的问题,报错位置指向 OpenCV 3.2.0 的头文件。
原因:主仓库和 contrib 仓库版本不匹配。最常见的是主仓库用的 3.2.0 tag,contrib 却 clone 到了 master 最新版,master 版本调用的 API 在 3.2.0 主库里不存在。两个仓库不是同一个发布版本,任何手动修补都是白费力气。
解决:把两个仓库都切到 3.2.0 tag。git checkout 3.2.0 后,删除整个 build-vs2015-x64 目录重新 Configure,因为 CMake 会把 OpenCV 模块配置信息写进缓存,光重新点 Generate 不够。
5.3 程序链接时报 LNK2038:_MSC_VER 的值对不上
现象:自己的工程链接 opencv_world320.lib 时,控制台报LNK2038: mismatch detected for '_MSC_VER': value '1910' doesn't match value '1900'。
原因:OpenCV 库是用 VS2015(_MSC_VER=1900)编的,但当前工程被 VS2017(_MSC_VER=1910)编译,运行库 ABI 不一致。VS 小版本之间的升级并不保证二进制兼容,这个错就是专门拦这种混用的。
解决:把工程的平台工具集改回 Visual Studio 2015(v140)。如果一定要用新版 IDE 编译程序,唯一的正路是把 OpenCV 3.2.0 也用新版编译器重编一遍,这不是改个链接器选项能绕过去的。反向的情况同理:主工程是 VS2015,却去链接 VS2019 编出来的 OpenCV,也会翻这个车。
5.4 Debug 编译时编译器内存耗尽,Release 却没事
现象:Release 编译顺利,切到 Debug 配置编译到 contrib 模块时,报fatal error C1060: compiler is out of heap space或fatal error C1001: internal compiler error。
原因:Debug 配置会开启完整调试符号,contrib 里像 xfeatures2d 这种大模块单个 .cpp 文件预处理后非常庞大,MSVC 的符号表占内存翻倍,再加上并行编译任务数一高,32 位 cl.exe 进程直接内存耗尽。
解决:把 MSBuild 并行度压到 /m:1 或 /m:2,并确保系统盘有足够空间用于交换文件。另一个更省事的做法是,如果主程序只需要 Release 配置,就只编 Release,不碰 Debug。等到真需要调试 contrib 内部逻辑时,再单独编所需模块的 Debug 版本。
5.5 程序跑起来提示缺 opencv_world320.dll
现象:编译链接全过了,双击 exe 运行却弹窗说找不到 opencv_world320.dll。
原因:BUILD_SHARED_LIBS=ON 时 OpenCV 编译成动态库,程序运行需要到 DLL 的搜索路径里找 opencv_world320.dll。DLL 确实存在于 install/x64/vc14/bin 下,但 Windows 默认搜索路径不包含这个目录。
解决:把 install 目录下的 bin 目录加入系统 PATH。命令行里可以这样加:
setx PATH "%PATH%;D:/opencv320/install/x64/vc14/bin"setx 写入的是当前环境的 PATH 拼接结果,新开终端才生效。如果是部署到别的机器,程序目录里直接放一份 opencv_world320.dll 更省事,或者安装对应版本的 VC Redistributable 解决运行时依赖。
6. 编译之后第一件事:写一个带 SIFT 的测试程序验证全链路
编译完别急着往老项目里接,先写一个最小程序验证一下 opencv_contrib 是否真的生效。我的习惯是固定用 SIFT:SIFT 在 3.2.0 里位于 xfeatures2d 扩展模块,主模块里根本没有。这个程序若跑通,说明 CMake 配置、contrib 编译、库安装、链接配置整条链路都没问题。
6.1 新建工程并让 CMake 找到自编译的 OpenCV
工程目录下放一个 CMakeLists.txt:
cmake_minimum_required(VERSION 3.10) project(test_sift) # 让 find_package 能找到 install 目录下的 OpenCVConfig.cmake set(CMAKE_PREFIX_PATH "D:/opencv320/install") find_package(OpenCV 3.2 REQUIRED) add_executable(test_sift main.cpp) target_link_libraries(test_sift ${OpenCV_LIBRARIES})由于 CMake 找不到 OpenCV 时不会给具体路径,CMAKE_PREFIX_PATH 必须设置在 find_package 之前。OpenCV_LIBRARIES 在设置了 BUILD_opencv_world 时只会指到 opencv_world320.lib,这也顺便验证了 world 模式的配置成功。
6.2 main.cpp:用 xfeatures2d::SIFT 检测关键点
#include <opencv2/core.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/xfeatures2d.hpp> #include <cstdio> #include <vector> int main() { cv::Mat img = cv::imread("test.jpg"); if (img.empty()) { std::printf("load image failed\n"); return 1; } cv::Ptr<cv::xfeatures2d::SIFT> sift = cv::xfeatures2d::SIFT::create(); std::vector<cv::KeyPoint> kps; cv::Mat desc; sift->detectAndCompute(img, cv::noArray(), kps, desc); std::printf("keypoints: %zu\n", kps.size()); return 0; }这里用 detectAndCompute 而不是先 detect 再 compute,是为了少写两行状态管理;关键点在 Ptr 的引用计数由 OpenCV 自己管理,不需要手动 release。desc 是否为空不影响程序退出,但 kps.size() 为 0 通常是 test.jpg 太简单导致,换一张纹理丰富的图再试。
工程根目录放一张 test.jpg,然后cmake -G "Visual Studio 14 2015 Win64" && cmake --build . --config Release。运行时如果输出 keypoints 后跟一个正数,说明 contrib 的 xfeatures2d 编译成功且链接正确;如果报 LNK2019,说明 install 目录里的 opencv_world320.lib 不完整,回第 4 章重新检查 INSTALL 产物。
这个最小验证程序我每次都做,省下的排查时间远比那几分钟多。旧项目里如果出了问题,能被整体构建系统干扰视线,而这里只有 OpenCV 一个变量。坚持这个习惯之后,每次换环境、换编译器、换 OpenCV 版本,我都能在十分钟内确认库是否可用。希望帮到你。
本文还有配套的精品资源,点击获取