简介:这是一份由Qt6.2.2与OpenCV4.5.5在MinGW环境下编译生成的OpenCV库文件包,面向Windows下使用Qt Creator进行图像处理、计算机视觉开发的工程师与研究者。包内集成了已编译库文件和配套依赖,可在Qt项目中直接链接调用,省去自行配置CMake与编译源码的过程,也降低了MinGW下依赖和链接器设置难度。资源包共12280个文件、约308.46MB,以cpp/obj/d/hpp/h等源码、头文件和cmake配置脚本为主,并含大量png/jpg示例图片及python工具脚本,便于查看实现和测试用例。已有1102人学习/下载,适合需要快速搭建Qt+OpenCV环境的开发者,可借助构建产物理解OpenCV模块组织方式,减少编译配置中的常见排错成本。
1. 为什么要自己编译:官方预编译库与Qt6的兼容性问题
如果你正在用Qt 6.2.2做Windows桌面开发,大概率会遇到这个问题:打开OpenCV官网,下载了最新的Windows版本,一编译报一堆错;或者明明编译过了,运行时一闪就没了,调试器里全是“未找到opencv_world450.dll”这类提示。更常见的是链接阶段直接报一堆无法解析的外部符号,比如找不到cv::Mat的构造函数。
老实说,很多刚开始碰Qt+OpenCV的人都会卡在这一步,因为在Windows上,事情和Linux下完全不一样。Linux下用系统的g++配合OpenCV,基本就是apt install libopencv-dev然后g++ main.cpp \pkg-config --cflags --libs opencv4``就完事了,但Windows下的OpenCV官方预编译包,默认是用MSVC编译的。这意味着你如果用MinGW工具链(也就是Qt 6.2.2自带的那个编译器),去链接MSVC编译出来的库文件,结果通常是“链接失败”或者“二进制不兼容”。这里面最核心的问题在于两个编译器生成的COFF目标文件格式、运行时库和符号修饰规则不一样,所以没有第三个选择,只能重新编译一份MinGW版本的OpenCV。
这篇我详细记录一下我在Windows 10环境下,用Qt 6.2.2内置的MinGW 11.2.0工具链,从源码编译OpenCV 4.5.5的完整过程,其中包括CMake配置阶段的关键参数、编译阶段的踩坑备忘,以及编译完之后如何在Qt工程里正确使用这套库。整个过程踩了不少坑,有些坑真的能把人搞到崩溃,我把关键点都整理出来了。
2. 环境准备与版本匹配:最容易翻车的环节
2.1 完整环境清单
先说我的环境,这一步的重要性怎么强调都不过分。很多人在编译失败之后反复折腾CMake参数,但根本问题是版本之间串了,或者工具链路径错了。
我这边的最终可用版本组合如下:
- 操作系统:Windows 10 专业版 64位
- Qt版本:6.2.2(在线安装包安装,安装时勾选了MinGW 11.2.0工具链组件)
- 编译器:GCC 11.2.0(MinGW-w64 / x86_64)
- CMake版本:3.22.3
- OpenCV版本:4.5.5源码包
- 构建工具:MinGW自带的mingw32-make
注意:这里有一个非常容易踩的坑——Qt安装时自带的MinGW版本是11.2.0(具体看你装的组件),而很多人电脑上可能以前装过Code::Blocks或者Dev-Cpp,里面带着一个很老的MinGW 8.1.0。如果PATH环境变量里同时存在这两个版本,CMake在探测编译器时可能随机选到老版本,导致编译失败。建议把Qt安装目录下的MinGW路径(类似
D:\Qt\Tools\mingw1120_64\bin)提到PATH的最前面。
2.2 源码与目录规划:一个容易被忽略的坑
OpenCV源码下载的时候,我建议大家去GitHub的tags页面下载,不要用GitHub的自动打包ZIP,也不要下载那些看起来奇怪的分支版本。我用的地址是:
https://github.com/opencv/opencv/releases/tag/4.5.5下载Source code(zip或tar.gz都行),解压之后我的目录结构是这样组织的:
D:\opencv\ ├─ sources\ │ ├─ modules\ │ ├─ CMakeLists.txt │ └─ ... ├─ build-qt\ │ ├─ CMakeCache.txt │ └─ ... └─ install\ ├─ include\ ├─ x64\mingw\bin ├─ x64\mingw\lib └─ ...这里有个很重要的原则:源码目录和构建目录必须分离,也就是out-of-source构建。这一点在官方文档里也反复强调。有人为了省事直接在源码目录里执行CMake,结果第一次配置失败后再想清干净就非常麻烦,各种CMakeCache、CMakeFiles残留目录会干扰后续配置。我一开始就是因为这个折腾了一个晚上,后面养成了“构建目录一旦乱了就直接删掉重建”的坏习惯,反而省心。
3. CMake配置的逐项拆解:每个参数都值得花时间
3.1 第一次按“常规套路”配置的结果
初次尝试时,可能很多人会按照以前Linux下编译的套路,直接在CMake GUI里选一下源码路径,然后Generate。但这里有个关键步骤:CMake第一次Configure之前,需要显式指定Qt的路径。如果不指定,CMake只会检测到Qt的Core组件缺失,然后自动把WITH_QT选项关闭,接下来编译出的OpenCV的highgui模块就会退化成用Win32窗口,无法跟Qt的Gui模块对接。
我第一次遇到的情况是:CMake配置阶段没有报错,生成的时候也没问题,但是一编译就报winrt相关错误或者highgui缺东西。原因就是WITH_QT被自动关掉了,然后highgui用了很老的cv::namedWindow实现,而我自己在Qt工程里写的是cv::imshow,链接时自然就缺符号了。
3.2 关键选项说明与完整命令行
在CMake GUI里操作也可以,但我个人更推荐用命令行方式,尤其是后面需要反复清理配置时,命令行历史的可复现性更高。以下是我确认可用的配置命令:
cd D:\opencv\build-qt cmake D:\opencv\sources -G "MinGW Makefiles" ^ -DCMAKE_BUILD_TYPE=Release ^ -DCMAKE_MAKE_PROGRAM=D:/Qt/Tools/mingw1120_64/bin/mingw32-make.exe ^ -DCMAKE_C_COMPILER=D:/Qt/Tools/mingw1120_64/bin/gcc.exe ^ -DCMAKE_CXX_COMPILER=D:/Qt/Tools/mingw1120_64/bin/g++.exe ^ -DCMAKE_PREFIX_PATH=D:/Qt/6.2.2/mingw_64 ^ -DWITH_QT=ON ^ -DWITH_OPENGL=ON ^ -DWITH_OPENCL=OFF ^ -DBUILD_opencv_world=ON ^ -DCMAKE_INSTALL_PREFIX=D:/opencv/install这套参数里有几个值得单独说:
-DCMAKE_MAKE_PROGRAM:如果不显式设置,CMake可能去PATH里找mingw32-make,找到的可能是老版本的,导致编译过程中报各种奇怪的语法错误。-DWITH_OPENCL=OFF:我关闭了OpenCL,因为MinGW版本的OpenCL头文件和库有些时候会出问题,而且桌面应用场景下CPU处理就够了,没必要引入GPU调度的复杂度。当然如果你后面要用CUDA,那就另说了。-DBUILD_opencv_world=ON:这个选项会把所有模块编成一个统一的动态库opencv_world455.dll和对应的导入库。这样可以大大简化后期的链接配置,不用在CMakeLists里列一堆opencv_core、opencv_imgproc、opencv_highgui了。缺点是库文件会比较大,但个人开发用完全没问题。
还有一个选项是-DWITH_CUDA,这个默认是OFF的,我这边没有NVIDIA显卡,所以压根没考虑。如果你有CUDA环境,并且需要GPU加速,建议单独研究OpenCV的CUDA模块编译,那个复杂度比现在这个要高不少,不建议新手一上来就碰。
重要:如果你之前安装过Qt 5.x,并且环境变量里设置了QT_DIR或者CMAKE_PREFIX_PATH指向Qt 5,在配置Qt 6.2.2时必须把这些环境变量清掉,否则CMake会优先找到Qt 5的模块,然后在编译阶段报
Qt5 not found或者各种版本相关的编译错误。
3.3 Configure和Generate阶段应该看到的结果
配置完成后,CMake输出里会有一行类似这样的摘要信息:
GUI: QT: YES (Qt6 Core GUI Widgets) Win32 UI: YES OpenGL support: YES (QT6)只有看到QT对应的是YES,并且后面括号里是Qt6,才可以放心进入下一步。如果这里显示的是NO或者Qt5,那趁早重新配置,不要抱有侥幸心理。
在摘要里还需要检查一下:
Media I/O: JPEG: YES PNG: YES TIFF: YES WEBP: YES OpenEXR: NO GDAL: NO这里JPEG/PNG/TIFF一般会编译内置的第三方库,所以显示YES很正常。如果某个显示NO,也不是致命问题,只是对应格式的图片无法读写。我的经验是,如果只是日常图像处理和Qt界面显示,不全装这些编解码器影响不大,而且省编译时间。
4. 编译过程中的坑点与提速建议
4.1 编译很慢,怎么处理
OpenCV 4.5.5的源码量不小,全模块编译的话,在普通配置的电脑上大概需要40分钟到1个小时。我这边是八代i5处理器,16G内存,用-j8参数并行编译,大概花了40分钟左右。如果你电脑配置一般,建议不要贪多,用-j4或者干脆用cmake自带的并行参数:
cmake --build . --config Release -j 8或者直接:
mingw32-make -j8第一次编译时,最好打开终端窗口盯着,因为有些错误提示刷新很快,一闪而过你可能根本不知道哪里出了问题。我有一次编译到90%的时候报错,就是因为某个源代码文件里用了std::filesystem,而MinGW的某些版本对文件系统库的支持不完整。解决办法是升级工具链,或者加编译选项。不过4.5.5版本在GCC 11.2.0下编译还挺顺利,没有遇到这个问题,如果你用旧版本的MinGW,可能就会在这里卡住。
4.2 常见编译错误一览
我把编译过程中遇到过的两个典型错误记录下来,供参考:
错误一:找不到windows.h或者winbase.h
这个通常是因为MinGW没有进入CMake的搜索路径,或者是构建目录是从之前MSVC版本残留复制的。解决办法:删除build目录,重新按上面的命令行配置一次,确保CMAKE_C_COMPILER和CMAKE_CXX_COMPILER都指向Qt自带的MinGW路径。
错误二:编译某模块时报undefined reference to __imp_...
这个一般是链接阶段的问题。多数情况下是因为某些库文件还没编译出来,进程就提前结束了,或者动态库导出符号表不完整。碰到这种情况,先确认编译是否真的全部完成(最后一行有没有出现Linking CXX shared library的提示),如果报错发生在某几个特定模块且伴随乱码的DLL,我建议把build文件删除重来——多试几次,有时候就是配置缓存串了。
4.3 编译产出物在哪里
编译完成之后,要记得执行安装步骤,把所有头文件和库文件收集到统一目录。这一步很多人会忽略,直接跑到build/lib目录里去找库,但其实OpenCV提供了install目标,可以把文件整理得更规范:
mingw32-make install或者:
cmake --build . --target install --config Release安装完成后,D:/opencv/install目录下的结构大致是:
D:\opencv\install\ ├─ include\opencv2\... ├─ x64\mingw\bin\opencv_world455.dll ├─ x64\mingw\lib\libopencv_world455.dll.a └─ ...注意:这里生成的是libopencv_world455.dll.a,这是MinGW格式的导入库,而不是MSVC的.lib文件。如果你拿到的是.lib且不带.dll.a后缀,那说明你用的编译工具链不对,回到第3节重新走一遍。
5. 在Qt 6.2.2工程中接入这套OpenCV库
5.1 CMakeLists.txt的配置模板
编译好库之后,怎么在Qt Creator里用起来,是另一个大坑。Qt 6.2.2创建的默认工程是用CMake管理的,而不是qmake。如果你还在用qmake的.pro文件,建议尽早迁移到CMake,因为Qt 6对CMake的支持已经非常完善,而且OpenCV本身也提供CMake配置文件,可以更优雅地接入。
下面是我在项目里实际使用的CMakeLists.txt片段:
cmake_minimum_required(VERSION 3.16) project(MyOpenCVApp VERSION 0.1 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # OpenCV 路径 set(OpenCV_DIR "D:/opencv/install/x64/mingw/lib/cmake/opencv4") find_package(OpenCV REQUIRED) # Qt6 find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) qt_standard_project_setup() qt_add_executable(MyOpenCVApp main.cpp mainwindow.cpp mainwindow.h ) target_include_directories(MyOpenCVApp PRIVATE ${OpenCV_INCLUDE_DIRS} ) target_link_libraries(MyOpenCVApp PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets ${OpenCV_LIBS} )这段配置里最关键的是那一行set(OpenCV_DIR ...)。因为OpenCV安装时生成的OpenCVConfig.cmake文件所在路径不是常规的/lib/cmake/opencv4,如果你不确定路径,可以安装后在D:\opencv\install目录下搜索OpenCVConfig.cmake,把它的父目录填进去。
5.2 运行时要设置的PATH
C++编译链接阶段的错误解决了,还有运行时的动态库加载问题。很多人在Qt Creator里点运行,程序起来后立刻弹窗说缺DLL,其中最常见的就是opencv_world455.dll不在搜索路径里。
解决办法有几种:
- 把
D:/opencv/install/x64/mingw/bin加入系统PATH环境变量后重启Qt Creator; - 在Qt Creator的运行环境设置里添加PATH条目;
- 更省事的办法:把
opencv_world455.dll直接复制到生成的exe同级目录。
我个人推荐第三种,因为打包分发时反正也要复制DLL,提前养成这个习惯比较好。
Qt 6还有一个细节:它在运行时依赖的DLL也都在D:/Qt/6.2.2/mingw_64/bin目录下,如果你之前没设置过Qt的环境变量,在部署到别的机器上时可能会导致找不到Qt6Widgets.dll。用Qt自带的windeployqt工具可以自动收集这些依赖,不过我一般是在CMake里直接把这个工具作为post-build步骤来调用,省得手动跑。
5.3 验证代码:能不能显示一张图
接入成功之后写个最简单的代码验证即可:
#include <QApplication> #include <QLabel> #include <opencv2/opencv.hpp> int main(int argc, char *argv[]) { QApplication app(argc, argv); cv::Mat image = cv::imread("test.jpg"); if (image.empty()) { return -1; } cv::cvtColor(image, image, cv::COLOR_BGR2RGB); QImage qimg(image.data, image.cols, image.rows, image.step, QImage::Format_RGB888); QPixmap pixmap = QPixmap::fromImage(qimg); QLabel label; label.setPixmap(pixmap); label.show(); return app.exec(); }这段代码里有个细节值得多说一句:OpenCV读取图像默认是BGR通道顺序,而Qt的QImage使用RGB,所以显示之前一定要cvtColor转换一次,否则颜色偏蓝偏红。这是新手最容易忽略的地方。
6. 一些容易反复踩的细节与最终建议
6.1 关于MinGW和MSVC的抉择
如果你不是对MinGW有特殊偏好,或者你的项目必须依赖某些只有MSVC版本的第三方库,我建议还是用MSVC方案——直接用Visual Studio安装MSVC工具链,然后去OpenCV官网下载官方预编译的Windows版本,配起来确实省心。但如果你和我一样,主力IDE是Qt Creator,就老老实实用MinGW编译。
在Qt 6时代,MinGW和MSVC两者编译出来的程序性能差异已经很小了,况且日常桌面应用瓶颈主要在界面渲染和I/O,不在单纯的计算循环。所以不用太纠结编译器之间的性能差距,重点是保证整个工具链的一致性。
6.2 是否需要开启world模块
我前面强调了-DBUILD_opencv_world=ON,但还是要说一个它的代价:编译时间变长,生成的DLL体积大概在100MB以上。如果你的硬盘空间很紧张,或者你只需要core、imgproc、highgui这三个模块,可以指定只编译这几个模块,这样能节省不少时间。
不过对我个人来说,world模块带来的便利是实打实的:链接的时候一行opencv_world就够,不需要在CMakeLists里堆一堆库名,也不会因为少写一个组件导致链接失败。而且随着你后续用到calib3d、objdetect、video等更多功能,world模块的好处就更明显了。
6.3 编译失败后的心理建设和排查顺序
编译失败不可怕,可怕的是在错误的配置上反复重试。我总结了一套排查顺序,基本能解决90%的问题:
- 清理build目录(不是改几个CMake参数,而是整个删除重新配置);
- 确认CMake输出摘要中QT、OpenGL均为YES;
- 确认编译器路径确实是Qt自带的MinGW,而不是PATH里其他版本;
- 确认Windows系统PATH里没有残留的旧版libopencv库路径,否则运行时可能加载错误版本的DLL;
- 如果报错信息里有MSVC相关字样,检查是不是构建目录被之前的MSVC配置污染了。
这套顺序看起来很基础,但就是这些基础环节,让我在第一次编译时浪费了一整天。
6.4 关于后续升级
Qt和OpenCV的版本更新很快,以后想升级OpenCV版本时,建议一并升级Qt工具链到对应版本。比如Qt 6.2.2内置的MinGW是11.2.0,升级到Qt 6.4时内置的MinGW可能变成13.x,这时候用旧的编译配置可能遇到新的兼容性问题。最好的做法是“升级Qt后重新编译OpenCV”,不要试图把老版本的库文件直接拷贝到新环境里用。
文章写到这里,主要的内容基本都覆盖了。这套方案我自己用了几个月,目前没再出过大问题,希望对正在折腾Qt+OpenCV的朋友们有所帮助。如果编译过程中遇到另外的坑,也欢迎一起交流,毕竟工具链这种问题,很多时候就是“一个人卡一周,两个人五分钟”。
本文还有配套的精品资源,点击获取