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

news2024/11/26 20:00:45

单线程

部署代码可参考:

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是比较慢)。

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

 

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

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

相关文章

分布式应用:Zabbix监控MariaDB

目录 一、理论 1.Zabbix监控MariaDB 二、实验 1.Zabbix监控MariaDB 一、理论 1.Zabbix监控MariaDB &#xff08;1&#xff09;环境 zabbix服务端&#xff1a;192.168.204.214 zabbix客户端&#xff1a;192.168.204.215 &#xff08;2&#xff09;MareaDB安装 安装 za…

文献阅读:AnnoLLM: Making Large Language Models to Be Better Crowdsourced Annotators

文献阅读&#xff1a;AnnoLLM: Making Large Language Models to Be Better Crowdsourced Annotators 1. 文章简介2. 方法介绍3. 实验考察 1. 实验结果2. 消解实验3. Consistency & Stability 4. 结论 & 思考 文献链接&#xff1a;https://arxiv.org/abs/2303.16854 …

STM32F429IGT6使用CubeMX配置SPI通信(W25Q256芯片)

1、硬件电路 需要系统性的看一下W25Q256芯片手册 2、设置RCC&#xff0c;选择高速外部时钟HSE,时钟设置为180MHz 3、配置SPI 4、生成工程配置 5、相关代码 #define sFLASH_ID 0XEF4019 // W25Q256#define SPI_FLASH_PageSize 256 #define SPI_FLASH_PerWritePageSize 256#def…

爬虫小白-如何辨别请求头referer/origin反爬

目录 一、网站分析二、最终代码一、网站分析 1、网站,研究这块数据从哪个接口来的 2、反爬参数:请求头referer/origin校验和x-api-key 3、详细分析流程,看b站十一姐时一视频, 或者知识星球时光漫漫图文文章 二、最终代码 # -*- coding: utf-8 -*- # @Time : 2023-08-13

为了监控上厕所次数,我开发了一个软件

背景 最近整了一个好玩的东西&#xff0c;一个快捷指令&#xff0c;实现点击之后显示当前的日期&#xff0c;同时后台将这个时间记录到一个文件里。文件在icloud上&#xff0c;实现多个设备的同步。话不多说&#xff0c;先看看效果吧。 这个是我的“软件”图标&#xff1a; 怎…

网络安全 Day30-容器架构上

容器架构上 1. 容器架构1.1 什么是容器1.2 容器 vs 虚拟机(化) :star::star:1.3 Docker极速上手指南1&#xff09;使用rpm包安装docker2) docker下载镜像加速的配置3) 载入镜像大礼包&#xff08;老师资料包中有&#xff09; 1.4 Docker使用案例1&#xff09; 案例01&#xff1…

第12集丨Vue 江湖 —— 内置指令

目录 一、v-text二、v-html2.1 基本使用2.2 cookie原理2.2.1 登入成功后cookies的信息2.2.2 手动增加cookie值2.2.3 cookie edit 三、v-cloak3.1 案例 四、v-once五、v-pre 到本节为止&#xff0c;我们学过的指令: v-bind &#xff1a;单向绑定解析表达式v-model &#xff1a;…

idea生成springboot单元测试用例

1、找到需要生成单元测试的类型&#xff0c;右键Go To -> Test 2、选择JUnit4 和勾选需要测试的方法 3、查看自动生成的文件 public class CategoryMapperTest {Testpublic void findById() {}Testpublic void queryById() {} } 4、添加测试代码 RunWith(SpringRunner.cla…

【JavaEE】懒人的福音-MyBatis框架—[单表]增删改查等常规操作

【JavaEE】MyBatis框架要点总结&#xff08;2&#xff09; 文章目录 【JavaEE】MyBatis框架要点总结&#xff08;2&#xff09;1. 单表查看操作1.1 (条件查询)通过id查找用户1.1.1 接口上声明方法1.1.2 xml文件中去实现方法1.1.3 测试 1.2 传递参数的重点问题&#xff1a;sql注…

【LeetCode周赛】LeetCode第358场周赛

LeetCode第358场周赛 数组中的最大数对和翻倍以链表形式表示的数字限制条件下元素之间的最小绝对差 数组中的最大数对和 给你一个下标从0开始的整数数组nums。请你从nums中找出和最大的一对数&#xff0c;且这两个数数位上最大的数字相等。 返回最大和&#xff0c;如果不存在满…

手机商城网站的分析与设计(论文+源码)_kaic

目录 摘 要 1 1 绪论 2 1.1选题背景意义 2 1.2国内外研究现状 2 1.2.1国内研究现状 2 1.2.2国外研究现状 3 1.3研究内容 3 2 网上手机商城网站相关技术 4 2.1.NET框架 4 2.2Access数据库 4 2.3 JavaScript技术 4 3网上手机商城网站分析与设…

基于grpc从零开始搭建一个准生产分布式应用(3) - GRPC实现

本章开始会进入GRPC子专题&#xff0c;先实现前面章节中提到的例子。然后就使用的知识点展开全面的描述。本章代码任务&#xff1a;1、实现一个简单的GRPC服务&#xff1b;2、实现GRPC拦截器。 本章的代码承接上一章的代码进行迭代。因模块间存在相互依赖关系&#xff0c;读者一…

SpringBoot复习:(42)WebServerCustomizer的customize方法是在哪里被调用的?

ServletWebServletAutoConfiguration类定义如下&#xff1a; 可以看到其中通过Import注解导入了其内部类BeanPostProcessorRegister。 BeanPostProcessor中定义的registerBeanDefinition方法会被Spring容器调用。 registerBeanDefinitions方法调用了RegistrySyntheticBeanIf…

【MongoDB】一文带你快速掌握MongoDB数据库和集合基础操作

文章目录 前言一、案例需求二、数据库操作1. 选择和创建数据库2. 数据库的删除 三、集合操作1. 集合的显式创建&#xff08;了解&#xff09;2. 集合的隐式创建3. 集合的删除 总结 前言 为了巩固所学的知识&#xff0c;作者尝试着开始发布一些学习笔记类的博客&#xff0c;方便…

pycorrector一键式文本纠错工具,整合了BERT、MacBERT、ELECTRA、ERNIE等多种模型,让您立即享受纠错的便利和效果

pycorrector&#xff1a;一键式文本纠错工具&#xff0c;整合了Kenlm、ConvSeq2Seq、BERT、MacBERT、ELECTRA、ERNIE、Transformer、T5等多种模型&#xff0c;让您立即享受纠错的便利和效果 pycorrector: 中文文本纠错工具。支持中文音似、形似、语法错误纠正&#xff0c;pytho…

激活函数总结(七):激活函数补充(Softsign、Threshold、Sinc)

激活函数总结&#xff08;七&#xff09;&#xff1a;激活函数补充 1 引言2 激活函数2.1 Softsign激活函数2.2 Threshold (Unit step activation function) 激活函数2.3 Sinc激活函数 3. 总结 1 引言 在前面的文章中已经介绍了介绍了一系列激活函数 (Sigmoid、Tanh、ReLU、Lea…

Java-运算符和控制语句(下)(基于c语言的补充)

输出到控制台 System.out.println(msg); // 输出一个字符串, 带换行 System.out.print(msg); // 输出一个字符串, 不带换行 System.out.printf(format, msg); // 格式化输出 从键盘输入 使用 Scanner 读取字符串/整数/浮点数 首先需要导入util包 自动导入util包 这里把回车看…

21-因子个数

题目 一个正整数可以分解成一个或多个数组的积。例如362*2*3*3&#xff0c;即包含2和3两个因子。NowCoder最近在研究因子个数的分布规律&#xff0c;现在给出一系列正整数&#xff0c;他希望你开发一个程序输出每个正整数的因子个数。 输入描述: 输入包括多组数据。 每组数…

Ubuntu22开机后正上方弹出“Printer addded(已添加打印)”等提示框

一、问题描述 Ubuntu22开机后正上方弹出“Printer addded&#xff08;已添加打印&#xff09;”等提示框。如下 二、问题分析 1、列出当前所有开机启动服务 service --status-all msmoshui:~$ service --status-all[ - ] alsa-utils[ - ] anacron[ ] apparmor[ ] app…

预测算法|改进粒子群算法优化极限学习机IDM-PSO-ELM

回归拟合&#xff1a; 分类 本文是作者的预测算法系列的第四篇&#xff0c;前面的文章中介绍了BP、SVM、RF及其优化&#xff0c;感兴趣的读者可以在作者往期文章中了解&#xff0c;这一篇将介绍——极限学习机 过去的几十年里基于梯度的学习方法被广泛用于训练神经网络&am…