win10系统下使用opencv-dnn部署yolov5模型

news2024/12/25 9:17:59

文章目录

  • 前言
  • 一、环境
    • 1、硬件
    • 2、软件
  • 二、YOLO模型
  • 三、新建Qt项目
    • 1、pro文件
    • 2、main函数
  • 四、YOLO 类封装
    • 1、yolo.h
    • 2、yolo.cpp
    • 3、classes.txt
  • 五、效果


前言

  最近工作中需要用yolov5训练模型,然后在win10系统下,完成推理部署。本篇主要介绍使用opencv-dnn模块实现模型推理部署。

一、环境

1、硬件

Intel® Core i5-7400 CPU @ 3.00GHZ
Intel® HD Graphics 630 内存4G 核显
内存 8G
win10 64位系统

2、软件

opencv4.6.0
yolov5 6.2版本

二、YOLO模型

我使用的是onnx模型,如果没有训练过自己的模型,可以使用官方的yolov5s.pt模型,将其转化为yolov5s.onnx模型,转化方法如下:

python export.py

在yolov5-master目录下,可以看到yolov5s.onnx模型已生成。

三、新建Qt项目

1、pro文件

在pro文件中,添加opencv相关配置,内容如下:

#-------------------------------------------------
#
# Project created by QtCreator 2022-10-09T13:28:19
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = untitled1
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp \
    yolo.cpp

HEADERS  += mainwindow.h \
    yolo.h

FORMS    += mainwindow.ui

INCLUDEPATH += C:/opencv4.6.0/build/include
               C:/opencv4.6.0/build/include/opencv2

LIBS += -LC:/opencv4.6.0/build/x64/vc14/lib/ -lopencv_world460

2、main函数

#include "mainwindow.h"
#include <QApplication>

#include <QDebug>
#include "yolo.h"
#include <iomanip>
#include <QTime>
#include <QThread>

//const vector<Scalar> colors = { Scalar(255, 255, 0), Scalar(0, 255, 0), Scalar(0, 255, 255), Scalar(255, 0, 0) };

int main(int argc, char *argv[])
{
    Mat frame;
    VideoCapture capture("G:/1.mp4");//sample
    if (!capture.isOpened())
    {
        std::cerr << "Error opening video file\n";
        return -1;
    }
    cv::VideoWriter video("out.avi",cv::VideoWriter::fourcc('M','J','P','G'),10, cv::Size(1920,1080));
    //
    YOLO *yolov5 = new YOLO;
    yolov5->init("F:/SVN-ZJKY/YiFeiShouJiRobot/yolov5-6.1/yolov5s.onnx");
    //
    std::vector<detect_result> output;
    int total_frames = 0;
    //
    clock_t start_name = 0;
    clock_t end_time = 0;
    //
    while ( true )
    {

        //
        start_name = clock();
        capture.read(frame);
        if (frame.empty())
        {
            std::cout << "End of stream\n";
            break;
        }

        //
        total_frames++;
//        auto start = std::chrono::system_clock::now();
//        t = (double)cv::getTickCount();
        yolov5->detect(frame,output);
//        auto end = std::chrono::system_clock::now();
//        auto detect_time =std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();//ms
//        std::cout<<detect_time<<":"<<total_frames<<":"<<output.size()<<std::endl;
        //
//        t = ((double)cv::getTickCount() - t) / cv::getTickFrequency();
//        fps = 1.0 / t;
        end_time=clock();//ms

        auto text = "FPS: " + std::to_string(1 / ((double)(end_time - start_name) / CLOCKS_PER_SEC));
        qDebug() << "Frame time(ms): " << (double)(end_time - start_name) /*/ CLOCKS_PER_SEC*/;
        cv::putText(frame, text, cv::Point(3, 25), cv::FONT_ITALIC, 0.8, cv::Scalar(0, 0, 255), 2);
        //
        yolov5->draw_frame(frame,output);
        imshow("output", frame);
        video.write(frame);

        if (waitKey(1) != -1)
        {
            std::cout << "finished by user\n";
            break;
        }
        output.clear();
    }
    //
    capture.release();
    video.release();
    cv::destroyAllWindows();
    waitKey(0);
    //std::cout << "Total frames: " << total_frames << "\n";
    return 0;
}

四、YOLO 类封装

1、yolo.h

#include <fstream>
#include <sstream>
#include <iostream>
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
using namespace dnn;
using namespace std;

class detect_result
{
public:
    int classId;
    float confidence;
    cv::Rect_<float> box;
};

class YOLO
{
public:
    YOLO();
    ~YOLO();
    void init(std::string onnxpath);
    //Net loadNet(bool is_cuda);
    //Mat format_yolov5(const Mat &source);
    std::vector<std::string> classes_;
    void detect(cv::Mat & frame, std::vector<detect_result> &result);
    //void drawRect(Mat &image,vector<Detection> &output);
    //std::vector<std::string> load_class_list();
    void draw_frame(cv::Mat & frame, std::vector<detect_result> &results);

private:
    cv::dnn::Net net;
    //cv::dnn::Net m_net;
//    const float INPUT_WIDTH = 640.0;
//    const float INPUT_HEIGHT = 640.0;
//    const float SCORE_THRESHOLD = 0.2;
//    const float NMS_THRESHOLD = 0.4;
//    const float CONFIDENCE_THRESHOLD = 0.4;

    const float confidence_threshold_ =0.25f;
    const float nms_threshold_ = 0.4f;
    const int model_input_width_ = 640;
    const int model_input_height_ = 640;
};

2、yolo.cpp

#include "yolo.h"

YOLO::YOLO()
{
    //loadNet(false);
}

YOLO::~YOLO()
{

}

//std::vector<std::string> YOLO::load_class_list()
//{
//    std::vector<std::string> class_list;
//    std::ifstream ifs("G:/classes.txt");
//    std::string line;
//    while (getline(ifs, line))
//    {
//        class_list.push_back(line);
//    }
//    return class_list;
//}

//Net YOLO::loadNet(bool is_cuda)
//{
//    //F:\SVN-ZJKY\YiFeiShouJiRobot\yolov5-master
//    //m_net = readNet("F:\\SVN-ZJKY\\YiFeiShouJiRobot\\yolov5-master\\yolov5s.onnx");
//    m_net = readNet("F:\\SVN-ZJKY\\YiFeiShouJiRobot\\demo\\yolov5-opencv-dnn-cpp-main\\QtDemo\\build-yolov5-opencv-dnn-cpp-main-Qt5_6_2_MSVC2015_64bit-Release\\release\\yolov5s.onnx");
//    if (is_cuda)
//    {
//        cout << "Attempty to use CUDA\n";
//        m_net.setPreferableBackend(DNN_BACKEND_CUDA);
//        m_net.setPreferableTarget(DNN_TARGET_CUDA_FP16);
//    }
//    else
//    {
//        cout << "Running on CPU12\n";
//        m_net.setPreferableBackend(DNN_BACKEND_OPENCV);
//        m_net.setPreferableTarget(DNN_TARGET_CPU);
//    }

//    return m_net;
//}

//Mat YOLO::format_yolov5(const Mat &source)
//{
//    int col = source.cols;
//    int row = source.rows;
//    int _max = MAX(col, row);
//    Mat result = Mat::zeros(_max, _max, CV_8UC3);
//    source.copyTo(result(Rect(0, 0, col, row)));
//    return result;
//}

void YOLO::init(std::string onnxpath)
{

    this->net = cv::dnn::readNetFromONNX(onnxpath);

    std::string file="G:/classes.txt";
    std::ifstream ifs(file);
    if (!ifs.is_open())
        CV_Error(cv::Error::StsError, "File " + file + " not found");
    std::string line;
    while (std::getline(ifs, line))
    {
        classes_.push_back(line);
    }
}

void YOLO::detect(cv::Mat & frame, std::vector<detect_result> &results)
{
    int w = frame.cols;
    int h = frame.rows;
    int _max = std::max(h, w);
    cv::Mat image = cv::Mat::zeros(cv::Size(_max, _max), CV_8UC3);
    cv::Rect roi(0, 0, w, h);
    frame.copyTo(image(roi));


    float x_factor = static_cast<float>(image.cols) / model_input_width_;
    float y_factor = static_cast<float>(image.rows) / model_input_height_;


    //std::cout<<x_factor<<std::endl;
    //std::cout<<y_factor<<std::endl;

    cv::Mat blob = cv::dnn::blobFromImage(image, 1 / 255.0, cv::Size(model_input_width_, model_input_height_), cv::Scalar(0, 0, 0), true, false);
    this->net.setInput(blob);
    cv::Mat preds = this->net.forward("output");//outputname


    cv::Mat det_output(preds.size[1], preds.size[2], CV_32F, preds.ptr<float>());

    std::vector<cv::Rect> boxes;
    std::vector<int> classIds;
    std::vector<float> confidences;
    for (int i = 0; i < det_output.rows; i++)
    {
        float box_conf = det_output.at<float>(i, 4);
        if (box_conf < nms_threshold_)
        {
            continue;
        }

        cv::Mat classes_confidences = det_output.row(i).colRange(5, 85);
        cv::Point classIdPoint;
        double cls_conf;
        cv::minMaxLoc(classes_confidences, 0, &cls_conf, 0, &classIdPoint);


        if (cls_conf > confidence_threshold_)
        {
            float cx = det_output.at<float>(i, 0);
            float cy = det_output.at<float>(i, 1);
            float ow = det_output.at<float>(i, 2);
            float oh = det_output.at<float>(i, 3);
            int x = static_cast<int>((cx - 0.5 * ow) * x_factor);
            int y = static_cast<int>((cy - 0.5 * oh) * y_factor);
            int width = static_cast<int>(ow * x_factor);
            int height = static_cast<int>(oh * y_factor);
            cv::Rect box;
            box.x = x;
            box.y = y;
            box.width = width;
            box.height = height;

            boxes.push_back(box);
            classIds.push_back(classIdPoint.x);
            confidences.push_back(cls_conf * box_conf);
        }
    }

    std::vector<int> indexes;
    cv::dnn::NMSBoxes(boxes, confidences, confidence_threshold_, nms_threshold_, indexes);
    for (size_t i = 0; i < indexes.size(); i++)
    {
        detect_result dr;
        int index = indexes[i];
        int idx = classIds[index];
        dr.box = boxes[index];
        dr.classId = idx;
        dr.confidence = confidences[index];
        results.push_back(dr);
    }

}

void YOLO::draw_frame(cv::Mat & frame, std::vector<detect_result> &results)
{
    for(auto dr : results)
    {

        cv::rectangle(frame, dr.box , cv::Scalar(0, 0, 255), 2, 8);
        cv::rectangle(frame, cv::Point(dr.box .tl().x, dr.box .tl().y - 20), cv::Point(dr.box .br().x, dr.box .tl().y), cv::Scalar(255, 0, 0), -1);

        std::string label = cv::format("%.2f", dr.confidence);
        label = classes_[dr.classId ] + ":" + label;

        cv::putText(frame, label, cv::Point(dr.box.x, dr.box.y + 6), 1, 2, cv::Scalar(0, 255, 0),2);
    }
}

3、classes.txt

官方yolov5s.pt模型,能够识别80种物体,classes.txt文件记录的就是这80种物体类别名,如下:

person
bicycle
car
motorbike
aeroplane
bus
train
truck
boat
traffic light
fire hydrant
stop sign
parking meter
bench
bird
cat
dog
horse
sheep
cow
elephant
bear
zebra
giraffe
backpack
umbrella
handbag
tie
suitcase
frisbee
skis
snowboard
sports ball
kite
baseball bat
baseball glove
skateboard
surfboard
tennis racket
bottle
wine glass
cup
fork
knife
spoon
bowl
banana
apple
sandwich
orange
broccoli
carrot
hot dog
pizza
donut
cake
chair
sofa
pottedplant
bed
diningtable
toilet
tvmonitor
laptop
mouse
remote
keyboard
cell phone
microwave
oven
toaster
sink
refrigerator
book
clock
vase
scissors
teddy bear
hair drier
toothbrush

五、效果

以本地视频文件1.mp4为例,效果如下:
在这里插入图片描述
可以看到,在我的机器上,视频卡顿现象非常严重,FPS较小。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/25746.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

7判断环的入口结点8输出倒数第k个

7.判断环的入口结点 第一次第二次看感觉都无从下手&#xff0c;还是看了题解&#xff0c;主要思路是&#xff1a; 假设前面无环的结点有a个&#xff0c;环有b个结点&#xff0c;则设置快慢结点之后&#xff0c;fast结点一次走两步&#xff0c;slow结点一次走一步。则相遇时fast…

《第一行代码》核心知识点:活动(Activity)的儿子叫碎片(Fragment)

《第一行代码》核心知识点&#xff1a;活动Activity的儿子叫碎片Fragment前言四、活动(Activity)的儿子叫碎片&#xff08;Fragment&#xff09;4.1 碎片是神马&#xff1f;4.2 碎片的基本使用4.3 向容器中动态添加碎片4.4 活动与碎片之间通信方法4.5 碎片的生命周期4.6 使用限…

重载单目运算符以及重载运算符的注意事项

一、单目运算符的重载 单目运算符可分为两种&#xff1a; 1&#xff09;可以放在前面&#xff0c;也可以放在后面的单目&#xff0c;如&#xff1a; -- 2&#xff09;只能放在前面的运算符&#xff1a;&#xff01; &#xff08;正号&#xff09; -&#xff08;负号&#x…

Python函数详解(四)——Python函数参数使用注意事项

今天继续给大家介绍Python相关知识&#xff0c;本文主要内容是Python函数参数使用注意事项。 在上文Python函数详解&#xff08;三&#xff09;——函数的参数传递进阶中&#xff0c;我们学习了函数参数的进阶内容。今天&#xff0c;我们来学习函数的参数使用注意事项。 一、P…

【微信小程序】使用 Cryptiojs 解密微信绑定手机号码

很抱歉断更了一段时间&#xff0c;因为最近在做一个项目比较忙&#xff0c;正好项目中小程序板块需要解密手机号码来提交给接口&#xff0c;小程序中虽然提供了获取手机号按钮点击事件&#xff1a;bindgetphonenumber&#xff0c;但是该事件的处理函数中只能获取到加密过的手机…

关于如何调节Mahony AHRS算法的参数

文章目录一、Mahony算法的控制系统特征多项式二、Kp, Ki参数调节方法三、其他自适应调参法我在之前的博客AHRS互补滤波&#xff08;Mahony&#xff09;算法及开源代码中曾提及Mahony算法的难点在于如何调节PI参数。 最近看到参考文献[1]&#xff0c;提出了基于无阻尼自由频率设…

C# 将一种类型的数组转换为另一种类型的数组

将一种类型的数组转换为另一种类型的数组 public static TOutput[] ConvertAll<TInput, TOutput>(TInput[] array, Converter<TInput, TOutput> converter); 参数: array: 要转换为目标类型的从零开始的一维 System.Array。 converter: …

【数据结构与算法】杨辉三角,相同字符的截取以及扑克牌

✨个人主页&#xff1a;bit me ✨当前专栏&#xff1a;数据结构 ✨每日一语&#xff1a;不要等到了你的人生垂暮&#xff0c;才想起俯拾朝花&#xff0c;且行且珍惜。 ArrayList题训&#x1f335; 一. 杨辉三角&#x1f334;二.相同字符的截取&#x1f332;三.扑克牌&#x1f…

【SpringCloud】02 搭建springcloud微服务项目,服务治理组件nacos,负载均衡ribbon,远程调用Openfeign

文章目录搭建springcloud微服务项目1. 微服务父工程2. 创建子模块-shop-common3. 创建子模块--shop-product4. 创建子模块--shop-order服务治理组件1. 如何使用nacos2. 微服务客户端连接到nacos注册中心3. 消费端如何通过nacos调用提供者负载均衡1. 自己控制负载均衡2. ribbon完…

Nginx配置SSL证书

目录 获得证书 步骤一&#xff1a;购买证书 步骤二&#xff1a;申请证书 ​编辑 下载证书及证书转换&#xff1a;​编辑 配置SSL证书 在Nginx目录下新建certificate目录&#xff0c;并将下载好的证书/私钥等文件上传至该目录&#xff08;与配置文件同级目录&#xff09;。…

LiDAR点云转换到大地坐标系——简单粗标定

目录一、LiDAR和IMU位姿标定1.1安装角度标定1.2安装位置标定1.3部分代码二、点云转换到当地水平坐标系2.1基本理论2.1.1坐标系2.1.1.1激光雷达2.1.1.2导航坐标系/当地水平坐标系/大地坐标系2.1.2惯性传感器原理2.2点云转换试验2.2.1试验场地2.2.2试验内容2.2.3点云变换效果Wind…

C语言日记 37 类的友元(1)(全局函数做友元)

根据36 类和对象-友元-全局函数做友元_哔哩哔哩_bilibili复现出如下代码&#xff1a; 一、&#xff08;只是&#xff09;访问&#xff08;公开&#xff09;内部成员&#xff1a; #include <iostream> using namespace std; class Building { private:int ws;//卧室 pub…

NewStarCTF 公开赛-web

week1 HTTP cookie 修改admin 源码发现key GET和POST传参即可 Head?Header! User-Agent: CTF Referer: ctf.com X-Forwarded-For: 127.0.0.1我真的会谢 信息泄露 robots.txt www.zip 源码 /.index.php.swp NotPHP 函数绕过 if(file_get_contents($_GET[data]) &qu…

数据备份一般有哪些方式,如何进行数据备份

在如今这个时代&#xff0c;数据于我们而言是特别重要的&#xff0c;一旦发生丢失&#xff0c;可能会带来严重后果&#xff0c;如果你也很苦恼如何保证这些重要数据的安全&#xff0c;小编建议一定要对重要数据进行备份&#xff0c;以防发生丢失的意外。数据备份一般有哪些方式…

设计一个缓存策略,动态缓存热点数据

&#x1f468;‍&#x1f4bb;个人主页&#xff1a; 才疏学浅的木子 &#x1f647;‍♂️ 本人也在学习阶段如若发现问题&#xff0c;请告知非常感谢 &#x1f647;‍♂️ &#x1f4d2; 本文来自专栏&#xff1a; 常见场景解决方案 &#x1f308; 每日一语&#xff1a;努力不一…

C语言 0 —— 信息在计算机中的表示

计算机的电路 由 逻辑门电路组成。一个逻辑门电路可以看成为一个开关&#xff0c;每个开关的状态是“开” 则 高电位 对应 1 或者 “关” 则 低电位 对应 0 &#xff0c; 那么1和0 刚刚好用二进制数来表示&#xff1a; 每个位只能取1和0 &#xff0c;称为 one 个 bit &#…

谈一谈关于Linux内核编译详解原理

前言&#xff1a;为什么要做这个启动盘&#xff0c;因为内核编译是很危险的&#xff0c;中间出了错系统则直接崩溃&#xff0c;然后就无法开机了&#xff0c;你将看到一个_在你的左上角闪烁。知道启动盘可以帮你从外置设备启动系统&#xff0c;能启动系统才能恢复系统。1.编译前…

Java 线程和反射---尚硅谷Java视频学习

1.Java程序在运行得时候默认就会产生一个进程2.这个进程会有一个主线程3.代码都在主线程中执行 线程的生命周期 线程的执行方式 public class Java02_Thread {public static void main(String[] args) throws Exception {// TODO 线程 - 执行方式&#xff08;串行&#xff0c…

ASP.NET Core 3.1系列(14)——分布式缓存Redis的使用

1、前言 前一篇博客介绍了ASP.NET Core中本地缓存MemoryCache的使用方法。相较于本地缓存&#xff0c;分布式缓存更加适合大多数项目应用场景&#xff0c;下面就来介绍一下如何在ASP.NET Core中对Redis缓存进行相关操作。 2、分布式缓存接口——IDistributedCache 对于分布式…

pytorch深度学习实战24

第二十四课 VGG网络 VGG是Oxford的Visual Geometry Group的组提出的&#xff08;大家应该能看出VGG名字的由来了&#xff09;。该网络是在ILSVRC 2014上的相关工作&#xff0c;主要工作是证明了增加网络的深度能够在一定程度上影响网络最终的性能。VGG有两种结构&#xff0c;分…