资讯动态

Windows 下 Qt 配置 OpenCV:官方预编译包跑通图像显示

发布时间:2026/9/30 3:43:40 来源:尧图企业网站定制
Windows 上给 Qt 配 OpenCV十个新手里有八个卡在同一件事上要么翻到一篇三小时的源码编译教程跟着敲到 CMake 配置那一半就报错退出要么抄了别人的.pro配置编译侥幸过了链接阶段炸出一屏 LNK2019。这篇东西只讲一条路——直接拿 OpenCV 官方预编译包不自己编译在 Qt 里跑通第一个能读图、处理、在窗口里显示的完整程序。核心关键词就三个Windows、Qt、OpenCV 配置。适合刚学完 Qt 控件、想在 GUI 里做图像处理的人也适合被源码编译折磨过一轮、想找个省事方案的老手。下面所有步骤我都实际跑过包含每一处为什么会这样配的理由以及一份能直接对着查的报错速查表。1. 别急着编译先把方案选型这件事说清楚很多人一搜Qt OpenCV 配置出来排在前面的都是源码编译教程于是默认配置 编译。这是最大的认知误区。配置的本质是让编译器和链接器找到头文件与库文件编译 OpenCV 本身只是获取这些文件的一种方式而且是最费事的那一种。1.1 自己编译 OpenCV 到底会卡在哪几步我不是说编译没用。你要用opencv_contrib里的扩展模块比如 SIFT 进主仓库之前的版本、人脸识别的face模块、文本检测text模块或者要给 OpenCV 打开 CUDA 加速那确实得自己编。但如果你只是想用imread、cvtColor、threshold、Canny、findContours这些基础能力编译就是纯粹的时间黑洞。实际的卡点通常集中在这几处。第一是 CMake 配置界面里几百个选项BUILD_opencv_world要不要开、WITH_IPP要不要留、OPENCV_EXTRA_MODULES_PATH怎么填每个填错一次就是一轮重来。第二是编译过程中的外部依赖下载ippicv、ffmpeg、protobuf这些资源包会在配置阶段尝试拉取网络稍差就是漫长的等待甚至超时中断报错信息还特别不友好。第三是编译本身的耗时与磁盘占用一台普通笔记本全量编译一次 OpenCV 加上contrib三四十分钟起步中间生成的中间文件能吃掉十几个 G。第四也是最烦的你辛辛苦苦编出来的东西一旦换电脑、换 Qt 版本、换编译器基本要重来一遍。官方预编译包恰好把这四件事全部绕开。它是 OpenCV 团队用 MSVC 编好的成品解压即用几百兆空间零等待而且版本对应关系写得清清楚楚。1.2 官方预编译包长什么样怎么选版本从 OpenCV 官网的 Releases 页面下载 Windows 版自解压包文件名形如opencv-4.8.0-windows.exe。双击它会解压出一个opencv文件夹结构大致如下opencv/ ├── build/ │ ├── include/ - 所有头文件都在这 │ │ └── opencv2/ │ │ ├── core.hpp │ │ ├── imgproc.hpp │ │ ├── opencv.hpp - 总入口最常用 │ │ └── ... │ └── x64/ │ └── vc16/ - 编译器代号目录 │ ├── bin/ - 运行时 DLL │ ├── lib/ - 链接用 .lib CMake 配置文件 │ └── staticlib/ └── sources/ - 源码不编译的话用不上选版本的关键在两个地方OpenCV 主版本以及x64/vcXX里的那个vcXX。华语技术社区里常见的一个坑是有人装完发现自己的x64目录下只有vc14和vc15没有vc16就以为下载包损坏了。其实不是是版本对应关系不同。OpenCV 版本x64 下提供的 vc 目录建议搭配的编译器说明4.5.5 及更早vc14、vc15VS2015 / VS2017与 Qt 5.14 的 MSVC2017 套件最匹配4.6.0 - 4.10.xvc16VS2019 / VS2022Qt 6.x 的 MSVC2019 套件首选4.11 及之后vc16VS2019 / VS2022结构不变库文件名跟着版本号变这里有个容易疏忽的点库文件名里的数字跟着主次版本走。4.8.0 就是opencv_world480.lib4.10.0 是opencv_world4100.libDebug 版在末尾多加一个d即opencv_world480d.lib。你升级一次 OpenCV所有引用这些名字的地方都得改这是后面版本升级一节要专门处理的问题。1.3 MSVC 还是 MinGW这是第一个也是最大的坑我必须把这件事单独拎出来讲因为它每年都在坑人。Qt 在 Windows 上提供两套编译器套件MSVC 和 MinGW。OpenCV 官方预编译包只提供 MSVC 版本因为它就是用 MSVC 编的。MSVC 和 MinGWGCC在 Windows 上生成的二进制接口不兼容。这意味着如果你装的是 Qt 的 MinGW 套件然后拿着 OpenCV 的.lib去链接结果一定是undefined reference一连串或者干脆在链接阶段报找不到库。搜索热词里那个unknown module(s) in qt: serialport和这个属于同一类问题——套件本身少组件或者选错了。所以选型决策只有两条路路线 A推荐装 Qt 的时候勾上 MSVC 套件用 MSVC 编译你的工程直接配官方预编译包。全程十分钟。路线 B你已经在 MinGW 上写了大量代码不想迁移那就只能自己用 MinGW 编译 OpenCV。这时候 CMake 的生成器要选MinGW Makefiles编译器指定成 Qt 自带的gcc.exe和g.exe编出来的库才能和你的 Qt 工程对上。对绝大多数新手毫不犹豫选路线 A。选错套件带来的时间损失比你想象的大得多。2. 三件套准备Qt、OpenCV、编译器方案定了接下来是把三样东西装好、放好、验好。这一步做扎实后面写配置就是照抄。2.1 Qt 安装组件勾选别乱点用 Qt 官方的在线安装器登录账号后在组件选择页只勾选你真正要用的东西。我的建议是这样Qt下的Qt 5.15.x或Qt 6.5.x展开后勾选MSVC 2019 64-bit。如果你用的是 Qt 5.14/5.15 的旧安装包对应的是MSVC 2017 64-bit。Developer and Designer Tools下勾选MinGW如果你还想要一个备用套件和Qt Creator。顺手把CMake和Ninja一起勾上它们随安装器一起装比你自己去官网下省事。关于 Qt 版本的选择我个人的偏好是纯新手、跟着老教程走用 Qt 5.15 会更顺社区里的示例代码绝大多数是 Qt 5 语法如果是新项目、想用 Qt 6 的新特性那就上 Qt 6.5 以上但要注意 Qt 6 默认走 CMake.pro虽然还能用但已经不是推荐路径了。注意安装路径不要带中文、不要带空格。D:\Qt可以D:\我的软件\Qt不行。Qt Creator 本身能忍但后面 CMake 和部分第三方脚本会出各种莫名其妙的路径解析错误。2.2 OpenCV 预编译包下载与解压位置下载opencv-4.8.0-windows.exe之后双击解压。它会问你要解压到哪这里有个小陷阱这个自解压包会在你选择的目录下再建一层opencv文件夹。所以如果你填D:\dev最终得到的是D:\dev\opencv\build\...。很多人填D:\dev\opencv结果变成D:\dev\opencv\opencv\build\...路径白套一层后面写配置的时候对不上。我的做法是固定在D:\dev解压最终路径就定为D:\dev\opencv\build\include D:\dev\opencv\build\x64\vc16\bin D:\dev\opencv\build\x64\vc16\lib解压完之后先去这三个目录各看一眼确认文件真的在。特别是lib目录里面应该有opencv_world480.lib、opencv_world480d.lib以及OpenCVConfig.cmake、OpenCVConfig-version.cmake这两个文件。后面用 CMake 的话就靠它们自动找路径。2.3 环境变量与五分钟验证在写任何 Qt 代码之前先用一个最朴素的命令行程序验证 OpenCV 本身能跑。这步的意义在于把问题隔离如果这一步都过不去那问题一定在 OpenCV 或环境变量跟 Qt 一点关系都没有不用在 Qt Creator 里瞎折腾。先配环境变量。把D:\dev\opencv\build\x64\vc16\bin加进系统Path这样运行时能找到 DLL。注意是bin不是lib加错目录是最常见的低级失误。然后用 Qt Creator 新建一个纯 C 的Plain C Application工程不要 Widgets或者干脆用 MSVC 命令行写这么一段#include opencv2/opencv.hpp #include iostream int main() { std::cout OpenCV version: cv::getVersionString() std::endl; // 打印构建配置能看到编译器、并行框架、GUI 后端等信息 std::cout cv::getBuildInformation() std::endl; cv::Mat m cv::Mat::zeros(3, 3, CV_8UC1); std::cout Mat created, size m.size() std::endl; return 0; }编译运行如果能看到版本号输出、getBuildInformation()打印出一大段配置信息说明 OpenCV 本体没问题。这个getBuildInformation()特别有用它会告诉你这个包是用什么编译器编的、有没有开 IPP、有没有开 OpenMP。当你遇到为什么我的程序跑得比别人慢这类问题时第一件事就是看这段输出。3. 工程配置qmake 与 CMake 两种写法到这一步真正的配置才开始。Qt 5 时代用.pro文件Qt 6 时代推荐 CMake。两种我都给你写全并且逐行解释为什么这么写。3.1 qmake 工程.pro 逐行拆解在 Qt Creator 里新建Qt Widgets Application打开生成的.pro文件在末尾追加下面这段# ---------- OpenCV 配置开始 ---------- # 用正斜杠qmake 在 Windows 上也能正确识别反斜杠反而容易被当转义符 OPENCV_DIR D:/dev/opencv/build # 头文件目录必须指到 build/include不能指到 build/include/opencv2 INCLUDEPATH $$OPENCV_DIR/include # 库目录 库文件用 vc16 对应 VS2019/2022 win32 { CONFIG(debug, debug|release) { # Debug 构建链接带 d 后缀的库 LIBS -L$$OPENCV_DIR/x64/vc16/lib -lopencv_world480d } else { # Release 构建链接不带 d 后缀的库 LIBS -L$$OPENCV_DIR/x64/vc16/lib -lopencv_world480 } } # ---------- OpenCV 配置结束 ----------几处必须讲清楚的原因第一INCLUDEPATH指向build/include而不是build/include/opencv2。因为 OpenCV 的头文件内部是用#include opencv2/core.hpp这种带子目录前缀的方式互相引用的如果你把 INCLUDEPATH 指到了opencv2这一层那opencv2/core.hpp就会被解析成opencv2/opencv2/core.hpp直接报 C1083 找不到文件。第二-L和-l是两个参数前者给目录后者给库名。qmake 里库名要写全-lopencv_world480会去找opencv_world480.libMSVC或libopencv_world480.aMinGW。写全名不要加lib前缀和扩展名。第三Debug/Release 分支必须严格分开。OpenCV 的 Debug 库和 Release 库是两个完全不同的二进制混链的后果是编译通过、运行时在某个不确定的地方崩溃或者报LNK2038: mismatch detected for _ITERATOR_DEBUG_LEVEL。这个错误特别隐蔽因为它可能在你调用某个不常用的函数时才触发。注意如果你在.pro里改了OPENCV_DIR记得在 Qt Creator 里执行一次构建 → 执行 qmake光点重新构建有时候不会重新解析.pro文件。3.2 CMake 工程Qt 6 下更推荐的写法Qt 6 新建工程默认生成CMakeLists.txt。CMake 的好处是它能通过OpenCVConfig.cmake自动推导出头文件和库路径你不用手动写INCLUDEPATH换电脑的时候只需要改一个变量。cmake_minimum_required(VERSION 3.16) project(QtOpenCvDemo LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) # 关键必须在 find_package 之前指定 OpenCV_DIR # 它指向 lib 目录OpenCVConfig.cmake 就在那里不是 build 根目录 set(OpenCV_DIR D:/dev/opencv/build/x64/vc16/lib) find_package(Qt6 REQUIRED COMPONENTS Widgets) find_package(OpenCV REQUIRED) qt_add_executable(QtOpenCvDemo main.cpp) target_include_directories(QtOpenCvDemo PRIVATE ${OpenCV_INCLUDE_DIRS}) target_link_libraries(QtOpenCvDemo PRIVATE Qt6::Widgets ${OpenCV_LIBS})这里最容易错的是OpenCV_DIR的位置。它不是 OpenCV 的根目录也不是build目录而是存放OpenCVConfig.cmake的那个lib目录。如果你指错了find_package会报Could not find a package configuration file provided by OpenCV并且顺手给你一段看起来很有道理但完全没用处的提示。另外set(OpenCV_DIR ...)必须写在find_package(OpenCV REQUIRED)之前顺序反了同样找不到。还有一个替代做法不改CMakeLists.txt而是在 Qt Creator 的构建配置里给 CMake 参数加上-DOpenCV_DIRD:/dev/opencv/build/x64/vc16/lib。这个做法的好处是源码保持通用团队里每个人在自己机器上配自己的路径。3.3 运行时 DLL 的三种处理方式对比编译链接都通了程序一运行弹出无法启动此程序因为计算机中丢失 opencv_world480.dll。这是配置流程的第二大高频问题。原因很简单.lib只是链接期的导入库真正运行需要同名的.dll而它不在系统搜索路径里。方案做法优点缺点适用场景加系统 Path把x64/vc16/bin加进环境变量一劳永逸所有工程共用换机器要重配Path 太长会影响系统启动个人开发机长期使用手动拷贝到输出目录把 DLL 复制到.exe同级目录最直观拷贝整个文件夹就能给别人跑每次清理重建都要重拷打包分发、临时调试qmake/CMake 自动拷贝构建后自动复制一劳永逸且跟工程走需要写几行脚本正式项目、团队协作我个人在生产项目里用的是第三种在.pro里加这么一段# 构建完成后自动把 OpenCV 的 DLL 复制到输出目录 win32 { OPENCV_BIN D:/dev/opencv/build/x64/vc16/bin CONFIG(debug, debug|release) { QMAKE_POST_LINK $$quote(cmd /c copy /Y $$shell_path($$OPENCV_BIN/opencv_world480d.dll) $$shell_path($$OUT_PWD/debug)) } else { QMAKE_POST_LINK $$quote(cmd /c copy /Y $$shell_path($$OPENCV_BIN/opencv_world480.dll) $$shell_path($$OUT_PWD/release)) } }这段的核心是QMAKE_POST_LINK它在链接完成之后执行$$OUT_PWD是构建输出目录。$$shell_path和$$quote两个包装是为了处理路径里可能出现的空格虽然我前面说了路径不要带空格但工程目录本身可能带加上更保险。4. 跑通第一个例子读图、处理、用 Qt 显示配置验证完毕写一个完整的、能看见结果的最小程序。这个程序要做三件事用 OpenCV 读一张图并做灰度化加边缘检测把结果转成 QImage用 QLabel 显示出来。4.1 完整 main.cpp#include QApplication #include QLabel #include QPixmap #include QDebug #include opencv2/opencv.hpp int main(int argc, char *argv[]) { QApplication app(argc, argv); // 1. 读图。中文路径在 Windows 上容易出问题建议用纯英文路径 cv::Mat img cv::imread(D:/test/lena.jpg, cv::IMREAD_COLOR); if (img.empty()) { qWarning() 读图失败请检查路径是否存在、文件是否损坏; return -1; } qDebug() 图像尺寸: img.cols x img.rows 通道数: img.channels(); // 2. 处理灰度化 Canny 边缘检测 cv::Mat gray, edges; cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY); cv::Canny(gray, edges, 60, 180); // 3. 转成 QImage。注意这里 QImage 不拷贝数据只是引用 Mat 的内存 QImage qimg(edges.data, edges.cols, edges.rows, static_castint(edges.step), QImage::Format_Grayscale8); // 4. 显示 QLabel label; label.setWindowTitle(Qt OpenCV Demo); label.setPixmap(QPixmap::fromImage(qimg)); label.show(); return app.exec(); }代码本身不长但每一行背后都有讲究尤其是第 3 步。4.2 Mat 转 QImage 的三个细节第一个细节stride行跨度必须传。cv::Mat的数据在内存里可能是连续存储的也可能每行末尾有填充字节这个信息存在mat.step里旧版叫step[0]。而QImage默认假设每行按 4 字节对齐。如果你的图像宽度恰好不是 4 的倍数直接构造出来的 QImage 会整体斜切、越往下偏移越明显很多人第一次看到这个现象以为是图像处理算法写错了其实是这一行参数没传。第二个细节颜色格式要选对。OpenCV 默认是 BGR 顺序Qt 的QImage::Format_RGB888是 RGB 顺序两者不能直接对接。Qt 5.14 之后提供了QImage::Format_BGR888可以直接对应 OpenCV 的 BGR 数据省掉一次颜色空间转换// Qt 5.14 推荐做法零拷贝、零转换 QImage qimg(img.data, img.cols, img.rows, static_castint(img.step), QImage::Format_BGR888);如果你的 Qt 版本低于 5.14就得老老实实转一次// 老版本 Qt 的做法多一次内存拷贝 cv::Mat rgb; cv::cvtColor(img, rgb, cv::COLOR_BGR2RGB); QImage qimg(rgb.data, rgb.cols, rgb.rows, static_castint(rgb.step), QImage::Format_RGB888);第三个细节也是最容易埋雷的QImage 不接管内存。上面这种构造方式QImage 只是拿了个指针不拷贝。这意味着如果cv::Mat先析构了QImage 就指向一块已经释放的内存接下来任何一次绘制都可能是访问越界。在上面的例子里edges和qimg都在main的作用域里app.exec()返回之前edges一直活着所以没问题。但如果你的 Mat 是某个函数里的局部变量函数一返回就销毁了那就必须在返回前调一次.copy()QImage safeCopy(edges.data, edges.cols, edges.rows, static_castint(edges.step), QImage::Format_Grayscale8); QImage owned safeCopy.copy(); // 真正持有数据脱离 Mat 生命周期.copy()会深拷贝一份数据代价是内存和一次拷贝耗时但对于一帧几十毫秒的显示场景完全可以接受。注意不要试图用cv::imshow和 Qt 窗口混用。OpenCV 的 HighGUI 窗口有自己的消息循环和 Qt 的事件循环放在一起会互相干扰表现是窗口无响应、图像不刷新、关不掉。既然已经在 Qt 里了显示这件事就交给 QLabel 或 QGraphicsView。4.3 编译运行与结果确认回到 Qt CreatorCtrlB 构建CtrlR 运行。如果前面配置没问题你会看到一个窗口里面是那张图的边缘检测结果。如果窗口弹出来是空白、或者显示的形状明显错乱按这个顺序排查先看qDebug()输出的尺寸对不对如果尺寸异常说明读图本身有问题尺寸对但画面斜切回头检查edges.step那一行是不是漏了尺寸对但颜色发蓝或发红检查格式是不是用错成了Format_RGB888去接 BGR 数据。这三个现象对应三类问题排查起来很快。5. 报错速查编译期、链接期、运行期配置过程中遇到的报错九成都能归到下面这几类。我把它们按出现的时间顺序整理出来并且给出直接的判断依据。5.1 编译期与链接期的典型报错fatal error C1083: 无法打开包括文件: opencv2/opencv.hpp这是头文件路径问题。百分之八十的情况是INCLUDEPATH指到了build/include/opencv2应该改成build/include。剩下百分之二十是路径里用了反斜杠导致转义异常在.pro里统一改成正斜杠即可。同样属于编译期的一大类是工程本身的环境问题而不是 OpenCV 的问题。比如vs2010编译报error msb6006 cmd.exe已退出代码为3这种报错来自 MSBuild 而不是编译器通常和自定义构建步骤、编码、杀毒软件拦截有关。这种错误跟 OpenCV 配置毫无关系不要往库配置上找原因先看构建步骤里有没有执行外部命令。LNK1104: 无法打开文件 opencv_world480d.lib链接器找不到这个.lib。三种可能-L给的目录不对Debug 构建用了 Release 的库名少了d后缀或反过来vc16和你的实际编译器版本对不上目录里根本没这个文件。最后一种最容易被忽略去x64下看看实际有哪个vcXX目录最直接。LNK2019: 无法解析的外部符号加一大串 OpenCV 函数名这个错误有个重要特征它说明头文件找到了、函数声明看到了但链接时找不到实现。原因通常是你用了 MinGW 的 Qt 套件去链 MSVC 编的 OpenCV 库。MSVC 和 GCC 的符号修饰规则完全不同链接器当然一个也对不上。解决办法就是换 MSVC 套件或者自己用 MinGW 编一份。还有一种可能是位数不匹配32 位工程链 64 位库。检查 Qt Creator 左下角的构建套件是不是 64bit。LNK2038: mismatch detected for _ITERATOR_DEBUG_LEVELDebug 和 Release 混用了。最常见的是工程是 Debug 构建但.pro里只写了 Release 的库名或者反过来。用前面 3.1 节那个CONFIG(debug, debug|release)分支就能彻底避免。5.2 运行期的典型报错无法启动此程序因为计算机中丢失 opencv_world480.dllDLL 不在搜索路径里。三种解法在 3.3 节已经列过表格按你的场景选一种。程序启动就闪退没有任何提示如果是控制台程序可能是缺少其他依赖 DLL比如 Visual C 运行库。用 Dependency Walker 或者 VS 自带的dumpbin /dependents看一下依赖清单。如果是 GUI 程序先确认是不是在app.exec()之前就崩了在可疑位置加qDebug()打点。程序跑到某一步突然崩溃在 OpenCV 内部先怀疑内存问题。cv::Mat的拷贝是引用计数的浅拷贝两个 Mat 指向同一块数据其中一个被修改另一个也变。如果你把 Mat 传给了多线程或者把一个局部 Mat 转换出的 QImage 传到了外面都会出现这种运行一段时间才崩的现象。这类问题的排查方法是把所有 Mat 的生命周期梳理一遍对于跨作用域传递的明确用.clone()或.copy()。5.3 一张可以贴在屏幕边上的速查表报错关键词出现阶段根本原因处理动作C1083 无法打开包括文件编译INCLUDEPATH 多指了一层改成build/include找不到 opencv2/opencv.hpp编译路径含反斜杠或空格换正斜杠路径去空格LNK1104 无法打开 .lib链接库目录或库名不对核对 vcXX 目录与 d 后缀LNK2019 无法解析的外部符号链接MinGW 链 MSVC 库 / 位数不符换 MSVC 套件或改 64 位LNK2038 _ITERATOR_DEBUG_LEVEL链接Debug/Release 混用加 CONFIG 分支丢失 opencv_worldXXX.dll运行DLL 不在搜索路径加 Path 或构建后拷贝显示画面斜切错位运行没传 step构造 QImage 时传mat.step显示颜色偏蓝/偏红运行RGB 与 BGR 顺序错用Format_BGR888或转 RGB图像显示为空白运行Mat 提前析构转换后调.copy()这张表里前面六行会让人怀疑人生后面三行会让人怀疑自己的算法。实际上它们都是配置层面的问题跟代码逻辑无关。有了这张表遇到问题先对号入座基本能省掉大量的搜索时间。6. 一些工程化与性能上的经验配置跑通只是开始。真拿 Qt OpenCV 做项目还有几个地方值得提前规划。6.1 目录组织与多人协作绝对不要把 OpenCV 解压到工程目录里面。我见过有人把整个 OpenCV 复制到工程下的third_party里理由是这样拷给别人就能直接跑。后果是 git 仓库体积直接涨到几个 G克隆一次二十分钟而且每次 OpenCV 升级都要重新提交一遍二进制。正确做法是把 OpenCV 放在工程外面通过一个配置文件来指定路径。qmake 里可以用.pri文件# opencv.pri —— 每个人本地维护一份加进 .gitignore OPENCV_DIR D:/dev/opencv/build INCLUDEPATH $$OPENCV_DIR/include LIBS -L$$OPENCV_DIR/x64/vc16/lib -lopencv_world480主.pro里写include(opencv.pri)然后把opencv.pri加进.gitignore。这样每个人在自己机器上维护自己的路径新人克隆下来只需要创建一份opencv.pri不用改任何被追踪的文件。如果嫌麻烦也可以提交一份opencv.pri.example作为模板。CMake 那边思路一样把OpenCV_DIR做成一个带默认值的缓存变量允许命令行覆盖set(OpenCV_DIR D:/dev/opencv/build/x64/vc16/lib CACHE PATH OpenCV config dir)6.2 显示性能与内存用 QLabel 显示图像简单场景够用但有几个性能拐点要知道。第一QPixmap::fromImage()每次调用都会把图像数据从 CPU 内存搬到图形系统里一张 4000x3000 的图一次转换就是几十毫秒。如果你在做一个需要连续刷新的预览界面这个开销会很明显。优化思路是在 QLabel 的尺寸固定、图像尺寸也固定的前提下复用同一个 QPixmap或者改用QGraphicsPixmapItem。第二cv::Mat到QImage的零拷贝构造虽然快但每次调用QPainter绘制时仍会读取原始数据。如果原始 Mat 会被频繁改写绘制过程可能出现撕裂。稳妥做法是在显示前.copy()一份代价是一次内存拷贝换来的是画面不会突然变形。第三别在 UI 线程里做重处理。cv::Canny、大图的cv::resize、各种滤波随便一个都可能占用几十到几百毫秒。放在 UI 线程里界面就是卡住的状态。常见做法是把处理放到QThread或者QtConcurrent::run里处理完通过信号槽把结果 Mat 传回 UI 线程再显示。传的时候注意 Mat 的浅拷贝语义跨线程传之前先.clone()。6.3 版本升级与长期维护OpenCV 的库文件名带版本号这件事决定了升级它不是换个文件夹那么简单。从 4.8 升到 4.10opencv_world480.lib要变成opencv_world4100.lib所有写死这个名字的地方都得改。我的做法是在.pro里抽一个变量出来OPENCV_VER 480 OPENCV_DIR D:/dev/opencv/build LIBS -L$$OPENCV_DIR/x64/vc16/lib -lopencv_world$${OPENCV_VER}升级时只改OPENCV_VER这一个值。同时把vc16也抽成变量因为将来 OpenCV 可能出vc17目录。这看起来是小事但版本管理混乱带来的构建失败往往发生在你最不想折腾的时候。另外一个需要留意的长期问题是 Qt 版本与 OpenCV 的编译器匹配。Qt 5.15 时代的 MSVC2019 和 OpenCV 4.8 的 vc16 是天生一对这个组合可以安心用很多年。如果你哪天把 Qt 升到 6.x注意 Qt 6 的 MSVC2019 套件依然可以链 vc16 的库但如果直接把 Qt 换成 MinGW 套件前面所有配置都要推倒重来。我个人在这几年里反复配置过这套环境最深的体会是能不用编译就不用编译能用预编译包就不要碰源码。源码编译解决的是需要定制的问题而绝大多数项目根本不需要定制只是被教程带着走进了一条不必要的路。把省下来的那几个小时拿去看 OpenCV 的图像处理 API产出比折腾 CMake 选项高得多。真到了需要opencv_contrib里的某个模块那天再回头编译那时候你对整个工具链的理解也已经足够支撑你走完流程了。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑