ARTICLE DETAIL

资讯详情

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

Win10+VS2017下用CMake重新编译OpenCV4.5.1并集成contrib

Win10+VS2017下用CMake重新编译OpenCV4.5.1并集成contrib 简介面向Windows 10下以Visual Studio 2017和CMake重新编译OpenCV 4.5.1并集成contrib模块的C视觉开发者这套工程包同时保留了编译生成的库文件、头文件与CMake配置脚本可解决官方发行版缺少SIFT、SURF等扩展算法以及自定义编译选项难以落地的问题。资源内含992个文件压缩包约47.65MB以hpp头文件454个和exe可执行文件415个为主体另有h头文件、dll动态链接库、lib静态库、cmake工程配置文件以及xml、md、txt、rtf等格式的使用说明便于查看接口、运行示例和接入VS2017工程。包内提供CMake导入配置模块和依赖模块清单并附带环境变量配置脚本便于VS2017直接识别编译结果同时收录了BEBLID等较新contrib模块的参考实现调试版与发布版配置齐全能显著减少从源码逐项排查、反复编译的时间。各类开源组件许可证与说明文件也完整收纳方便合规使用与二次分发。该资源已有487人学习/浏览适合计算机视觉方向的中高级开发者按需裁剪OpenCV功能快速获得支持contrib模块的自定义库并投入实际项目。1. 在win10vs2017下重新编译opencv4.5.1一个“找不到dll”引发的翻车现场你去官网下好opencv4.5.1的Windows包解压照着旧教程把路径填进Path写个读图程序。编译过了一运行弹出“找不到opencv_world451.dll”就算侥幸跑通你在代码里写SIFT链接器直接报未定义符号——官方预编译包默认不带opencv4.5.1contrib。这时候所有“配置opencv”的教程都失效唯一出路就是标题里写的那句话win10opencv4.5.1vs2017cmake重新编译。这文章是给被“重新编译”卡住的人写的你大概率是冲着contrib功能、或者官网包和你机器VC版本对不上来的。照着走完能得到一份和vs2017完全匹配、带contrib的opencv_world451.dll。2. 编译前把三样东西捋顺vs2017、cmake与win10的版本矩阵2.1 vs2017的v141工具集为什么不能拿vs2019凑合opencv4.5.1官方Windows包解压后build目录里有vc14和vc15两个子目录vc15对应vs2017的v141工具集。如果你机器上只有vs2019的v142工具集硬链接vc15的lib库不一定会报错但一旦涉及contrib和debug/release混用ABI层面的差异就会出现奇怪的内存崩溃。所以标题锁死vs2017是有道理的。vs2017安装时注意要勾选“使用C的桌面开发”工作负载里面包含MSVC v141编译器、Windows 10 SDK和CMake工具。网上很容易搜到vs2017离线安装包但离线包默认不含C负载要么安装时加参数要么进去后改组件。装完在“单个组件”里确认有Windows 10 SDK版本不能太旧。opencv4.5.1的contrib模块里有些头文件依赖较新的SDK定义SDK太老会在编译期冒出各种莫名其妙的“未定义标识符”。装完后打开vs2017自带的开发者命令提示符敲一行确认工具链活着cl出来的第一行如果带“x64”字样并且版本号是19.16.x说明v141工具集可用。如果提示不是内部或外部命令回到安装器里检查C桌面开发负载是否完整。这一步不验证后面cmake生成的工程在vs里一编译就报“找不到vcvars”那时候再回头装就耽误时间了。2.2 cmake选版本3.20.x起步GUI和命令行两个入口opencv官方对cmake最低要求是3.5但这是理论值。我实际编译opencv4.5.1的经验是cmake版本太老会在configure阶段出现类似CMake Error at .../CMakeDetermineCompilerId.cmake:9的编译器探测失败。这个报错常见于cmake识别不了vs2017的v141工具集而不是你代码写错。建议直接装3.20.x的Windows x64版本下载包名是cmake-3.20.x-windows-x86_64.zip解压就能用不用安装。多说一句makefile和cmake的区别cmake不直接编译它是生成器——根据CMakeLists.txt生成vs的.sln工程或者生成makefile交给nmake/ninja执行。很多人以为cmake是编译工具其实它产出的是“工程描述”。在opencv场景里我们用cmake gui生成Visual Studio 15 2017 Win64的工程之后所有编译动作发生在vs2017里。这个理解后面排查问题会省很多事。cmake下载解压后把bin目录加入Path命令行里敲cmake --version能出来3.20.x就行。然后第3章用cmake gui第4章用命令行cmake --build两边都要用所以Path里一定得有cmake。2.3 win10系统层面的三处设置长路径、开发者模式、杀毒排除编译opencv生成的路径非常深最长能到两百多个字符。win10默认的MAX_PATH260会让很多文件写不进去。打开本地组策略WinR运行gpedit.msc计算机配置-管理模板-系统-文件系统-启用Win32长路径设为已启用。注册表方式也行reg add HKLM\SYSTEM\CurrentControlSet\Control\FileSystem /v LongPathsEnabled /t REG_DWORD /d 1 /f重启后生效。这一步不做编译到一半会冒出“Cannot open include file”或者文件系统错误不是代码问题是路径被截断了。开发者模式在设置-更新和安全-开发者选项里打开。它不是必需的但能避免一些符号链接和目录权限的怪问题特别是contrib里有些模块会创建软链接。最后是Windows Defender实时保护建议把opencv的source、build、install三个目录加进排除列表。编译时高密度读写小文件实时扫描会让编译时间翻倍甚至误杀编译产物。我一般直接把整个工作盘在Defender里排除。提示排除目录是给本地杀毒软件用的和网络无关。不要为了下载提速去动防火墙安全底线别碰。编译目录尽量放固态盘根目录下的英文路径别放C:\Users\你的中文用户名\下面。opencv的cmake脚本对非ASCII路径支持不算好中文用户名会让你在configure阶段就踩到“找不到文件”的坑。磁盘空间预留15GB以上ReleaseDebug两套编译加安装目录很占空间。opencv cmake编译步骤里最容易被忽略的就是系统环境。环境不对后面所有报错都看起来像玄学其实根源都在这一章。3. 用cmake gui配置opencv4.5.1contrib选项表与“configure-失败-重来”循环3.1 目录规划source、build、contrib三个目录分开先立个原则源码目录和构建目录绝对不能混。opencv下载解压后是opencv-4.5.1contrib解压后是opencv_contrib-4.5.1。我一般这样放D:/libs/opencv-4.5.1/ # 主仓库源码 D:/libs/opencv_contrib-4.5.1/ # contrib仓库源码 D:/libs/opencv-build-451/ # 构建目录名字上带上编译器和版本build目录名字带上vc15或vs2017是为了以后多版本并存。同一个源码你可以编出Debug/Release、x86/x64、开不开CUDA等多套组合每套都要独立build目录。以后想重新编译删掉build目录重来源码和contrib不用动。contrib模块路径只指到仓库根目录D:/libs/opencv_contrib-4.5.1不是再往下一层modules。很多人在这写错cmake虽然不报错但contrib全部不生效编出来的还是官方精简版。这个坑第5章细说。3.2 cmake gui必调选项一张表讲清楚打开cmake gui顶部两个输入框Where is the source code填源码根目录D:/libs/opencv-4.5.1Where to build the binaries填build目录D:/libs/opencv-build-451。填完后点Configure第一次会弹生成器选择选Visual Studio 15 2017 Win64。如果看到的是Visual Studio 16 2019说明cmake没找到vs2017回到2.2检查cmake版本。第一次Configure会跑很久期间下载几个第三方包。刷屏的红色警告先别慌很多是CMAKE变量警告不影响。等第一次Configure结束把下面这些选项改掉再点第二次Configure选项值说明OPENCV_EXTRA_MODULES_PATHD:/libs/opencv_contrib-4.5.1必须指到contrib仓库根目录BUILD_opencv_worldON把全部模块合成一个opencv_world451.dllOPENCV_ENABLE_NONFREEON要用SURF等算法必须开BUILD_EXAMPLESOFF不编官方示例BUILD_TESTS / BUILD_PERF_TESTSOFF不编译测试省半小时以上WITH_CUDAOFF不开显卡加速则保持OFFCMAKE_INSTALL_PREFIXD:/libs/opencv-install-451编译后安装的目标目录第一行是contrib能否编进来的关键。BUILD_opencv_world是为了让最终只产出一个dll方便拷贝。OPENCV_ENABLE_NONFREE在4.5.1里控制SURF这类受专利影响的算法SIFT在4.4以后已经移入主库的features2d模块不需要这个开关但SURF必须开。不用它的话保持OFF省得接到律师函。其余选项按需后面用DNN模块跑模型的话OPENCV_DNN_OPENCL可以留默认WITH_IPP建议保持ONopencv4.5.1会用ippicv加速代价是configure时要下载ippicv包。改完再点Configure让它跑完第二轮。此时cmake gui下方的输出流里会出现contrib模块的配置信息能看到opencv_xfeatures2d、opencv_face、opencv_sfm等模块名。这一步就是“opencv cmake编译步骤”里区分成败的分水岭列表里没有contrib后面vs里编出来就是官方精简版。3.3 Generate之后生成OpenCV.sln第二次Configure没有红色error后点Generate。cmake gui会把工程写到build目录里。生成完后打开build目录应该能看到OpenCV.sln。同时build目录下会出现CMakeCache.txt这是后续排查的重要文本里面记录每一次configure的变量。我习惯生成完先把CMakeCache.txt里OPENCV_EXTRA_MODULES_PATH搜一遍确认路径没被cmake转义成乱七八糟的反斜杠。如果你不想用gui命令行一样能做D:/libs/opencv-build-451/ cmake -G Visual Studio 15 2017 Win64 ^ -DOPENCV_EXTRA_MODULES_PATHD:/libs/opencv_contrib-4.5.1 ^ -DBUILD_opencv_worldON ^ -DOPENCV_ENABLE_NONFREEON ^ -DBUILD_EXAMPLESOFF ^ -DBUILD_TESTSOFF ^ -DCMAKE_INSTALL_PREFIXD:/libs/opencv-install-451 ^ ../opencv-4.5.1^是Windows命令行换行符cmake变量用-D传。和gui是同一套逻辑。这里有个容易混淆的点cmake命令第一次执行时相当于gui的ConfigureGenerate两步之后你再跑同样的cmake命令不会重新configure除非把CMakeCache.txt删掉。要改选项用gui重新Configure别手动去删cache。configure阶段卡住最多的地方是下载ippicv和ffmpeg。第一次Configure输出里会有Download: ippicv_2020_win_intel64_...zip这行多数人栽在这。常见做法是提前手动下载这些第三方包放进对应缓存目录具体操作放第5章避坑里那是血泪经验。4. 在vs2017里跑完编译与安装从ALL_BUILD到INSTALL再到配环境变量4.1 两种编译入口sln和cmake --buildGenerate完成后OpenCV.sln就是vs2017的解决方案。双击打开在工具栏把解决方案配置从Debug换成Release、平台选x64。右键ALL_BUILD生成。这是最直观的方式第一次编译会看到几千个文件在编译CPU占用拉满耗时看机器20分钟到一个半小时不等。如果想命令行等效操作是cd D:/libs/opencv-build-451 cmake --build . --config Release --target ALL_BUILD -j 8--config Release对应vs里的配置-j 8是并行任务数按cpu核数设置。注意cmake --build在vs生成器下其实是调MSBuild不是ninja它不会因为你机器16核就自动并行必须显式给-j。如果你装了ninja也在Path里这里依然走MSBuild因为第3章生成器选的是Visual Studio不用纠结这个。编译过程中最常见的中断是某个模块报C2xxx错误。看到错误别急着重来把错误日志复制出来搜一下opencv4.5.1配vs2017在官方CI里测过理论上是能一次过的。报错多出在contrib的新模块往往和SDK版本、python绑定有关。我的习惯是一旦某个模块编译失败先看完整错误是不是opencv_python或者opencv_java这种绑定模块——这些用不到的先关掉能避开一半的坑。关闭方法重新打开cmake gui把BUILD_opencv_python3和BUILD_opencv_java设为OFF再ConfigureGenerate回到vs重新编。4.2 INSTALL把产物装到CMake文件指定的前缀ALL_BUILD通过后再编INSTALL目标cmake --build . --config Release --target INSTALLINSTALL不会重新编译代码它只是把编译好的lib/dll/头文件按目录结构拷贝到CMAKE_INSTALL_PREFIX指定的D:/libs/opencv-install-451。装完检查三个关键目录install/include下有没有opencv2整个目录install/x64/vc15/lib下有没有opencv_world451.libinstall/x64/vc15/bin下有没有opencv_world451.dll。三个全齐说明这一轮编译成果是完整的。如果Debug也要用重复上面两条命令把Release换成Debug。注意Debug的库文件名多一个dopencv_world451d.lib和opencv_world451d.dll。混用版本是后面运行崩溃的主要来源。大多数时候你只需要Release库Debug的库编译时间几乎翻倍要是只做算法验证建议先只装Release。4.3 给vs2017工程配引用环境变量与项目属性页先配系统环境变量新建OPENCV_DIR指到D:/libs/opencv-install-451再把%OPENCV_DIR%\x64\vc15\bin加进Path。很多教程直接写死路径我推荐用OPENCV_DIR以后换版本只改一个变量。回到vs2017项目里右键项目-属性分两块填。C/C-常规-附加包含目录填$(OPENCV_DIR)\include链接器-常规-附加库目录填$(OPENCV_DIR)\x64\vc15\lib链接器-输入-附加依赖项里写opencv_world451.lib。Release配置写这个Debug配置要把文件名换成opencv_world451d.lib。如果你用了BUILD_opencv_worldOFF这里就没这么省事得把opencv_core451.lib、opencv_imgproc451.lib逐个列。命令行配环境变量可以这样setx OPENCV_DIR D:/libs/opencv-install-451 setx PATH %PATH%;%OPENCV_DIR%\x64\vc15\bin但注意setx写Path有1024字符截断风险如果原来Path很长追加后会被截断系统里一堆工具会找不到。保守做法是系统属性-环境变量界面里手动加或者导出Path到文本先备份。我吃过一次setx截断的亏重装了一半工具链才缓过来从那以后Path一律用界面改。提示vs2017项目属性页分“活动解决方案配置”Debug和Release要分别填别只填一个然后在另一个配置里跑半天报链接错误。写完代码后编译时如果提示找不到头文件先看包含目录有没有拼错如果是无法打开opencv_world451.lib看库目录如果是运行时报找不到opencv_world451.dll基本是Path没生效。改完环境变量要重开vs让新环境变量进进程再跑。这一章内容对做过qt的人很熟悉vs2017配置qt流程里也是同一套源码用cmake生成工程然后项目属性里指定包含目录和库目录。理解了这套逻辑opencv和qt在你机器上通用了。5. 避坑重编opencv4.5.1最常见的5个翻车现场5.1 configure卡死ippicv和ffmpeg下载超时现象第一次点Configure后cmake gui一直停在Download: ippicv_2020_win_intel64_20191018_general.zip进度条不动过一会儿报网络相关错误。日志里能看到连不上raw.githubusercontent或者opencv的下载服务器。原因opencv的cmake脚本在configure阶段会联网拉取ippicv、ffmpeg、ade这几个第三方组件。win10vs2017的组合本身没问题问题出在下载环节。默认下载地址对国内网络不友好超时是常态。解决手动把这三个文件下好放到build目录对应的缓存位置。ippicv文件放build/opencv/3rdparty/ippicv/ffmpeg的dll放build/opencv/3rdparty/ffmpeg/ade放build/opencv/3rdparty/ade/。文件名要和cmake脚本期望的一致可以从第一次configure的输出里看到它要的精确文件名和md5。放好以后重新Configure这一步会直接检测到缓存文件跳过下载。实际操作时我一般是先跑一次Configure让它下载失败再去查看缓存目录结构。目录是cmake脚本为这次build自动创建的你只需要把下载好的文件放进去。文件名不能改md5校验不通过照样重新下载。5.2 contrib模块没生效编完了还是精简版现象编译、安装、配环境变量全走完了代码里#include opencv2/xfeatures2d.hpp依然找不到文件或者链接SURF符号失败。更隐蔽的情况是编译成功了但程序刚运行就崩在xfeatures2d::SURF::create。原因OPENCV_EXTRA_MODULES_PATH没写对。最常见的是指到了opencv_contrib-4.5.1/modulescmake认为你指定了一个不存在的目录不会报错只是contrib一个都没加进去。另外如果是指到仓库根目录但路径里有空格cmake解析也可能出问题。解决重新打开cmake gui确认OPENCV_EXTRA_MODULES_PATH的值是D:/libs/opencv_contrib-4.5.1不是modules子目录。Configure后盯着输出流里有没有opencv_xfeatures2d。Generate后顺手去build目录搜一下看生成的文件里有没有modules/xfeatures2d相关工程文件。我每次都这样双重确认因为配错了再编译一次的时间足够你喝两杯咖啡。5.3 contrib模块报C2065/C1083SDK和新特性冲突现象编译到contrib某个模块时报fatal error C1083: Cannot open include file: stdint.h或者error C2065: nullptr: undeclared identifier。一眼看过去像是代码写错但源码是官方仓库的。原因这些是Windows SDK版本和编译器标准级别的问题。vs2017里如果“C语言标准”没切到C14以上contrib里较新的模块会用C11/14特性MSVC默认标准太老就报错。另一部分是Windows 10 SDK太旧缺stdint.h等头文件。解决vs2017项目里本来就设置了正确的标准但如果你用的是命令行cmake --build没有继承vs的项目设置得在cmake里显式指定。重新configure时加一个变量cmake -DCMAKE_CXX_STANDARD14 -DCMAKE_CXX_STANDARD_REQUIREDON ...另外打开vs2017安装器把Windows 10 SDK更新到最新版本10.0.19041或更高。这个坑在4.5.1contrib组合里出现过特别是opencv_sfm和opencv_stereo这类依赖线性代数库的模块SDK版本不够就会编不过去。5.4 程序运行时找不到opencv_world451.dll现象程序编译链接全过了双击exe弹窗“找不到opencv_world451.dll”但明明装目录的bin里有这个文件。原因Path环境变量没生效或者生效顺序不对。最常见的是在cmd里用setx改完Path没重开命令行直接运行exe再或者你改了系统变量但vs还在用旧环境。还有一种隐蔽情况你往Path里加的是D:/libs/opencv-install-451/bin实际dll在x64/vc15/bin目录少了一层。解决先确认dll的绝对路径在cmd里直接敲D:/libs/opencv-install-451/x64/vc15/bin/opencv_world451.dll能弹出文件属性窗口说明路径存在。然后确认Path里有没有包含这一层目录。如果确认无误还是找不到最省事的方法是把这个dll复制到exe同目录Windows会优先加载exe所在目录的dll。这不算脏活很多商业项目交付时也这么干免去客户机配环境变量。5.5 Debug和Release库混用运行时随机崩溃现象程序在Debug调试器里跑图像处理偶发崩溃或者cv::Mat释放时heap corruption。编译无错误链接无警告。原因给Debug配置填了opencv_world451.librelease版或者反过来。MSVC的Debug和Release运行时库不兼容Debug程序必须链带d后缀的debug库。opencv的install目录里x64/vc15/lib下会同时有opencv_world451.lib和opencv_world451d.lib填错一个就是这种玄学崩溃。解决项目属性里逐项核对。Debug配置的附加依赖项写opencv_world451d.libRelease写opencv_world451.lib。还有一个更隐蔽的点如果程序用了第三方库第三方库如果是Release编译的你整个程序也得是Release否则第三方库内部申请的堆和你的堆不一致照样崩。这已经不是opencv能背的锅了但在这个场景里最容易被问出来记一笔。6. 编译完怎么验证写一个SURF测试程序确认contrib真的编进来了编译安装是一条线验证是最后一道闸。我从不相信“应该编进去了”只信程序跑出来的结果。下面这段测试代码同时验证了opencv主库和contrib的xfeatures2d是否可用。先建一个项目目录放main.cpp#include opencv2/opencv.hpp #include opencv2/xfeatures2d.hpp int main() { cv::Mat img cv::imread(test.jpg, cv::IMREAD_GRAYSCALE); if (img.empty()) { return -1; } auto surf cv::xfeatures2d::SURF::create(800); std::vectorcv::KeyPoint kps; surf-detect(img, kps); cv::Mat out; cv::drawKeypoints(img, kps, out); cv::imwrite(out.jpg, out); return 0; }CMakeLists.txtcmake_minimum_required(VERSION 3.10) project(opencv_test) find_package(OpenCV REQUIRED) add_executable(test main.cpp) target_link_libraries(test ${OpenCV_LIBS})然后命令行编译mkdir test-build cd test-build cmake .. -DOpenCV_DIRD:/libs/opencv-install-451 cmake --build . --config ReleaseOpenCV_DIR必须指到安装目录的根cmake会去那里找OpenCVConfig.cmake。如果你前面配了系统环境变量OPENCV_DIR这里也可以不传cmake能自己搜到。跑起来后做两个检查。第一out.jpg能正常生成说明主库的imgcodecs、features2d都工作第二如果程序里换成SURF不崩溃说明contrib的xfeatures2d真的编进来了。只看编译通过不算数运行时不崩才算。进阶一点我还会顺手写个cv::getBuildInformation()打印里面能看到这一份opencv是哪个编译器编的、开了哪些模块。跑一下std::cout cv::getBuildInformation() std::endl;输出会带“NONFREE”配置信息如果缺SURF这里也能看出来。这套验证流程做完这份win10opencv4.5.1vs2017cmake重新编译的工程才算真正落地。我每次编完opencv第一件事就是跑这段SURF测试。它帮我拦住过至少三次配错环境变量的低级错误希望帮到你。本文还有配套的精品资源点击获取
返回列表