尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Windows下编译OpenCV_contrib完整指南:从CMake配置到项目集成

Windows下编译OpenCV_contrib完整指南:从CMake配置到项目集成 1. 编译前的准备与版本配套1.1 为什么一定要自己编译OpenCV_contrib很多刚入门OpenCV的朋友都会问一个问题OpenCV官网直接下载的Windows安装包双击装完就能用为什么非要折腾源码编译原因很简单官方预编译包只包含主库OpenCV主仓库不包含contrib模块。contrib是OpenCV的扩展仓库里面全是高价值的实验性模块和最新算法比如著名的SIFT、SURF特征点检测xfeatures2d、文本检测text、超分辨重建dnn_superres、增强现实标记检测aruco、目标跟踪tracking等。如果你要做的项目需要用SIFT做图像配准或者用dnn_superres做图像超分不好意思官方安装包直接给你报未定义的符号错误——因为这些代码根本不在里面。另外一个更现实的原因是版本配套问题。contrib模块的版本必须与主库严格对应OpenCV 4.10.0的主库必须配4.10.0的contrib混搭版本在CMake配置阶段就可能报错就算侥幸配置通过编译时也会出现一堆函数签名不一致的问题。这种坑我踩过不止一次所以干脆写一篇完整的编译指南从零开始带你走一遍。1.2 编译前的工具链准备在Windows下编译OpenCV需要的核心工具其实就三样CMake、Visual Studio、以及Python环境可选看你是否需要Python接口。先说要安装什么版本这直接决定你后续会不会遇到奇怪的问题。Visual Studio版本选择我建议用VS2019或VS2022。VS2015和VS2017虽然也能编译但CMake生成的工程文件在旧版本上偶尔会有兼容性问题。如果你手头有VS2010——请直接放弃OpenCV 4.x早就放弃了对VS2010的支持硬编只会收获满屏的语法错误。官网的预编译包支持到什么VS版本源码编译就建议用什么VS版本这是最省心的策略。CMake版本选择OpenCV 4.10.0要求CMake 3.5.1以上建议直接装最新的3.29或3.30版本。官网下载Windows版安装包即可安装时记得勾选Add CMake to the system PATH for all users省得后面命令行里找不到cmake命令。Python环境可选但强烈建议如果你需要编译出带Python接口的OpenCV务必提前装好Python并且一定要记住是64位还是32位。VS编译器的架构必须和Python解释器架构一致否则编译出来的cv2.pyd文件无法被Python加载。我一般用Anaconda管理Python环境创建虚拟环境后再开始编译。还要提一句话编译过程中会从GitHub下载一些第三方依赖包比如ippicv、ffmpeg、boostdesc等。这些下载经常超时失败建议确保你的网络能正常访问GitHub和raw.githubusercontent.com域名这部分卡住是新手最常见的第一道坎后面我会单独讲怎么解决。1.3 源码下载与目录结构规划源码下载有两个渠道GitHub官方仓库和OpenCV官网。GitHub下载速度通常更快也方便后续切换分支。下载时要同时下载两个仓库注意版本号必须一致# 下载主仓库 git clone --branch 4.10.0 https://github.com/opencv/opencv.git # 下载contrib仓库 git clone --branch 4.10.0 https://github.com/opencv/opencv_contrib.git不习惯用命令行也没关系GitHub页面直接下载对应tag的zip包解压后效果一样。我习惯用git clone因为后续如果发现某个模块有问题可以方便地切换到其他提交看看。目录结构我有一个固定习惯按这个规划可以避免很多路径相关的坑D:\opencv_build\ ├── opencv\ # 主库源码 ├── opencv_contrib\ # contrib源码 ├── build\ # CMake输出目录存放编译中间文件 └── install\ # 最终安装目录头文件、lib、dll都在这这里有几个关键原则所有路径不能有中文和空格源码目录和构建目录必须分开不能直接在主库源码目录里配置contrib源码目录最好和build目录平级方便CMake引用路径。源码目录规划好之后准备工作就算完成了。接下来是整篇文章最核心的部分CMake配置。2. 用CMake配置编译参数2.1 给CMake喂对参数CMake是编译的总调度它负责检查你的系统里有哪些工具、有哪些依赖然后生成一份适合当前环境的Visual Studio工程文件。OpenCV编译的大多数坑其实都出在CMake配置这一步。在build目录里打开命令行Windows下建议用Developer PowerShell for VS或者VS自带的命令行工具运行以下命令cmake -DCMAKE_BUILD_TYPERelease ^ -DCMAKE_INSTALL_PREFIXD:/opencv_build/install ^ -DOPENCV_EXTRA_MODULES_PATHD:/opencv_build/opencv_contrib/modules ^ -DWITH_TBBON ^ -DWITH_CUDAOFF ^ -DBUILD_opencv_worldON ^ -DBUILD_EXAMPLESOFF ^ -DBUILD_TESTSOFF ^ -DBUILD_PERF_TESTSOFF ^ -DPYTHON3_EXECUTABLED:/Anaconda3/envs/opencv_env/python.exe ^ D:/opencv_build/opencv注意最后一行是主库源码路径前面都是配置参数。这里面有几个参数很关键逐一解释一下。-DOPENCV_EXTRA_MODULES_PATH是指定contrib模块源码路径这是整个配置的核心指错路径后面直接白干。路径要精确到modules目录不是opencv_contrib仓库的根目录。-DBUILD_opencv_worldON的意思是生成一个整合了所有模块的world库文件。编译完成后你会得到一个opencv_world4100.lib和opencv_world4100.dll而不是几十个分散的小库。这样做的好处是项目链接时只需要配置一个库文件省心很多。-DPYTHON3_EXECUTABLE只有在需要编译Python接口时才指定。填的是你希望使用的Python解释器路径。CMake会自动检测Python的include目录和lib目录如果检测失败就需要额外指定PYTHON3_INCLUDE_DIR和PYTHON3_LIBRARY。2.2 模块裁剪与特性开关初次编译时很多人会图省事直接全模块编译。我要说千万别这么做。contrib模块里有大量依赖外部库的模块比如xfeatures2d依赖boostdesctext依赖tesseractdnn_superres依赖深度学习推理后端等。这些依赖有些在编译时会临时下载下载失败就编译失败有些需要你提前装好库不然直接跳过该模块。为了避免一上来就碰壁建议先配置一个最小可用的组合。在CMake配置完成后会输出一份模块清单你可以手动修改build目录下的CMakeCache.txt来禁用某些模块也可以用参数直接在命令行中指定-DBUILD_opencv_xfeatures2dOFF -DBUILD_opencv_textOFF -DBUILD_opencv_dnn_superresOFF我的经验是第一次编译先尽量精简保底跑通整个流程确认工具链没问题之后再回头逐步打开需要的模块。OpenCV编译一次动辄半小时起步如果因为一个模块的依赖下载失败导致全部推倒重来那真是浪费时间。还有一个高频开关是-DWITH_TBBTBB是Intel的并行计算库能加快部分算法的运行速度。开启这个选项前需要确保CMake能找到TBB的安装位置否则CMake阶段会自动关闭它不会导致编译失败但性能上会有些损失。如果你不追求极致性能直接-DWITH_TBBOFF也是没问题的。2.3 CMake配置成功的标志运行完cmake命令后如果最后输出类似这样的信息Configuring done Generating done就说明配置成功了build目录里会生成OpenCV.sln解决方案文件。如果中途报错别急着重新运行先打开错误信息往上翻找到CMake Error之前的警告部分往往真正的线索都在警告里。我用一个表格总结CMake配置阶段的关键参数方便大家逐个对照检查参数作用建议值CMAKE_BUILD_TYPE编译类型ReleaseCMAKE_INSTALL_PREFIX安装路径一个不含中文和空格的纯英文路径OPENCV_EXTRA_MODULES_PATHcontrib模块路径精确到opencv_contrib/modulesBUILD_opencv_world是否合并为单个库ONWITH_TBB启用TBB并行库按需WITH_CUDA启用CUDA GPU加速OFF有GPU再开BUILD_EXAMPLES是否编译官方示例OFFBUILD_TESTS是否编译单元测试OFFBUILD_PERF_TESTS是否编译性能测试OFF配置成功之后下一步就是真正的编译了。3. 使用MSVC编译的实操过程3.1 打开解决方案与选择编译配置CMake配置完成后进入build目录双击OpenCV.slnVisual Studio会自动打开。如果CMake是用VS2019生成的就用VS2019打开用VS2022也能打开但会提示升级解决方案一般没问题。打开后第一件事就是把解决方案配置从Debug切换到Release。原因有两点Debug版本编译出来的库文件巨大而且运行时依赖一堆调试运行时库发布到别的机器上时经常因为缺VCRUNTIME140D.dll而报错Release版本性能好、体积小也更容易发布部署。第二件事是确认平台是x64。如果你的Python是64位的或者你的项目是64位应用就必须选x64平台。选择x64时如果系统提示这需要下载额外的组件或者平台工具集不匹配大部分情况是因为没有安装使用C的桌面开发工作负载。打开Visual Studio Installer勾选这个组件补装一下即可。3.2 编译的两种方式界面操作与命令行在Visual Studio界面里编译路径是在解决方案资源管理器里找到项目ALL_BUILD右键选择生成。这个过程会根据你机器的核数耗时20到60分钟不等期间你会看到输出窗口里不断滚动编译日志。但我更推荐用命令行编译尤其是生成opencv_world库时命令行操作更灵活可控可以指定只编译某几个项目不用傻等ALL_BUILD把所有项目编译完。打开VS自带的开发者命令行工具Developer Command Prompt进入build目录执行cmake --build . --config Release --target opencv_world这条命令只编译opencv_world一个目标大大缩短了编译时间。如果连编译哪个模块都不确定就直接cmake --build . --config Release这会编译所有项目包括那些你用不到的测试和示例。等待时间会拉长所以我推荐先编译核心世界库验证没问题之后再编译其他需要的目标。编译结束后建议再执行一下install目标把生成的头文件、库文件和DLL统一拷贝到CMAKE_INSTALL_PREFIX指定的目录cmake --build . --config Release --target INSTALL执行完打开你之前设置的D:/opencv_build/install目录应该能看到典型的OpenCV目录结构install\ ├── include\opencv2\ # 头文件 ├── x64\vc16\lib\ # 静态库和导入库 └── x64\vc16\bin\ # 运行时DLL到这一步编译和安装就全部完成了。接下来就是怎么在自己的项目里用起来。3.3 编译中的性能优化与中断处理编译是个体力活但也有一些加速小技巧。如果你的CPU是多核的可以在命令行编译时使用MSBuild的并行参数cmake --build . --config Release /m:8意思是同时启动8个MSBuild进程充分压榨CPU性能。具体数字建议设置成你CPU的物理核心数不要盲目设大否则内存不够反而会导致编译变慢甚至卡死。编译中途如果遇到某个文件报错不用担心整个编译过程白费。MSBuild编译过的文件会缓存不会重新编译你只需要修正问题后再次执行同样的命令即可。这也算是命令行编译比VS界面好的一个优点它清楚告诉你上次编译到哪一步了而VS界面有时候会莫名其妙地从零开始重新编译。4. 项目集成与运行部署4.1 项目属性配置编译好OpenCV之后要把它用到自己的工程里还要做几步配置。这一步也是很多初学者觉得复杂的地方其实逻辑很简单告诉编译器头文件在哪、告诉链接器库文件在哪、告诉运行时DLL在哪。在VS项目里右键项目打开属性页按以下顺序配置第一步配置头文件目录在VC目录里的包含目录中添加D:/opencv_build/install/include D:/opencv_build/install/include/opencv2第二步配置库文件目录在VC目录里的库目录中添加D:/opencv_build/install/x64/vc16/lib第三步配置附加依赖项在链接器 - 输入 - 附加依赖项中添加opencv_world4100.lib注意opencv_world4100.lib是Release版本的导入库如果你编译的是Debug版本对应的库名是opencv_world4100d.lib。Debug和Release的库文件不能混用这几乎是新手必踩的坑。4.2 运行时DLL与程序发布配置完成后写一段简单的验证代码随手读入一张图片做边缘检测#include opencv2/opencv.hpp #include iostream int main() { cv::Mat img cv::imread(D:/test.jpg); if (img.empty()) { std::cerr Failed to load image! std::endl; return -1; } cv::Mat edges; cv::Canny(img, edges, 100, 200); cv::imwrite(D:/edges.jpg, edges); std::cout Edge detection done! Size: img.cols x img.rows std::endl; return 0; }编译运行如果提示找不到opencv_world4100.dll说明运行时找不到DLL。解决方式有三种最简单的就是把install/x64/vc16/bin目录下的opencv_world4100.dll复制到你的exe所在目录。这种方式适合开发阶段快速验证。第二种方式是把DLL目录加入系统环境变量PATH这样所有项目都能找到但要注意环境变量里多了之后可能造成版本冲突。第三种方式是用CMake来配置OpenCV的依赖关系这是推荐的生产级做法cmake_minimum_required(VERSION 3.10) project(MyProject) set(OpenCV_DIR D:/opencv_build/install) find_package(OpenCV REQUIRED) add_executable(my_app main.cpp) target_link_libraries(my_app ${OpenCV_LIBS})用CMake管理的好处是后续换机器或者换OpenCV版本时只需要修改OpenCV_DIR一个变量即可不用手动维护一堆VS属性配置。而且find_package会自动处理好include目录、库目录等一系列细节。4.3 验证contrib模块是否生效集成完成后最好立刻验证一下contrib模块是否真的编译进来了。写一个调用SIFT的测试程序SIFT在OpenCV 4.x里属于xfeatures2d模块只有contrib才有#include opencv2/opencv.hpp #include opencv2/xfeatures2d.hpp #include iostream int main() { cv::Mat img cv::imread(D:/test.jpg, cv::IMREAD_GRAYSCALE); auto detector cv::SIFT::create(); std::vectorcv::KeyPoint keypoints; detector-detect(img, keypoints); std::cout Found keypoints.size() SIFT keypoints. std::endl; return 0; }如果编译和运行都正常输出关键点数量恭喜你contrib模块已经成功集成。如果编译时报找不到xfeatures2d头文件说明CMake配置阶段没有正确包含contrib模块回到第二章检查OPENCV_EXTRA_MODULES_PATH是否有拼写错误。5. 常见问题与排查技巧实录5.1 CMake阶段下载依赖失败的应对编译OpenCV时CMake配置阶段会尝试下载一些第三方预编译库最典型的是ippicv和ffmpeg。由于服务器在国外下载经常超时导致配置中断。这个问题我遇到的次数太多了想单独拿出来说。一种行之有效的办法是手动下载并放置到本地。先查看build目录下CMakeDownloadLog.txt日志里记录了所有尝试下载的文件URL。找出下载失败的文件名用浏览器或下载工具手动下载对应文件然后放到CMake期望的下载缓存目录里。默认缓存目录是C:/opencv_download_cache或者build/CMakeDownloadLog.txt同级的隐藏目录具体路径根据CMake提示调整。还有一种做法是直接编辑CMakeCache.txt把对应选项指向本地文件路径。以ippicv为例在CMakeCache.txt里搜索OPENCV_IPPICV_LOCATION把它改成你手动下载好的文件路径即可。这个方法不是官方推荐的做法但在实际工程中非常实用能省下大量等待时间。5.2 编译中途报错C2491或LNK2005编译contrib模块时出现C2491: dllimport 不允许定义或者LNK2005: 符号已经在...中定义的错误通常是因为主库和contrib的版本号不匹配或者主库编译时的CMake配置项与contrib不一致。解决办法是清空build目录重新用同一份CMake命令配置两个仓库。注意CMakeCache.txt里残留的旧配置项不会自动清理如果你改了某些参数后发现行为还是老样子直接把build目录内容全部删除重新配置这是最彻底的排查方式。我吃过的亏让我养成一个习惯任何配置变更后宁可在build目录里重跑一次cmake也不要在一个带旧缓存的环境里调参数。5.3 编译时间过长的优化建议全量编译OpenCV contrib在我当时的机器上8核16线程第一次花了将近2小时第二次因为只想增加一个模块用了部分编译的方式只花了20分钟。如果你的目标只是某个具体模块可以用命令行指定目标项目cmake --build . --config Release --target opencv_xfeatures2d这个方法只编译指定的模块项目依赖的库会自动先编译。前提是之前已经成功编译过整个工程或者相关的依赖库。另外如果你确认只需要C接口可以在CMake配置时用-DBUILD_LISTcore,imgproc,imgcodecs,highgui,features2d,xfeatures2d指定要编译的模块列表这会大大减少编译量也避免那些不需要的模块给你带来额外的依赖麻烦。5.4 常见问题速查表我把编译过程中遇到的高频问题整理成一个速查表方便大家遇到问题时直接对照症状可能原因解决方案CMake卡在下载ippicv/ffmpeg网络原因导致下载超时手动下载文件并修改CMakeCache.txt指向本地编译报C2491 dllimport错误主库与contrib版本不匹配清空build目录重新用同一版本源码配置运行时找不到opencv_world4100.dllDLL未复制到exe目录或未配置PATH将dll复制到exe目录或配置环境变量链接时报LNK2019无法解析的外部符号库文件未匹配或Debug/Release混用检查附加依赖项和配置类型确保库匹配Python导入cv2失败Python版本架构不匹配统一编译器架构和Python架构都使用64位编译xfeatures2d模块时报boostdesc.h错误缺少boostdesc和vgg_generated系列文件手动下载这些预训练文件放到modules/xfeatures2d/src目录opencv_world编译通过但install没产物没有执行INSTALL目标执行cmake --build . --config Release --target INSTALL5.5 再说说boostdesc和vgg_generated文件如果编译xfeatures2d模块大概率会遇到fatal error C1083: 无法打开包括文件: boostdesc_bgm.i这类报错。这是因为xfeatures2d里用到的部分特征描述子需要下载一组预训练数据文件这些文件在源码仓库里没有包含需要编译时从网上下载。这类文件一共有大约10个左右文件名是boostdesc_bgm.i、boostdesc_bgm_bi.i、vgg_generated_48.i等等。当CMake下载失败或网络不畅时编译就会卡在这个环节。解决方法是从GitHub上直接找opencv_contrib仓库的modules/xfeatures2d/src目录把缺失的.i文件手动下载下来放进你本地的同一个目录里。然后把CMakeCache.txt里的OPENCV_XFEATURES2D_BOOSTDESC相关选项清空重新配置编译。这块属于纯粹的排查经验官方文档里写得很简略不实际踩一遍很难意识到问题出在哪。我把这一步单独列出来是因为我见过太多人在编译xfeatures2d上卡住浪费了大把时间。6. 一些关于版本选择的额外心得最后再分享一点版本选择的心得。OpenCV的版本更新频率不算快但每个大版本之间API变化不小。比如3.x到4.x很多模块从cv::命名空间调整到了cv::下新的子命名空间SIFT算法从cv::xfeatures2d::SIFT变成了cv::SIFT4.4.0之后。所以选定一个版本后最好长期保持不要频繁升级。我个人的做法是每个项目在README里明确记录OpenCV版本和编译参数防止日后重建环境时踩坑。如果你只是需要某个具体功能比如SIFT其实未必需要编译整个contrib。OpenCV 4.4.0之后SIFT和SURF已经移入了主库直接包含opencv2/features2d.hpp即可使用。在动手编译之前先查清楚你需要的功能属于主库还是contrib库是很有必要的能省不少事。在Windows下编译OpenCV_contrib核心无非三件事版本匹配、CMake参数正确、网络下载顺畅。把这三件事理清了剩下的就是等待编译结束。希望这篇指南能为你省下几个下午的折腾时间。
返回列表