当前位置: 首页 > news >正文

【AI时代速通QT】第五节:Qt Creator如何引入第三方库,以OpenCV为例

目录

引言

一、第一步:万事开头难 - 准备工作

1.1 获取并“安装”OpenCV

1.2 创建一个新的Qt项目

1.3 建立专业的项目目录结构

二、第二步:核心操作 - 配置.pro文件

2.1 方式一:图形化向导(适合初次体验)

2.2 方式二:手动编辑.pro文件(专业且灵活)

三、第三步:小试牛刀 - 编写代码并编译

3.1 修改`main.cpp`

3.2 编译项目

四、第四步:临门一脚 - 运行与问题排查

4.1 问题根源:编译时链接 vs 运行时加载

4.2 解决方案

4.2.1 方案一:简单粗暴法 - 手动复制DLL

4.2.2 方案二:Qt Creator的优雅之道 - 配置运行环境

4.2.3 方案三:终极方案 - 编写构建后脚本(推荐)

总结


  🎬 攻城狮7号:个人主页

🔥 个人专栏:C++QT跨平台界面编程

⛺️ 君子慎独!

 🌈 大家好,欢迎来访我的博客!
⛳️ 此篇文章主要介绍 Qt Creator如何引入第三方库
📚 本期文章收录在《C++QT跨平台界面编程》,大家有兴趣可以自行查看!
⛺️ 欢迎各位 ✔️ 点赞 👍 收藏 ⭐留言 📝!

引言

        在软件开发的世界里,几乎没有哪个大型项目是完全从零开始、闭门造车完成的。无论是为了实现复杂的功能,还是为了加快开发速度,我们都不可避免地需要站在巨人的肩膀上——使用第三方库。对于C++开发者,尤其是使用Qt框架构建图形化界面(GUI)应用的工程师来说,掌握如何优雅、高效地将强大的第三方库集成到自己的项目中,是一项至关重要的核心技能。

        OpenCV(Open Source Computer Vision Library)作为计算机视觉领域最负盛名、功能最强大的开源库,是无数图像处理、机器学习、视频分析应用的首选。而Qt则以其跨平台、功能完善、开发体验优秀而著称。将OpenCV强大的计算能力与Qt精美的交互界面相结合,便能创造出专业、强大的桌面应用程序。

        然而,对于许多初学者来说,配置过程中的各种路径问题、链接器错误、运行时DLL丢失等问题,常常像一道道难以逾越的鸿沟,令人望而生畏。本教程的目的,就是为您彻底扫清这些障碍。

        我们将以一个全新的Qt Widgets项目为例,手把手、一步步地演示如何将OpenCV库集成进来。本教程不仅仅是步骤的罗列,更会深入解释每个步骤背后的“为什么”,让您知其然,更知其所以然。读完本篇文章,您将掌握:

        (1)规范的项目文件组织方式:学习如何管理第三方库文件,让您的项目结构清晰、可移植。

        (2)Qt项目文件(.pro)的核心配置:精通`INCLUDEPATH`(头文件路径)和`LIBS`(库文件)的设置,包括如何使用相对路径和进行Debug/Release的区分配置。

        (3)解决经典的运行时DLL丢失问题:深入理解动态链接库(DLL)的加载机制,并学会三种以上解决该问题的有效方法。

        (4)编写简单的测试代码验证集成效果:通过一个“打开图片并显示”的简单实例,完成从配置到运行的闭环。

        准备好了吗?让我们开始这段奇妙之旅吧!

一、第一步:万事开头难 - 准备工作

        在敲下第一行配置代码之前,我们需要做好充分的准备。这包括准备OpenCV库文件、创建一个新的Qt项目以及建立一个科学合理的文件目录结构。

1.1 获取并“安装”OpenCV

        首先,您需要从[OpenCV官方网站](https://opencv.org/releases/)下载适用于您开发环境(例如Windows)的预编译版本。官网默认提供的是 MSVC 版本。下载下来通常是一个可执行文件,运行它,其实质是一个自解压程序,会将其中的文件解压到您指定的目录。

        解压后,您会得到一个名为`opencv`的文件夹,其核心内容位于`build`子目录中。我们需要其中的三个部分:

        -   `opencv/build/include`: 这里存放着所有的OpenCV头文件(`.h`和`.hpp`)。

        -   `opencv/build/x64/vc15/lib` (路径中的`x64/vc15`可能因您的系统和编译器版本而异): 这里存放着链接时所需的库文件(`.lib`)。

        -   通常您会看到两个版本,如`opencv_world320.lib`(用于Release模式)和`opencv_world320d.lib`(用于Debug模式,注意末尾的'd')。

        -   `opencv/build/x64/vc15/bin`: 这里存放着程序运行时真正依赖的动态链接库文件(`.dll`)。

1.2 创建一个新的Qt项目

打开Qt Creator,创建一个新的项目:

(1)`File` -> `New Project`

(2)选择 `Application (Qt)` -> `Qt Widgets Application`。

(3)为项目命名,例如`testqt`,并选择一个项目创建路径。

(4)选择构建系统为`qmake`。

(5)其他步骤保持默认设置,一直点击“Next”直到完成。

1.3 建立专业的项目目录结构

        这是至关重要的一步,一个好的目录结构能让您的项目瞬间变得专业和易于管理。根据您提供的示例,我们将采用一种常见的源码与依赖分离的结构。

        假设您的项目完整路径为 `D:/MyProjects/testqt/`。我们在此根目录下创建如下结构:

D:/MyProjects/

|-- 3rdparty/                 <-- 新建一个文件夹,统一存放所有第三方库

|   |-- opencv/

|       |-- include/          <-- 用于存放OpenCV的头文件

|       |-- lib/              <-- 用于存放OpenCV的.lib文件

|       |-- bin/              <-- 用于存放OpenCV的.dll文件

|

|-- testqt/                   <-- 这是我们的Qt项目目录

|   |-- testqt.pro            <-- Qt项目配置文件

|   |-- main.cpp

|   |-- widget.h

|   |-- widget.cpp

|   |-- widget.ui

        然后,将我们之前从OpenCV解压目录中找到的文件,按需复制过来:

(1)将`opencv/build/include`下的所有内容,复制到 `D:/MyProjects/3rdparty/opencv/include/` 目录下。

(2)将`opencv/build/x64/vc15/lib`下的`opencv_world320.lib`和`opencv_world320d.lib`,复制到 `D:/MyProjects/3rdparty/opencv/lib/` 目录下。

(3)将`opencv/build/x64/vc15/bin`下的`opencv_world320.dll`和`opencv_world320d.dll`,复制到 `D:/MyProjects/3rdparty/opencv/bin/` 目录下。

        为什么要这样做?

(1)可移植性:`testqt`项目通过相对路径引用`3rdparty`中的库,只要保持这个相对文件结构,您可以将`MyProjects`这个根目录拷贝到任何电脑上,项目都能直接编译运行。

(2)版本锁定:项目使用的OpenCV版本被清晰地锁定在`3rdparty`中,避免了系统环境变量中可能存在的其他版本干扰。

(3)结构清晰:项目代码(`testqt`)与第三方依赖(`3rdparty`)完全分离,一目了然。

准备工作完成!我们的项目现在“万事俱备,只欠东风”——配置`.pro`文件。

二、第二步:核心操作 - 配置.pro文件

        `.pro`文件是Qt项目的“心脏”,它通过`qmake`工具告诉编译器如何构建我们的应用程序。我们需要在这里告诉编译器两件重要的事情:

        (1)去哪里找OpenCV的头文件(`INCLUDEPATH`)。

        (2)需要链接哪个OpenCV的库文件(`LIBS`)。

        我们介绍两种配置方式:图形化向导和手动编辑。强烈推荐学习并使用第二种手动编辑的方式。

2.1 方式一:图形化向导(适合初次体验)

        Qt Creator提供了一个方便的向导来添加库。

(1)在项目文件树上右键点击项目根节点,选择`Add Library...`。

(2)选择`External Library`,点击`Next`。

(3)在`Library file`字段,点击`Browse...`,导航到我们项目中的`3rdparty/opencv/lib/`目录,选择`opencv_worldXXX.lib`(先选Release版本的)。

(4)在`Include path`字段,`Browse...`到`3rdparty/opencv/include/`目录。

(5)关键:在`Platform`下拉菜单中,确保勾选了`Windows`(如果您在Windows开发)。取消勾选其他平台。

(6)重要:取消勾选`Add "d" as a suffix for debug version`。因为我们稍后会通过更灵活的方式来手动区分Debug和Release版本,这里不使用它的自动功能。

(7)点击`Next`,然后`Finish`。

        此时,打开`.pro`文件,您会看到Qt Creator自动为您添加了类似下面(路径可能是绝对路径)的代码:

        这种方法的缺点是,它可能会生成硬编码的绝对路径,不利于项目迁移。因此,我们更推荐下面的手动方式。

2.2 方式二:手动编辑.pro文件(专业且灵活)

        手动编辑能让我们对项目有完全的控制,尤其是使用相对路径,这才是专业的做法。

打开`testqt.pro`文件,在文件的末尾添加以下内容,并做更完善的Debug/Release区分处理。

# ===================================================================# OpenCV Configuration# ===================================================================# $$PWD 是一个qmake内置变量,代表.pro文件所在的当前目录(D:/MyProjects/testqt/)。# 我们使用 '..' 来向上追溯一级目录,从而定位到3rdparty文件夹。# 这种相对路径的写法,保证了项目的可移植性。# 1. 指定头文件路径INCLUDEPATH += $$PWD/../3rdparty/opencv/include# 2. 指定库文件路径和具体库文件# 使用CONFIG来实现Debug和Release模式的区分配置CONFIG(debug, debug|release) {# Debug模式下# -L: 指定库文件所在的目录 (L for Library Path)# -l: 指定具体的库文件名,省略前缀'lib'和后缀'.lib' (l for library)#     例如 opencv_world320d.lib -> -lopencv_world320dLIBS += -L$$PWD/../3rdparty/opencv/lib -lopencv_world320d} else {# Release模式下LIBS += -L$$PWD/../3rdparty/opencv/lib -lopencv_world320}

> 代码解读:

> -   `$$PWD/../3rdparty/opencv/lib`:这是精髓所在。`$$PWD`是`D:/MyProjects/testqt/`,`..`让路径上溯一层到`D:/MyProjects/`,然后再进入`3rdparty/opencv/lib`。这样无论`MyProjects`目录在哪里,路径都是正确的。

> -   `INCLUDEPATH += ...`:将OpenCV `include`目录添加到项目的头文件搜索路径列表中。编译器在编译时,会到这个目录下去寻找`#include`的头文件。

> -   `CONFIG(debug, debug|release) { ... } else { ... }`:这是一个条件判断语句。当项目以Debug模式构建时(`debug`条件成立),执行第一个代码块;当以Release模式构建时,执行`else`中的代码块。

> -   `LIBS += -L<path> -l<name>`:这是链接器指令。

>     -   `-L`后面跟着的是库文件所在的目录路径。

>     -   `-l`后面跟着的是**库的名称**(去掉了`lib`前缀和`.lib`或`.a`后缀)。链接器会根据这个名称自动寻找对应的文件(如`libopencv_world455d.lib`)。

        完成编辑后,务必执行qmake。右键点击项目根节点,选择`Run qmake`。这一步会使您的`.pro`文件修改生效,重新生成Makefile。

        至此,编译环境已经配置完毕。如果现在点击“编译”,只要代码中没有语法错误,项目应该能够成功通过编译,不会再报“找不到头文件”或“未定义的引用”这类链接错误了。

三、第三步:小试牛刀 - 编写代码并编译

        配置完成,是时候写几行代码来验证我们的劳动成果了。根据您在`qtcreator引入第三方opencv库和头文件路径.md`中的描述,我们进行一个最简单的测试:在程序启动时,直接调用OpenCV的函数来创建一个窗口。

        我们将修改`main.cpp`文件,因为这个测试不依赖于`widget.ui`上的任何控件。

3.1 修改`main.cpp`

        打开`main.cpp`,添加OpenCV的头文件,并在显示主窗口前加入OpenCV的测试代码。

// main.cpp#include "widget.h"#include <QApplication>// 1. 引入OpenCV核心头文件#include <opencv2/opencv.hpp>int main(int argc, char *argv[]){QApplication a(argc, argv);// 2. 添加OpenCV测试代码// 使用cv命名空间// 创建一个名为 "open cv" 的窗口cv::namedWindow("open cv");Widget w;w.show();// 3. 最终返回Qt事件循环return a.exec();}

> 代码解释:

> -   `#include <opencv2/opencv.hpp>`:包含了使用OpenCV所需的所有核心功能。

> -   `cv::namedWindow("open cv");`:这是OpenCV的一个函数,它的作用就是创建一个可以显示图像的窗口。在我们的测试中,调用这个函数本身就是一种验证。如果程序能够编译链接通过,并成功运行到这一行,就说明我们对库的配置(`.lib`文件链接)是正确的。

3.2 编译项目

        现在,点击Qt Creator左下角的“锤子”图标(或按`Ctrl+B`)来编译项目。如果前面的`.pro`文件配置无误,编译过程应该会顺利通过,在输出栏看到绿色的“编译完成”信息。

        编译成功在这一步意义重大:

        (1)头文件找到了:`#include <opencv2/opencv.hpp>`没有报错,说明`INCLUDEPATH`配置正确。

        (2)库函数链接成功了:编译链接阶段没有报`undefined reference to cv::namedWindow`之类的错误,说明`LIBS`配置正确,链接器成功在`.lib`文件中找到了函数的声明。

四、第四步:临门一脚 - 运行与问题排查

        编译成功只代表“蓝图”没问题,但程序能否顺利“运行”是另一回事。点击绿色的“运行”按钮(或按`Ctrl+R`),下面运行成功的界面:

        但是您有**极大概率**会遇到程序闪退,或者看到一个Windows系统弹窗,提示“无法启动此程序,因为计算机中丢失 opencv_world320d.dll”。

        恭喜您,遇到了新手最常见,也是最经典的问题!

4.1 问题根源:编译时链接 vs 运行时加载

        为什么会这样?我们需要理解静态库(`.lib`)和动态库(`.dll`)的区别:

        -   编译时:编译器通过`.lib`文件(我们的“地址簿”)知道了`cv::namedWindow`等函数是真实存在的,并记录下它们位于哪个DLL中。因此编译能够成功。

        -   运行时:当您的`testqt.exe`程序开始执行时,操作系统(Windows)的加载器会尝试去加载该程序所依赖的所有`.dll`文件。它会按照一定的顺序搜索这些文件,默认的搜索路径包括:**1. 程序所在目录**;2. 系统目录(System32等);3. `PATH`环境变量中指定的目录。

        我们的`opencv_world320d.dll`文件安安稳稳地躺在`D:/MyProjects/3rdparty/opencv/bin`目录下,而我们生成的`testqt.exe`在另一个单独的`build-testqt-Desktop.../debug`构建目录里。操作系统加载器在默认搜索路径中找不到所需的DLL,于是程序启动失败。

4.2 解决方案

        知道了原因,解决办法就清晰了:我们必须让操作系统在运行时能找到我们的DLL文件。这里提供三种由浅入深、从“临时工”到“正规军”的解决方案。

4.2.1 方案一:简单粗暴法 - 手动复制DLL

        最直观的方法,就是缺啥补啥。

        (1)找到您的项目构建目录,例如`build-testqt-Desktop_Qt_5_15_2_MinGW_64_bit-Debug/debug`。

        (2)进入我们之前准备的`D:/MyProjects/3rdparty/opencv/bin`目录。

        (3)将`opencv_world320d.dll`复制到上述的`debug`文件夹中(与`testqt.exe`文件放在一起)。

        (4)如果是Release模式,则将`opencv_world320.dll`复制到`release`文件夹中。

再次运行程序,现在它应该可以正常启动了!您会看到两个窗口:一个是Qt的空白主窗口,另一个则是一个标题为“open cv”的OpenCV窗口。

        -   优点:立竿见影,易于理解。

        -   缺点:非常繁琐。每次“Clean”项目后,构建目录被清空,您都需要重新手动复制一次。不专业,且容易遗忘。

4.2.2 方案二:Qt Creator的优雅之道 - 配置运行环境

        既然问题出在“工作目录”,我们可以在Qt Creator中直接为我们的程序指定一个“聪明”的工作目录。

        (1)点击Qt Creator左侧的`Projects`图标,进入项目配置模式。

        (2)确保当前选中的是您的构建套件(Kit),在`Build & Run`下选择`Run`标签页。

        (3)找到`Run`设置中的`Working directory`字段。

        (4)点击`Browse...`,将其路径设置为我们存放DLL的目录:`D:/MyProjects/3rdparty/opencv/bin`。

        再次运行,程序也能成功启动。

        -   优点:一次配置,永久生效(在Qt Creator内部)。无需手动复制文件,项目更整洁。

        -   缺点:此设置仅在Qt Creator内部通过“运行”按钮启动时有效。如果您直接去`build`目录双击`.exe`文件,它依然会因为找不到DLL而无法运行。这对于最终发布程序是不够的。

4.2.3 方案三:终极方案 - 编写构建后脚本(推荐)

        这是最专业、最一劳永逸的方法。我们通过修改`.pro`文件,让`qmake`在每次成功编译链接之后,自动执行一个复制命令,将所需的DLL文件拷贝到可执行文件的旁边。

        在`.pro`文件末尾添加以下代码:

# ===================================================================# Post-build step: Copy DLLs# ===================================================================# 自定义一个函数,用于拷贝文件defineTest(copy_dll) {# $$1: source file, $$2: destination directory# QMAKE_POST_LINK 是一个特殊变量,它会在链接步骤后执行命令# 使用$$shell_path将路径中的'/'转换为'\'以兼容windows的copy命令QMAKE_POST_LINK += $$quote(cmd /c copy /y $$shell_path($$1) $$shell_path($$2))return(true)}# 获取DLL的源目录和目标目录DLL_SOURCE_DIR = $$PWD/../3rdparty/opencv/bin# $$OUT_PWD是qmake变量,指向构建输出目录(debug或release)DEST_DIR = $$OUT_PWD# 根据构建模式拷贝对应的DLLCONFIG(debug, debug|release) {copy_dll($$DLL_SOURCE_DIR/opencv_world320d.dll, $$DEST_DIR)} else {copy_dll($$DLL_SOURCE_DIR/opencv_world320.dll, $$DEST_DIR)}

        > 注意:如果您的Qt版本或环境配置不同,`cmd /c copy`可能需要调整。一个更跨平台的做法是使用`$$QMAKE_COPY`。为了简洁易懂,此处使用Windows原生的`copy`命令作为示例。

        修改后,再次`Run qmake`,然后重新编译您的项目。编译完成后,去`build/.../debug`目录查看,您会发现`opencv_world320d.dll`已经自动出现在那里了!

        -   优点:完全自动化,一劳永逸。无论是从Qt Creator运行,还是直接双击exe,或者将`build`目录打包发给别人,都能完美运行。这是软件发布的标准做法。

        -   缺点:`.pro`文件配置稍微复杂一点,但一次配置,终身受益。

总结

        通过以上四个步骤,您已经成功地将强大的OpenCV库“嫁接”到了您的`testqt`项目中,并掌握了从配置、编码到部署的全流程。让我们回顾一下成功的关键:

        (1)精心准备:建立清晰的、源码与依赖分离的目录结构(`testqt`与`3rdparty`),是项目清晰、可移植的基石。

        (2)精确制导:通过手动编辑`.pro`文件,使用`$$PWD/..`相对路径和`CONFIG`条件编译,精确地告诉编译器头文件和库文件的位置,并区分Debug/Release。

        (3)对症下药:深刻理解DLL的运行时加载机制,从而选择最适合的方案(推荐自动拷贝DLL的构建后脚本)来解决“找不到DLL”的经典问题。

        这个流程不仅适用于OpenCV,它几乎适用于任何您想在Qt中使用的第三方C++库。掌握了这套方法,就等于打通了Qt与其他无数优秀C++生态库连接的“任督二脉”。

看到这里了还不给博主点一个:
⛳️ 点赞☀️收藏 ⭐️ 关注

💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖
再次感谢大家的支持!
你们的点赞就是博主更新最大的动力!

http://www.dtcms.com/a/291724.html

相关文章:

  • 深入解析MIPI C-PHY (三)C-PHY 功耗屠龙刀
  • FunASR 说话人识别 Xvector 环境版本配置
  • 一文读懂深度模型优化器,掌握炼丹工具
  • 【数学建模】基础知识
  • FTP考点
  • SparkSQL 聚合函数 COUNT 对 NULL 值的处理
  • css3地球转动模型(动态数据)
  • RxSwift 核心解析
  • 生成式AI導論 2024】第9講:以大型語言模型打造的AI Agent 学习记录
  • Nacos 注册中心高频面试题及解析
  • v0+claude+cursor构建初始脚手架
  • ADA4522-2ARMZ-R7 ADI亚德诺 双通道零漂移运算放大器 工业高精度测试设备应用
  • 您需要了解的有关 GIS 中基于位置和基于属性的查询的所有信息
  • [pdf epub]《软件方法》电子书202507更新下载
  • thinkphp入门
  • 企业级IIS配置手册:安全加固/负载均衡/性能优化最佳实践
  • C++性能优化擂台技术文章大纲
  • Axios Token 设置示例
  • MySql 运维性能优化
  • React 项目性能优化概要
  • Vue-21-利用Vue3的axios+Python的flask实现前后端交互功能
  • 精密全波整流电路(二)
  • 以太网基础⑥ ZYNQ PS端 基于LWIP的TCP例程测试
  • uniapp “requestPayment:fail [payment支付宝:62009]未知错误“
  • 渗透第2次作业
  • 从零开始:Vue 3 + TypeScript 项目创建全记录
  • C++刷题常用方法
  • uniapp请求封装上传
  • DeepSPV:一种从2D超声图像中估算3D脾脏体积的深度学习流程|文献速递-医学影像算法文献分享
  • 从0到1:盲盒抽卡小程序开发全流程解析