yolov5部署 单线程与多线程对比

单线程

部署代码可参考:

Yolov5 ONNX Runtime 的 C++部署_爱钓鱼的歪猴的博客-CSDN博客

main.cpp

#include "detector.h"
#include <chrono>
using namespace std;



// 识别线程
void *detect_thread_entry(void *para){

}

int main(int argc, char *argv[])
{
    auto start1 = std::chrono::system_clock::now();
    Detector detector;
    bool isGPU=false;
    Utils utils;
    const vector<string> classNames=utils.loadNames("/home/lrj/work/file/coco.names");

    if(classNames.empty()){
        cerr<<"Error: Empty class names file"<<endl;
        return -1;
    }
    cv::Mat image;
    vector<Detection> result;

    cv::VideoCapture capture(2);
    if (!capture.isOpened())
        return 1;

    auto end1 = std::chrono::system_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end1 - start1);

    cout << " " << endl;
    printf("init time use: %ld ms", duration);

    while(1){
        auto start2 = std::chrono::system_clock::now();
        capture >> image;

        try{
            detector.YOLODetector(isGPU,cv::Size(640,640));
            cout<<"Model was initialized......"<<endl;

            int ret = detector.detect(image,0.4,0.4, result);

            }catch(const exception& e){
                cerr<<e.what()<<endl;
                return -1;
            }

    utils.visualizeDetection(image,result,classNames);


    auto end2 = std::chrono::system_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end2 - start2);
    string text = "time use: " + std::to_string(duration.count()) + "ms";
    cv::putText(image, text, cv::Point(30, 30), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(255,0,0),2);

    imshow("result", image);
    if(cv::waitKey(1) == 'q') break;

    }
    return 0;
}

这里是单线程,每帧获取耗时200ms左右,也就是fps大概为5;

多线程

#include "detector.h"
#include <chrono>
#include <pthread.h>
#include <unistd.h>
#include "utils.h"

using namespace std;

struct ThreadParams {
    vector<Detection> result_;
};

cv::Mat algorithm_image = cv::Mat::zeros(480,640,CV_8UC3);
//pthread_cond_t img_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t img_lock;
pthread_mutex_t result_lock;

Utils utils;
const vector<string> classNames=utils.loadNames("/home/lrj/work/file/coco.names");

 //识别线程
void *detect_thread_entry(void *para){

    // 初始化
    Detector detector;
    bool isGPU=false;
    detector.YOLODetector(isGPU,cv::Size(640,640));
    cout<<"Model was initialized......"<<endl;

    ThreadParams *pThreadParams = (ThreadParams *) para;
//    vector<Detection> result = pThreadParams->result_;
    cv::Mat image;
    while(1){

            auto start = std::chrono::system_clock::now();

            // 阻塞等待图像可用
            if(algorithm_image.empty()){
                cerr << "Error: Failed to retrieve image frame" << endl;
                usleep(5);
                continue;

            }

            pthread_mutex_lock(&img_lock); // 加锁
            image = algorithm_image.clone(); // 复制图片
            pthread_mutex_unlock(&img_lock); // 解锁



            pthread_mutex_lock(&result_lock); // 加锁
            int ret = detector.detect(image,0.4,0.4, pThreadParams->result_); // 检测
            pthread_mutex_unlock(&result_lock); // 解锁


            auto end = std::chrono::system_clock::now();
            auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
            string text = "yolov5n detect time use: " + std::to_string(duration.count()) + "ms";
            cout << text + "\n" + "\n" << endl;

            if(pThreadParams->result_.size() <=0){
                usleep(1000);
                continue;
            }

    }
    return NULL;
}

int main(int argc, char *argv[])
{
    if(classNames.empty()){
            cerr<<"Error: Empty class names file"<<endl;
            return -1;
    }

    ThreadParams threadParams;
    threadParams.result_ = std::vector<Detection> ();
    pthread_t mTid;


    // 1.打开摄像头
    cv::VideoCapture camera(2);
    if (!camera.isOpened())
            return -1;
    int width = camera.get(cv::CAP_PROP_FRAME_WIDTH);
    int height = camera.get(cv::CAP_PROP_FRAME_HEIGHT);
    int fps = camera.get(cv::CAP_PROP_FPS);
    cout << width << "  ||" <<height << fps << endl;


    // 跳过前10帧
    int skip = 10;
    while(skip--){
            camera >> algorithm_image;
    }

    // 2创建识别线程,以及图像互斥锁
    pthread_mutex_init(&img_lock, NULL);
    pthread_mutex_init(&result_lock, NULL);

    pthread_create(&mTid, NULL, detect_thread_entry,(void*)&threadParams);


    // 3.(取流 + 显示)循环
    cv::Mat img;
    while(1){
            // 4.1 取流
            pthread_mutex_lock(&img_lock);
            camera >> algorithm_image;
            img = algorithm_image.clone();
//            pthread_cond_signal(&img_cond); // 通知识别线程图像可用
            pthread_mutex_unlock(&img_lock);

            // 4.2 显示
            pthread_mutex_lock(&result_lock); // 加锁
            utils.visualizeDetection(img,threadParams.result_,classNames);
            pthread_mutex_unlock(&result_lock); // 解锁
            cv::imshow("result", img);
            if(cv::waitKey(1) == 'q') break;
//            usleep(150*1000);
    }

//    pthread_join(mTid, NULL); // 等待识别线程的结束
    pthread_mutex_destroy(&img_lock);
    pthread_mutex_destroy(&result_lock);
    return 0;
}

这里主线程(main函数)负责获取图像及展示图像;识别线程负责yolov5检测,每帧耗时170ms左右(CPU是比较慢)。

其实这里获取主线程获取图像很快,主要是检测比较耗时;我感觉主线程获取的图像一直在排队等待被检测。

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【正版系统】2023热门短剧SAAS版开源 | 小程序+APP+公众号H5

当我们在刷百度、D音、K手等各种新闻或短视频时经常会刷到剧情很有吸引力的短剧广告&#xff0c;我们点击广告链接即可进入短剧小程序&#xff0c;小程序运营者通过先免费看几集为诱耳然后在情节高潮时弹出充值或开VIP会员才能继续看的模式来赚钱&#xff0c;以超级赘婿、乡村小…

HTML5 基础标签

目录 前言 标题标签 段落标签 换行标签和水平线标签 文本格式化标签 图像标签 超链接标签 多媒体标签 列表标签 无序列表 有序列表 表格 合并单元格 表单 无语义的布局标签 字符实体 前言 当今互联网时代&#xff0c;网页是我们获取信息、交流和展示自己的重要渠…

【RocketMQ入门-安装部署与Java API测试】

【RocketMQ入门-安装部署与Java API测试】 一、环境说明二、安装部署三、Java API 编写Producer和Consumer进行测试四、小结 一、环境说明 虚拟机VWMare&#xff1a;安装centos7.6操作系统源码包&#xff1a;rocketmq-all-5.1.3-source-release.zip单master部署&#xff0c;在…

如何微调优化你的ChatGPT提示来提高对话质量

ChatGPT会话质量很大程度上取决于微调优化提示的艺术。本文旨在阐明微调提示的复杂性&#xff0c;以确保你可以充分发挥ChaGPT这一颠覆性工具的潜力。 与ChatGPT对话的关键部分是“提示”。即&#xff1a;你输入的问题或陈述&#xff0c;它决定了人工智能的响应。类似于引导对…

软件测试基础篇——Docker

1、docker技术概述 docker描述&#xff1a;docker是一项虚拟化的容器技术&#xff08;类似于虚拟机&#xff09;&#xff0c;docker技术给使用者提供一个平台&#xff0c;在该平台上可以利用提供的容器&#xff0c;对每一个应用程序进行单独的封装隔离&#xff0c;每一个应用程…

Blender如何给fbx模型添加材质贴图并导出带有材质贴图的模型

推荐&#xff1a;使用 NSDT场景编辑器快速助你搭建可二次编辑的3D应用场景 此教程适合新手用户&#xff0c;专业人士直接可直接绕路。 本教程中介绍了利用Blender建模软件&#xff0c;只需要简单几步就可以为模型添加材质贴&#xff0c;图&#xff0c;并且导出带有材质的模型文…

netty基础与原理

Netty线程模型和Reactor模式 简介&#xff1a;reactor模式 和 Netty线程模型 设计模式——Reactor模式&#xff08;反应器设计模式&#xff09;&#xff0c;是一种基于 事件驱动的设计模式&#xff0c;在事件驱动的应用中&#xff0c;将一个或多个客户的 服务请求分离&#x…

Verilog求log10和log2近似

Verilog求log10和log2近似 Verilog求10对数近似方法&#xff0c;整数部分用位置index代替&#xff0c;小数部分用查找表实现 参考&#xff1a; Verilog写一个对数计算模块Log2(x) FPGA实现对数log2和10*log10

【LangChain学习】基于PDF文档构建问答知识库(三)实战整合 LangChain、OpenAI、FAISS等

接下来&#xff0c;我们开始在web框架上整合 LangChain、OpenAI、FAISS等。 一、PDF库 因为项目是基于PDF文档的&#xff0c;所以需要一些操作PDF的库&#xff0c;我们这边使用的是PyPDF2 from PyPDF2 import PdfReader# 获取pdf文件内容 def get_pdf_text(pdf):text "…

SQL常见命令语句

1.连接数据库 mysql (-h IP) -u root -p 密码2.查看数据库 show databases3.使用数据库 use db_name4.查看表 show tables [from db_name]5.查看表结构 desc tb_name6.创建、删除、选择数据库 create database db_namedrop database db_nameuse db_name7.数据类型 参考链…

技术应用:Docker安全性的最佳实验|聊聊工程化Docker

&#x1f525; 技术相关&#xff1a;《技术应用》 ⛺️ I Love you, like a fire! 文章目录 首先&#xff0c;使用Docker Hub控制访问其次&#xff0c;保护密钥写在最后 不可否认&#xff0c;能生存在互联网上的软件都是相互关联的&#xff0c;当我们开发一款应用程序时&#x…

(二)结构型模式:1、适配器模式(Adapter Pattern)(C++实现示例)

目录 1、适配器模式&#xff08;Adapter Pattern&#xff09;含义 2、适配器模式应用场景 3、适配器模式的UML图学习 4、C实现适配器模式的示例 1、适配器模式&#xff08;Adapter Pattern&#xff09;含义 将一个接口转换为客户端所期待的接口&#xff0c;从而使两个接口…

JVM 查看配置 jinfo 及使用 jstat,查看堆栈jstack及GC

1. Jinfo 查看正在运行的Java应用程序的扩展参数: 包含 JVM 参数与 java 系统参数 命令&#xff1a; jinfo pid 2 jstat 查看堆内存使用情况及 GC 回收频率等&#xff1a; jstat [-命令选项] [vmid] [间隔时间(毫秒)] [查询次数] 2.1 jstat -gc pid 最常用&#xff0c;可…

MySQL数据库----------安装anaconda---------python与数据库的链接

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

【Linux】进程间通信之管道

【Linux】进程间通信之管道 进程间通信进程间通信目的进程间通信的方式 管道&#xff08;内核维护的缓冲区&#xff09;匿名管道&#xff08;用于父子间进程间通信&#xff09;简单使用阻塞状态读写特征非阻塞状态读写特征 匿名管道特点命名管道 匿名管道与命名管道的区别 进程…

时序预测 | MATLAB实现基于CNN卷积神经网络的时间序列预测-递归预测未来(多指标评价)

时序预测 | MATLAB实现基于CNN卷积神经网络的时间序列预测-递归预测未来(多指标评价) 目录 时序预测 | MATLAB实现基于CNN卷积神经网络的时间序列预测-递归预测未来(多指标评价)预测结果基本介绍程序设计参考资料 预测结果 基本介绍 1.Matlab实现CNN卷积神经网络时间序列预测未…

中国首款量子计算机操作系统本源司南 PilotOS正式上线

中国安徽省量子计算工程研究中心近日宣布&#xff0c;中国国产量子计算机操作系统本源司南 PilotOS 客户端正式上线。 如果把量子芯片比喻成人的“心脏”&#xff0c;那么量子计算机操作系统就相当于人的“大脑”&#xff0c;量子计算应用软件则是人的“四肢”。 据安徽省量子…

C++入门篇7---string类

所谓的string类&#xff0c;其实就是我们所说的字符串&#xff0c;本质和c语言中的字符串数组一样&#xff0c;但是为了更符合C面向对象的特性&#xff0c;特地将它写成了一个单独的类&#xff0c;方便我们的使用 对其定义有兴趣的可以去看string类的文档介绍&#xff0c;这里…

运维监控学习笔记3

DELL的IPMI页面的登录&#xff1a; 风扇的状态&#xff1a; 电源温度&#xff1a;超过70度就告警&#xff1a; 日志信息&#xff1a; 可以看到更换过磁盘。 iDRAC的设置 虚拟控制台&#xff1a;启动远程控制台&#xff1a; 可以进行远程控制。 机房工程师帮我们接远程控制&…

opencv 基础54-利用形状场景算法比较轮廓-cv2.createShapeContextDistanceExtractor()

注意&#xff1a;新版本的opencv 4 已经没有这个函数 cv2.createShapeContextDistanceExtractor() 形状场景算法是一种用于比较轮廓或形状的方法。这种算法通常用于计算两个形状之间的相似性或差异性&#xff0c;以及找到最佳的匹配方式。 下面是一种基本的比较轮廓的流程&…