Qt-YOLO-OpenCV

一、绪论

从零开始配置Qt-YOLO-OpenCV。

二、配置OpenCV

网址:

https://opencv.org/releases/

三、配置YOLO

网址:

https://github.com/ultralytics/ultralytics

模型和推理的关系

维度 模型 (Model) 推理 (Inference)
本质 静态的知识库(数据文件) 动态的计算过程(程序运行)
类比 菜谱 按菜谱烹饪
存在形式 .pt, .onnx, .bin 等文件 一段代码或一个正在运行的程序
内容 网络结构、权重参数 加载、计算、输出等逻辑
作用 定义"做什么"和"怎么做"的规则 执行规则,完成具体任务
依赖关系 推理的基础和依据 模型的使用者和实现者

3.1下载模型

点击YOLO11s,下载好就这样

将pt格式转换为onnx

维度 PyTorch (.pt) 格式 ONNX (.onnx) 格式
性质与目的 研发框架专用格式,用于保存完整的训练状态。 跨平台交换标准,用于在不同框架和硬件间部署。
主要用途 模型训练、微调、继续训练和PyTorch环境内推理。 模型跨平台部署、性能优化(如TensorRT/OpenVINO转换)。
包含内容 完整状态:网络结构、权重、优化器状态、epoch等。 精简计算图:网络结构、权重、固定输入输出节点。
平台依赖 强依赖PyTorch及其Python生态。 弱依赖,任何支持ONNX标准的运行时均可加载。
可编辑性 ,可直接加载并修改结构、继续训练。 极低,通常视为只读的推理模型,难以直接修改或训练。
性能优化 依赖PyTorch自身优化和TorchScript。 作为中间格式,可被专用推理引擎(如ONNX Runtime、TensorRT)深度优化。
标准化程度 由PyTorch定义,是事实标准 由开放联盟定义,是行业开放标准

具体步骤:

新建python文件复制下面的代码

cpp 复制代码
from ultralytics import YOLO

model = YOLO("yolo11n.pt")  

export_path = model.export(format="onnx")  

运行后会生成onnx格式文件

3.2下载推理代码

将整个项目下载后找到这个路径

四、配置cmake,将OpenCV和YOLO集成到qt

OpenCV(注意这个对应的编译器是mscv2019)

cpp 复制代码
# 替换为你实际的OpenCV lib目录(包含OpenCVConfig.cmake的路径)
set(OpenCV_DIR "D:/opencv/build/x64/vc16/lib")

# 查找OpenCV库(基于上面设置的绝对路径)
find_package(OpenCV REQUIRED)

# 链接OpenCV库
target_link_libraries(demo PRIVATE
    ${OpenCV_LIBS}
)

# 添加OpenCV头文件路径
target_include_directories(demo PRIVATE
    ${OpenCV_INCLUDE_DIRS}
)

五、ui设计

添加inference文件

将这两个文件添加到你上面创建的项目中

mainwindow.h

cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include"inference.h"
#include<QFileDialog>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_open_clicked();

private:
    Ui::MainWindow *ui;
      Inference *inf{nullptr};
};
#endif // MAINWINDOW_H

mainwindow.cpp

cpp 复制代码
#include "mainwindow.h"
#include "./ui_mainwindow.h"
using namespace std;
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
    if (inf) {
        delete inf;
        inf = nullptr;
    }

}
cv::Mat QImageToCvMat(const QImage &qimage)
{
    switch(qimage.format()) {
    case QImage::Format_RGB32:    // 最常见格式(ARGB,忽略Alpha)
    case QImage::Format_ARGB32:
    case QImage::Format_ARGB32_Premultiplied: {
        cv::Mat mat(qimage.height(), qimage.width(), CV_8UC4,
                    (void*)qimage.constBits(), qimage.bytesPerLine());

        // 移除Alpha通道,将ARGB转为BGR
        cv::Mat mat_rgb;
        cv::cvtColor(mat, mat_rgb, cv::COLOR_BGRA2BGR);
        return mat_rgb;
    }

    case QImage::Format_RGB888: { // 24位RGB
        cv::Mat mat(qimage.height(), qimage.width(), CV_8UC3,
                    (void*)qimage.constBits(), qimage.bytesPerLine());

        // RGB转BGR
        cv::Mat mat_bgr;
        cv::cvtColor(mat, mat_bgr, cv::COLOR_RGB2BGR);
        return mat_bgr;
    }

    case QImage::Format_Grayscale8: { // 灰度图
        cv::Mat mat(qimage.height(), qimage.width(), CV_8UC1,
                    (void*)qimage.constBits(), qimage.bytesPerLine());
        return mat.clone(); // 需要clone以确保数据连续
    }

    default:
        // 转换为24位RGB再处理
        QImage converted = qimage.convertToFormat(QImage::Format_RGB888);
        return QImageToCvMat(converted);
    }
}
// 在 QImageToCvMat 函数后面添加这个函数
QImage cvMatToQImage(const cv::Mat &mat)
{
    switch(mat.type()) {
    // 8-bit, 4 channel
    case CV_8UC4: {
        QImage image(mat.data, mat.cols, mat.rows,
                     static_cast<int>(mat.step), QImage::Format_ARGB32);
        return image.copy();
    }
    // 8-bit, 3 channel
    case CV_8UC3: {
        QImage image(mat.data, mat.cols, mat.rows,
                     static_cast<int>(mat.step), QImage::Format_RGB888);
        return image.rgbSwapped();  // BGR to RGB
    }
    // 8-bit, 1 channel
    case CV_8UC1: {
        QImage image(mat.data, mat.cols, mat.rows,
                     static_cast<int>(mat.step), QImage::Format_Grayscale8);
        return image.copy();
    }
    default: {
        qWarning() << "cv::Mat image type not handled in switch:" << mat.type();
        return QImage();
    }
    }
}
void MainWindow::on_open_clicked()
{
    qDebug() << "按钮被点击";

    QString filePath = QFileDialog::getOpenFileName(
        this,
        "选择图片",
        "",
        "图片文件 (*.jpg *.jpeg *.png *.bmp *.gif)"
        );

    if (filePath.isEmpty()) return;

    QImage image(filePath);
    if (image.isNull()) {

        return;
    }

    // 先显示原始图片
    QPixmap originalPixmap = QPixmap::fromImage(image);

    // 计算合适的尺寸,保持图片比例,同时确保按钮可见
    QSize labelSize = ui->show->size();
    QPixmap scaledPixmap = originalPixmap.scaled(
        labelSize.width() - 20,  // 留出边距
        labelSize.height() - 60,  // 留出按钮空间
        Qt::KeepAspectRatio,
        Qt::SmoothTransformation
        );

    // 显示原始图片
    ui->show->setPixmap(scaledPixmap);
    ui->show->setAlignment(Qt::AlignCenter);

    // 设置按钮文本
    ui->open->setText("推理中...");
    ui->open->setEnabled(false);

    // 立即更新界面显示
    QCoreApplication::processEvents();

    // 进行推理
    string onnxPath = "D:/qtdemo/Fire/YOLO/yolo11s.onnx";
    string classesPath = "D:/qtdemo/Fire/YOLO/classes.txt";
    bool runOnGPU = false;

    // 如果之前有推理器,先删除
    if (inf) {
        delete inf;
        inf = nullptr;
    }

    try {
        inf = new Inference(onnxPath, cv::Size(640, 640), classesPath, runOnGPU);

        cv::Mat frame = QImageToCvMat(image);

        // 如果图像有 alpha 通道,转换为 BGR
        if (frame.channels() == 4) {
            cv::cvtColor(frame, frame, cv::COLOR_BGRA2BGR);
        }

        std::vector<Detection> output = inf->runInference(frame);

        int detections = output.size();
        std::cout << "Number of detections:" << detections << std::endl;

        // 在图像上绘制检测结果
        for (int i = 0; i < detections; ++i) {
            Detection detection = output[i];

            cv::Rect box = detection.box;
            cv::Scalar color = detection.color;

            // 绘制检测框
            cv::rectangle(frame, box, color, 2);

            // 绘制检测框文本
            std::string classString = detection.className + ' ' + std::to_string(detection.confidence).substr(0, 4);
            cv::Size textSize = cv::getTextSize(classString, cv::FONT_HERSHEY_DUPLEX, 1, 2, 0);
            cv::Rect textBox(box.x, box.y - 40, textSize.width + 10, textSize.height + 20);

            cv::rectangle(frame, textBox, color, cv::FILLED);
            cv::putText(frame, classString, cv::Point(box.x + 5, box.y - 10),
                        cv::FONT_HERSHEY_DUPLEX, 1, cv::Scalar(0, 0, 0), 2, 0);
        }

        // 将处理后的 OpenCV Mat 转换为 QImage
        QImage resultImage = cvMatToQImage(frame);

        // 计算合适的尺寸显示结果图片
        QPixmap resultPixmap = QPixmap::fromImage(resultImage);
        QSize labelSize = ui->show->size();
        QPixmap scaledResult = resultPixmap.scaled(
            labelSize.width() - 20,
            labelSize.height() - 60,  // 为按钮留出空间
            Qt::KeepAspectRatio,
            Qt::SmoothTransformation
            );

        // 在 QLabel 中显示结果图片
        ui->show->setPixmap(scaledResult);
        ui->show->setAlignment(Qt::AlignCenter);

        // 恢复按钮状态
        ui->open->setText("重新选择图片");
        ui->open->setEnabled(true);

        // 显示检测结果统计
        if (detections > 0) {
            QString message = QString("检测到 %1 个目标").arg(detections);

        }

    } catch (const std::exception& e) {
        qDebug() << "推理错误:" << e.what();


        // 恢复按钮状态
        ui->open->setText("选择图片并识别");
        ui->open->setEnabled(true);
    }
}

六、效果

相关推荐
Quz42 分钟前
QML TextArea 入门(二):富文本与换行模式
qt
qq_25294131682 小时前
列车车轮缺陷智能检测数据集:800张图像、4大类别,助力铁路安全运维
运维·人工智能·安全·yolo·目标检测·计算机视觉·视觉检测
老木避暑研究所2 小时前
基于OpenCV的避暑房采光分析与朝向优化——重庆云澜栖不同楼层日照时长实测
人工智能·opencv·计算机视觉
leoZ2312 小时前
Vue3 还原一个企业级后台-06-主布局设计
人工智能·opencv·机器学习·计算机视觉·数据挖掘·语音识别·caffe
雨晨源码(同名B站)3 小时前
基于深度学习YoloV11农业病害虫害检测系统 智慧农业信息化综合管理平台 (附源码+lw文档+ppt)
数据库·人工智能·深度学习·yolo·信息可视化
大白同学4214 小时前
初识Qt——创建第一个Qt项目
开发语言·qt
秋田君7 小时前
QT_绘图原理双缓冲机制
服务器·数据库·qt
想要入门的程序猿7 小时前
Qt插件QPluginLoader
开发语言·qt
欧特克_Glodon7 小时前
OpenCV计算机视觉开发入门与实践<六>:OpenCV架构模块简介
c++·人工智能·opencv·计算机视觉
JeJe同学8 小时前
Opencv之高斯金字塔
人工智能·opencv·计算机视觉