ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

OpenCV 3.2.0 与 MinGW、Qt 5.9.6 的 Windows 编译实战指南

OpenCV 3.2.0 与 MinGW、Qt 5.9.6 的 Windows 编译实战指南 简介面向 Windows 10 64 位、Qt 5.9.6 与 MinGW 环境的 OpenCV 3.2.0 预编译资源包专为需要跳过 CMake 配置与源码编译的 C 开发者设计可将库文件直接引入 Qt 工程用于图像处理及视觉功能界面开发。包体为 7z 压缩格式共 245 个文件约 10.61MB其中 145 个 hpp、57 个 h 头文件提供接口声明17 个 dll 与 16 个 a 导入库对应运行与链接另有 5 个 exe 示例、4 个 cmake 配置和 1 个 txt 说明辅助验证。从内容预览可见 core、imgproc、highgui、features2d、calib3d、objdetect、stitching、videostab、superres、photo 等模块的库文件覆盖图像处理、特征检测、相机标定、图像拼接等常见工作可满足大部分基础视觉开发需求。资源内不包含源码所有文件均面向 MinGW 工具链整理不依赖 Visual Studio目录结构清晰便于直接放入 Qt 项目的库路径。包内示例程序与说明可帮助快速确认集成结果减少环境排错消耗。目前已有 239 人学习下载适合希望在 Win10 下快速使用 OpenCV 的初学者或中级开发者。 前阵子帮朋友处理一个老工程终端里跑的是 opencv 3.2.0界面层依赖 Qt 5.9.6系统是 Windows 10。这个组合放在今天看确实有点复古但在工业设备、实验室、学校项目里依然大量存在尤其是一些不能随便升版本的存量代码。问题在于 OpenCV 官方只发布 MSVC 预编译包如果你用的是 MinGW 工具链直接拿官方 DLL 去链接符号表基本全对不上。于是我自己从源码编了一套 opencv3.2.0_mingw接上 Qt 5.9.6在 win10 上跑通这篇文章把整个流程、参数和踩过的坑一次说清。1. 这套组合出现在什么场景下以及为什么需要自己编译1.1 谁还在用这套组合先说场景。OpenCV 3.2.0 是 2016 年底的版本但到现在还有不少项目在用主要原因是很多老代码基于cv::Mat和cv::VideoCapture的旧接口写死了升级到 4.x 后高gui和imgcodecs模块拆分变化很大函数名也有改动不太敢动。Qt 5.9.6 是 LTS 版本稳定很多工控上位机、检测软件就是用这一代写的Win10 下跑完全没问题。我遇到的情况是底层图像的采集、灰度处理、边缘检测都用 OpenCV上层界面用 Qt 做显示和交互。这种组合最痛苦的环节就是工具链。VS 的 MSVC 编译器是闭源且有版权的即使社区版免费很多开发者在企业环境里也不方便装。MinGW 是开源的 GCC 移植版和 Qt 的 MinGW 版本天然配套所以很多团队就选了 MinGW。问题来了OpenCV 官方 Windows 预编译包只提供了 MSVC 编译的版本文件名叫opencv-3.2.0-vc14.exe它对应的运行时是 MSVC 2015 的。你用 MinGW g 去链接会出现一堆undefined reference to这是两种编译器的 C ABI 不一致导致的没有任何捷径必须自己用 MinGW 重新编译 OpenCV。1.2 官方预编译包为什么用不了顺带解释一下 MSVC 和 MinGW 的区别。MSVC 是微软的编译器生成的对象文件格式、名称修饰规则、标准库实现都和 GCC 完全不同。MinGW 虽然同样运行在 Windows 上但它依赖的是 POSIX 风格的 GNU 工具链。两者编译出的 C 二进制在 Windows 平台下基本不能混用尤其涉及 STL、异常、Qt 对象模型时。所以如果网上有现成的opencv MinGW版本也别急着用。第一别人编的版本未必和你的 Qt 5.9.6 是同一个 MinGW 版本第二OpenCV 3.2.0 这个版本本身对新版 GCC 兼容性一般和编译器版本不匹配运行时会冒出奇怪的崩溃或中文乱码问题。最靠谱的办法就是按照自己的 Qt 自带的 MinGW 版本从源码编译一套目录名就叫opencv3.2.0_mingw以后复用起来也清晰。2. 环境准备先统一 Qt、MinGW、OpenCV 这三者的身份2.1 Qt 5.9.6 安装时最容易漏掉的东西Qt 5.9.6 官方在线安装器里有几个组件最容易漏掉的是Qt 5.9.6 MinGW 5.3.0 32-bit和Qt 5.9.6 Tools MinGW 5.3.0。前者是编译好的一整套 Qt 库后者是配套的 GCC 编译器。很多新手只装了 Qt 库没装 Tools 目录下的编译器后面 CMake 配置时根本找不到 g。安装完成后你可以看下两个关键路径是不是存在C:\Qt\Qt5.9.6\5.9.6\mingw53_32\bin这是 Qt 库和 qmakeC:\Qt\Qt5.9.6\Tools\mingw530_32\bin这是 gcc/g 和 mingw32-make编译 OpenCV 前先打开一个 cmd 窗口把这两个路径加进 PATH再确认编译器版本set PATHC:\Qt\Qt5.9.6\Tools\mingw530_32\bin;C:\Qt\Qt5.9.6\5.9.6\mingw53_32\bin;C:\Qt\Qt5.9.6\bin;%PATH% gcc -v qmake -v这里有个容易踩的迷魂阵如果你系统里之前装过其他 mingw 或者 Dev-CppPATH 里会有多个 gcc。版本不一致编译到一半就是一堆莫名其妙的警告和错误。最好的办法是在编译用的 cmd 窗口最前面强制插入 Qt 自带的 MinGW bin确保命令提示符里看到的是gcc version 5.3.0。2.2 路径、位数和 CMake 生成器路径问题我多说两句。OpenCV 源码和编译输出目录绝对不要带中文、空格、特殊符号否则 CMake 能配置成功编译时可能找不到头文件或者生成文件路径错乱。我个人的习惯是都放盘符根目录比如源码D:\build\opencv-3.2.0构建目录D:\build\opencv-3.2.0-mingw-qt安装目录D:\opencv320_mingw还要注意位数。Qt 5.9.6 官方 MinGW 版默认提供的是 32 位库配套的 MinGW 5.3.0 也是 32 位编译器。所以 OpenCV 也必须编 32 位版本。如果你非要 64 位就得自己用 64 位 MinGW 重新构建整个 Qt这个工程量不值得建议直接用 32 位跑通除非你的图像数据量确实大到需要 64 位内存寻址。CMake 生成器我建议直接用MinGW Makefiles不要再选CodeBlocks - MinGW Makefiles或者NMake Makefiles后面会解释为什么。CMake 版本方面建议用 3.10 到 3.15 之间的版本太新的 CMake 对 OpenCV 3.2.0 的老 CMakeLists 可能会有兼容性报错没必要在工具版本上找罪受。3. CMake 配置能省的时间都在这一步3.1 核心开关逐个过一遍打开 cmake-gui源码目录选D:/build/opencv-3.2.0构建目录选D:/build/opencv-3.2.0-mingw-qt。第一次点击 Configure在弹窗里选择MinGW Makefiles指定本机编译器时选 gcc 和 g路径手动指到C:/Qt/Qt5.9.6/Tools/mingw530_32/bin/gcc.exe和g.exe。Configure 完成后下面这些选项是核心我逐个说明CMAKE_BUILD_TYPE Release CMAKE_INSTALL_PREFIX D:/opencv320_mingw WITH_QT ON WITH_OPENGL ON WITH_IPP OFF BUILD_TESTS OFF BUILD_PERF_TESTS OFF BUILD_EXAMPLES OFF BUILD_opencv_python OFF BUILD_opencv_java OFFWITH_QTON是让 OpenCV 的 highgui 模块使用 Qt 作为后端这样cv::imshow弹出来的窗口内嵌在 Qt 事件循环里。WITH_OPENGLON是配合 Qt 显示加速的但也不是非开不可有些版本不开会在编译时提示缺 GL 库建议直接打开。WITH_IPPOFF必须设IPP 只有 MSVC 版本的预编译库MinGW 下开着会导致编译失败。时比较容易被忽略的是CMAKE_PREFIX_PATH它得指向 Qt 库的根目录CMAKE_PREFIX_PATH C:/Qt/Qt5.9.6/5.9.6/mingw53_32如果不设CMake 可能找不到 Qt5 的配置脚本最后在日志里看到Could NOT find Qt5整个WITH_QT就白设了。检查时可以在 CMake 输出里搜索Qt5看到Found Qt5: ...才算接上。3.2 编译前最后的检查Configure 成功一次后还要再点一次 Configure 让所有缓存生效然后再点 Generate。Generate 完成后打开D:/build/opencv-3.2.0-mingw-qt/CMakeCache.txt用记事本搜几个关键变量确认没有残留的 MSVC 配置。比如CMAKE_CXX_COMPILER:FILEPATH应该指向g.exe不是cl.exe。如果之前电脑装过 VSCMake 有可能会自动检索到 MSVC导致生成器变成 VS 工程这一步一定要看。还有一个小细节OpenCV 3.2.0 的源码里有些第三方库和 C11 标准存在兼容性问题。MinGW 5.3.0 默认支持 C11但编译 OpenCV 时如果遇到比较诡异的模板报错可以在 CMAKE_CXX_FLAGS 里手动加上-stdc11。大部分情况下默认设置都能过这里只是留一个兜底方案。一切就绪后不要急着 Generate 完就关在 CMake 界面里把OPENCV_ENABLE_NONFREE也可以顺便打开如果后面要做 SIFT/SURF能省不少事。4. 编译、安装与实际踩坑4.1 一条命令引发的血案从 nmake 到 mingw32-make很多人玩 Linux 习惯了在 Windows 上会顺手敲make结果提示找不到。MinGW 自带的 make 命令叫mingw32-make你在 Qt 自带的 MinGW bin 目录里找不到make.exe而是有mingw32-make.exe。所以编译命令是cd /d D:\build\opencv-3.2.0-mingw-qt mingw32-make -j4-j4是并行编译根据 CPU 核数调整。我是在一台四核机器上编的全模块大概跑了二十分钟左右。如果编译中途崩了别急着重来先看终端最后几行的错误信息。常见原因是内存不够可以降到-j2再试。这里也顺手解释下刚才为什么生成器选MinGW Makefiles而不是NMake Makefiles。NMake 是微软的 make 工具配套 MSVCMinGW Makefiles 则是让 CMake 生成适合mingw32-make的 Makefile。两者混着用要么编译命令不对要么链接参数完全不通。4.2 链接阶段的符号问题我第一次编 OpenCV 3.2.0 Qt 5.9.6 时卡在链接阶段出现大量undefined reference to __imp_...。排查了几轮最后定位到是CMAKE_PREFIX_PATH没指对CMake 找到了系统里另一个 Qt 版本。因此出现这种问题时先看 CMakeCache 里的 Qt5_DIR 路径一定指向C:/Qt/Qt5.9.6/5.9.6/mingw53_32/lib/cmake/Qt5才对。还有一种链接错误和你自己的工程有关。OpenCV 3.2.0 编译出来的导入库文件在lib目录下文件名类似libopencv_core320.dll.a、libopencv_imgproc320.dll.a。在 qmake 工程里写 LIBS 时用-lopencv_core320千万不要把lib前缀和.dll.a后缀都写进去。如果你看到-lopencv_world相关的链接错误多半是开了BUILD_opencv_world这个选项把全部模块合并成一个库顺序问题和依赖问题反而更多建议保持默认多库模式。4.3 install 之后的目录到底是什么样编译成功不代表能用还要执行安装步骤mingw32-make install安装完成后D:/opencv320_mingw下会有三个最重要的目录include所有头文件libMinGW 导入库*.dll.abin运行时需要的所有 OpenCV DLL我把这个目录戏称为“自产自销版 OpenCV”以后写 Qt 工程的时候INCLUDEPATH 和 LIBS 都指向这里就可以了。需要特别注意的是bin目录里的 DLL 数量很多发布程序给别人时不是只拷一个 exe 就能跑必须把用到的 OpenCV DLL 一并带上。5. Qt 工程集成验证不会写 CMake 也照用5.1 pro 文件与库链接如果你用的是 Qt Creator完全没必要去写 CMakeLists直接继续用 qmake 工程.pro文件简单直接。假设 OpenCV 安装在D:/opencv320_mingw那.pro文件里这样写QT core gui widgets CONFIG c11 TARGET QtOpenCVTest TEMPLATE app OPENCV_DIR D:/opencv320_mingw INCLUDEPATH $${OPENCV_DIR}/include LIBS -L$${OPENCV_DIR}/lib \ -lopencv_core320 \ -lopencv_imgproc320 \ -lopencv_imgcodecs320 \ -lopencv_highgui320 \ -lopencv_videoio320如果你只是做图像处理不涉及视频和摄像头可以去掉videoio。但imgcodecs必须要imread、imwrite都由它提供。如果同时用了highgui它依赖imgcodecs和videoio这时候链接顺序也需要注意MinGW 的 ld 对库顺序敏感被依赖的库要放在后面上面这个顺序通常没问题。如果遇到莫名其妙的未定义符号可以把所有-lopencv_*320用-Wl,--start-group和-Wl,--end-group包起来强制链接器循环查找。5.2 一个能打开图像的程序下面这个 Demo 用QFileDialog选择一张图片再用 OpenCV 读取并转成 RGB最后通过 QLabel 显示。代码不长但把“Qt 弹窗选文件”和“OpenCV 图像处理”串起来了。#include QApplication #include QLabel #include QFileDialog #include QPixmap #include QImage #include opencv2/opencv.hpp int main(int argc, char *argv[]) { QApplication app(argc, argv); QString filePath QFileDialog::getOpenFileName( nullptr, 选择图片, ., Images (*.png *.jpg *.bmp)); if (filePath.isEmpty()) return 0; cv::Mat src cv::imread(filePath.toLocal8Bit().toStdString()); if (src.empty()) return 0; cv::Mat rgb; cv::cvtColor(src, rgb, cv::COLOR_BGR2RGB); QImage qimg(rgb.data, rgb.cols, rgb.rows, rgb.step, QImage::Format_RGB888); QLabel label; label.setPixmap(QPixmap::fromImage(qimg.copy())); label.resize(qimg.width(), qimg.height()); label.show(); return app.exec(); }注意一定要做BGR - RGB转换OpenCV 默认读图是 BGR 通道顺序Qt 的 QImage 用 RGB不转换的话画面里红色和蓝色会颠倒。QImage 构造时传了rgb.step这是为了处理图像行尾可能存在的填充字节不传在某些尺寸下会出花屏。setPixmap 用的qimg.copy()也是为了避免原图数据失效后悬空指针的问题。5.3 发布时别漏了这些 DLL程序能跑起来后发布又是一个坑。Qt Creator 默认把可执行文件生成在 build 目录下直接双击运行可能提示找不到 Qt 相关 DLL。解决办法是 Qt 自带的部署工具windeployqt.exe。在 cmd 里进入 Qt 的 bin 目录cd /d C:\Qt\Qt5.9.6\5.9.6\mingw53_32\bin windeployqt.exe D:\build\QtOpenCVTest\debug\QtOpenCVTest.exe这会自动把 Qt 运行库、platforms 插件、imageformats 插件复制到 exe 所在目录。之后再手动把D:\opencv320_mingw\bin里用到的opencv_core320.dll、opencv_imgproc320.dll、opencv_imgcodecs320.dll、opencv_highgui320.dll复制过去。如果 exe 和 OpenCV DLL 不在同一目录就必须把D:\opencv320_mingw\bin加入系统 PATH。我的习惯是所有 DLL 都堆在 exe 同目录下短小直接避免客户机器上 PATH 环境变量混乱。另外如果运行时报“entry point not found”或者“无法定位程序输入点”之类的话多半是 MinGW 运行时版本不一致比如编 OpenCV 用的 gcc 5.3.0运行程序却用了系统 PATH 里更新的 libstdc-6.dll。把 Qt 自带的 mingw530_32 bin 目录放在 PATH 最前面基本能避免。这套流程走完openCV 3.2.0 MinGW Qt 5.9.6 的坑我也算踩了个遍。最核心的一条经验凡是涉及混合编译先花半小时把工具链版本对齐比后面改十个小时代码都值。另外如果你编译时想节省时间可以只编opencv_core、opencv_imgproc、opencv_imgcodecs这几个模块在 CMake 里把BUILD_LIST设为core,imgproc,imgcodecs,highgui,videoio能快很多。后面我又把这套环境用来接摄像头和做简单滤波稳定得很。本文还有配套的精品资源点击获取
返回列表