首页 > 编程语言 >在国产芯片上实现YOLOv5/v8图像AI识别-【2.3】RK3588上使用C++启用多线程推理更多内容见视频

在国产芯片上实现YOLOv5/v8图像AI识别-【2.3】RK3588上使用C++启用多线程推理更多内容见视频

时间:2024-08-09 12:53:03浏览次数:17  
标签:YOLOv5 img RK3588 height padding width letterbox 多线程 cv

本专栏主要是提供一种国产化图像识别的解决方案,专栏中实现了YOLOv5/v8在国产化芯片上的使用部署,并可以实现网页端实时查看。根据自己的具体需求可以直接产品化部署使用。

B站配套视频:https://www.bilibili.com/video/BV1or421T74f
在这里插入图片描述

基础背景

对于国产化芯片来说,是采用NPU进行推理,无论从性能、功耗、软件环境来说都是比不过英伟达显卡的。所以在进行推理的时候除了实现我们正常的业务逻辑还需要将核心推理部分改造成线程池,实现快速推理。

在此之前我们大概知道推理需要分成三个部分,预处理、推理、后处理。此处我们参照上节课的代码、官方模型来和大家讲解。

预处理部分

首先我们看一下模型的输入部分,是640640,这个是在我们训练的时候就决定好了,所以进行推理的时候我们也一样先要把图片处理成640640。

在这里插入图片描述

除此之外,使用过opencv的同学应该知道,opencv读取图片时候一半都是BGR的颜色通道,预处理的时候我们一样要把图片处理成RGB才可以。

// yolo的预处理
void cvimg2tensor(const cv::Mat &img, uint32_t width, uint32_t height, tensor_data_s &tensor)
{
    // img has to be 3 channels
    if (img.channels() != 3)
    {
        NN_LOG_ERROR("img has to be 3 channels");
        exit(-1);
    }
    // BGR to RGB
    cv::Mat img_rgb;
    cv::cvtColor(img, img_rgb, cv::COLOR_BGR2RGB);
    // resize img
    cv::Mat img_resized;
    NN_LOG_DEBUG("img size: %d, %d", img.cols, img.rows);
    NN_LOG_DEBUG("resize to: %d, %d", width, height);
    cv::resize(img_rgb, img_resized, cv::Size(width, height), 0, 0, cv::INTER_LINEAR);
    // BGR to RGB
    memcpy(tensor.data, img_rgb.data, tensor.attr.size);
}

此处有一个小知识点,opencv的cv::resize是将图片进行强制拉伸,也就是图片中的元素都会变形。其实还有别的预处理方法,比如将图片扩充到640*640大小,然后多余部分进行黑色填充,一样可以实现效果,而且识别结果较好,下面就是实例代码。

LetterBoxInfo letterbox(const cv::Mat &img, cv::Mat &img_letterbox, float wh_ratio)
{
    // img has to be 3 channels
    if (img.channels() != 3)
    {
        NN_LOG_ERROR("img has to be 3 channels");
        exit(-1);
    }
    float img_width = img.cols;
    float img_height = img.rows;

    int letterbox_width = 0;
    int letterbox_height = 0;

    LetterBoxInfo info;
    int padding_hor = 0;
    int padding_ver = 0;

    if (img_width / img_height > wh_ratio)
    {
        info.hor = false;
        letterbox_width = img_width;
        letterbox_height = img_width / wh_ratio;
        info.pad = (letterbox_height - img_height) / 2.f;
        padding_hor = 0;
        padding_ver = info.pad;
        
    }
    else
    {
        info.hor = true;
        letterbox_width = img_height * wh_ratio;
        letterbox_height = img_height;
        info.pad = (letterbox_width - img_width) / 2.f;
        padding_hor = info.pad;
        padding_ver = 0;
    }
    // 使用cv::copyMakeBorder函数进行填充边界
    cv::copyMakeBorder(img, img_letterbox, padding_ver, padding_ver, padding_hor, padding_hor, cv::BORDER_CONSTANT, cv::Scalar(0, 0, 0));
    return info;
}

推理部分

yolo的推理部分官方已经帮我进行了较好的封装,此处我们继续沿用就好,由于是调用底层的API,外部封装代码我们就不过多说明了。感兴趣的朋友可以看视频,其中我们会简单过一下。

后处理部分

模型在推理的时候会图片拆分成三个大小去识别,8080、4040、20*20,然后通过极大值抑制,将识别的结果计算出来。我们可以从模型里面看到模型里面输出了这三个部分。
在这里插入图片描述

但是这部分的计算处理其实在NPU中的速度并不快,我们会对模型进行修改,然后将后处理部分放到CPU中进行运算,图中就是我们修改之后的模型样子。具体处理方式官方也已经给出我们不做过多描述,关于模型如何修改,我们会在小节课的训练导出和大家说。

在这里插入图片描述 在这里插入图片描述

多线程处理

虽然进行了模型的裁剪和量化,但是国产嵌入式芯片毕竟起步较晚,受限于性能,对于1080P的视频来说可能推理速度只能每秒2-5帧左右,对于这种新能是远远无法达到产品使用要求的,所以我们需要进行多线程处理,让更多的线程去参与到推理过程中,提高整体性能效率。
更多内容查看视频>>>>>>>>>>>>>>>>> https://www.bilibili.com/video/BV1or421T74f](https://www.bilibili.com/video/BV1or421T74f

多媒体流处理

此处我们多媒体流处理使用的是zlmediakit,这是一款国人开发的流媒体服务器,也提供了相关C++的接口,几乎所有做流媒体的项目都会使用到,但是关于它C++的使用会有所不同需要另外学习一下。
更多内容查看视频>>>>>>>>>>>>>>>>> https://www.bilibili.com/video/BV1or421T74f](https://www.bilibili.com/video/BV1or421T74f

标签:YOLOv5,img,RK3588,height,padding,width,letterbox,多线程,cv
From: https://blog.csdn.net/weixin_41864178/article/details/140925431

相关文章

  • JAVA多线程的使用和创建的几种方式
    Thrad创建和使用创建实体类,继承Thread实现run()方法调用start()方法publicclassThreadDemoextendsThread{Loggerlogger=LoggerFactory.getLogger(ThreadDemo.class);privateStringtaskName;publicStringgetTaskName(){return......
  • 多线程系列:线程中包含子线程
    多线程系列:线程中包含子线程这里展示的多线程基本包含了常见的多线程操作:实现线程中包含子线程;计算子线程耗时展示一个函数如何通过参数传递进行多线程一个线程调用一个函数的情况代码示例importthreadingimporttimefrompprintimportpprintimportqueue#假......
  • 多线程学习总结
    Java多线程学习总结本章目标理解线程的基本概念理解线程与进程的区别熟悉线程的实现方式了解线程的管理熟悉线程的生命周期掌握线程同步掌握线程池了解线程通信掌握线程定时器什么是进程进程就是正在运行的程序,它是系统进行资源分配和调度的基本单位,各个进程之间......
  • Java多线程编程中的常见问题及优化策略
    Java多线程编程中的常见问题及优化策略大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!多线程的基本概念在Java中,多线程是指程序中可以同时运行多个线程,每个线程可以执行不同的任务。多线程可以提高程序的执行效率,但同时也带来了一些挑战。线程安全......
  • yolov5更换主干网络shufflent
    目录1.网络结构解析1.1创建yolov5s_shufflent_v2_X0_5.yaml文件2.对common.py末尾进行添加 3.修改yolo.py1.网络结构解析1.可以先看看shufflenet_v2的网络结构importtorchfromtorchimportnnfromtorchvisionimportmodelsfromtorchinfoimportsummaryc......
  • yolov5主干网络换残差18
    目录1.网络结构​编辑 1.1三层如下定义1.2在common.py后面加入如下刚刚定义的网络,就是上面的代码的一部分2. 如此修改网络的yaml文件,yolov5n_res18.yaml3. 修改yolo网络并运行1.网络结构残差18网络如下可做出如下修改 1.1三层如下定义importtorchfrom......
  • RK3588安装rknn-toolkit-lite2
    RK3588安装rknn-toolkit-lite2一、下载rknn-toolkit2包:sudogitclonehttps://gitclone.com/github.com/airockchip/rknn-toolkit2二、安装进入到所在包的位置,然后解压:unziprknn-toolkit2-master.zip进入rknn-toolkit-lite2所在路径:cdrknn-toolkit2-master/rknn-t......
  • java之多线程篇
    一、基本概念1.什么是线程?线程就是,操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。简单理解就是:应用软件中互相独立,可以同时运行的功能2.什么是多线程?有了多线程,我们就可以让程序同时做多件事情3.多线程的作用?提高效率4.线程的应用场......
  • 多线程执行函数(迭代器版本)
    #include<iostream>#include<numeric>#include<thread>#include<vector>template<typenameIterator,typenameT>structthreadBlock{voidoperator()(T(*func)(Iterator,Iterator,T),Iteratorfirst,Iteratorlast,T&am......
  • RK3588—安装Linux系统以及环境配置
    neardiRK3588—安装Linux系统一、安装linux系统由于买的是neardi的LPB3588开发板,直接找它的官方手册:http://wiki.neardi.com/wiki/LPB3588/zh_CN/ 二、其他问题(1)无法读取U盘sudochmod777/media/<username>/(这里是sudochmod777/media/neardi/)(2)pip3安装s......