yolo导出的onnx怎么使用onnxruntime调用_yolo 调用onnx 推理-程序员宅基地

技术标签: YOLO  yolo  

1.上几篇文件,写了怎样标注数据,获取yolo数据,怎样训练数据。这篇文章写下,怎样使用yolo训练好的网络进行推理,怎样使用onnxruntime调用网络推理。

2.yolo模型训练后推理,主要分两种,一种是使用yolo官方提供的api推理,一种使用onnx模式推理。

3.使用yolo官方的api推理:
###把qimage图片转成mat函数
def CoverQImageToMat(self):
ptr_=self.CurrentImage.constBits() ###用pyqt加载的图片
###QImage内部是按照每个像素4个字节的方式组织数据的,即使最后一个alpha通道没有使用,也用0xff来填充
image_mat_=np.array(ptr_).reshape(self.CurrentImage.height(),self.CurrentImage.width(),4)
image_mat_rgb_=cv2.cvtColor(image_mat_,cv2.COLOR_RGBA2RGB)
return image_mat_rgb_

self.Model=YOLO(‘best.pt’)###加载模型
image_mat_ = self.CoverQImageToMat()###图片转换,把图片转成opencv的mat
results_=self.Model(image_mat_)###推理获取结果
for result_ in results_: #####循环结果
boxes_ = result_.boxes ####获取boxes
for box_ in boxes_: ####循环boxes
x_,y_,w_,h_=box_.xywh[0] ####获取识别到对象的左上角坐标,长,宽
c=box_.cls ####获取属于第几类
cls_=self.Model.names[int] ####查询类名
self.BoxX.append(float(x_))
self.BoxY.append(float(y_))
self.BoxWidth.append(float(w_))
self.BoxHeight.append(float(h_))
self.BoxClass.append(cls_)

4.yolo官方提供的api推理,可以按照官方文档就可以推理,这里还在讲下导出的onnx模型后,怎么加载推理。

4.1self.Model.export(format=‘onnx’)###把yolo的模型导出成onnx格式

4.2 使用onnxruntime调用onnx推理。首先安装onnxruntime.lib,这里使用的版本是
onnxruntime-1.16.3-cp311-cp311-win_amd64.whl
onnx-1.15.0-cp311-cp311-win_amd64.whl
这两个文件可以到https://pypi.org/收索下载,使用pip离线安装

4.3 代码导入onnxruntime
import onnxruntime as ort
import onnx

self.OnnxModel = ort.InferenceSession(‘best.onnx’)###加载onnx模型

###推理函数

def UseOnnxInference(self):      	  
  	  if (self.CurrentImage.width() > 0) & (self.CurrentImage.height() > 0):
  	  	####清空结果缓存
        self.BoxY.clear()	
        self.BoxX.clear()
        self.BoxWidth.clear()
        self.BoxHeight.clear()
        self.BoxClass.clear()
        
        #获取onnx模型输入点
        inputs =self.OnnxModel.get_inputs()
        len(inputs)
        input_onnx_=inputs[0]
        print("Name:",input_onnx_.name)##输入节点名称
        print("Type:", input_onnx_.type)##数据格式
        print("Shape:",input_onnx_.shape)###数据维度

        image_mat_ = self.CoverQImageToMat()  ###图片转换
        print("ImageMatShape:",image_mat_.shape)####查看图片的维度

        img_width_ = image_mat_.shape[1]  ###获取图片输入输出
        img_height_ = image_mat_.shape[0]###获取图片输入输出

        target_image_height_ = 640###输入到onnx推理的图片大小
        target_image_width_ = 640###输入到onnx推理的图片大小


        scale_precentage_=min(target_image_height_/image_mat_.shape[0],target_image_width_/image_mat_.shape[1])
        image_mat_=cv2.resize(image_mat_,None,fx=scale_precentage_,fy=scale_precentage_)#缩放成onnx推理的图片大小

        image_np_=np.array(image_mat_)###图片转成np数组
        print("ImageNpShape:", image_np_.shape)####查看下维度

        image_np_=image_np_.transpose(2,0,1)##转成通道在前面的维度
        print("ImageNpShape:", image_np_.shape)

        image_np_=image_np_.reshape(1,3,640,640)##添加一个新维度
        print(image_np_[0, 0, 0, 0])
        print("ImageNpShape:", image_np_.shape)

        image_np_ = image_np_.astype(np.float32)####把数据转成float32格式

        image_np_=image_np_/255.0##数据归一化
        print(image_np_[0, 0, 0, 0])

        ###获取输出点
        outputs=self.OnnxModel.get_outputs()
        output_onnx_=outputs[0]
        print("Name:",output_onnx_.name)###输出节点名称
        print("Type:",output_onnx_.type)###输出节点格式
        print("Shape:",output_onnx_.shape)###输出节点维度

        ###运行推理
        outputs=self.OnnxModel.run(["output0"],{"images":image_np_})
        len(outputs)
        
        ###outputs处理
        output_onnx_=outputs[0][0]
        print("OutputOnxxShape:",output_onnx_.shape)

        ###转换 行列
        output_onnx_=output_onnx_.transpose()
        print("OutputOnxxShape:", output_onnx_.shape)
        row=output_onnx_[0]
        print(row)###输出下第一个特征

        ###获取多小行特征
        rows_=output_onnx_.shape[0]

        ###获取boxs
        boxs=[]
        for i in range(rows_):
            ###获取最大概率 对应的index
            prob_ = output_onnx_[i][4:].max()

            if prob_>self.ConfidenceThres:
                class_id_ = output_onnx_[i][4:].argmax()
                ###前是个特征代表 x中心 y中心 w宽 h高
                xc_,yc_,w_,h_ = output_onnx_[i][:4]
                ###转换成x1 y1 x2 y2
                x1_=(xc_-w_/2)/target_image_width_*img_width_
                y1_=(yc_-h_/2)/target_image_height_*img_height_
                x2_=(xc_+w_/2)/target_image_width_*img_width_
                y2_=(yc_ + h_ / 2) / target_image_height_ * img_height_

                boxs.append([x1_,y1_,x2_,y2_,class_id_,prob_])

        ###去掉重叠的box
        boxs.sort(key=lambda x:[5],reverse=True)
        result_box_=[]

        lenght_box_=len(boxs)

        while lenght_box_>0:

            box_temp_=boxs[0].copy()

            boxs_temp_ = []

            ##不是重叠的添加进去boxs_temp_
            for box_ in boxs:
                ###计算intersection
                box1_x1_,box1_y1_,box1_x2_,box1_y2_=box_temp_[:4]
                box2_x1_, box2_y1_, box2_x2_, box2_y2_ = box_[:4]

                distance1_=math.sqrt((box1_x1_-box2_x1_)**2+(box1_y1_-box2_y1_)**2)
                distance2_=math.sqrt((box1_x2_-box2_x2_)**2+(box1_y2_-box2_y2_)**2)

                if (distance1_<self.Iou)&(distance2_<self.Iou):
                    pass
                else:
                    boxs_temp_.append(box_)
                    pass

            boxs.clear()###清空原来的

            for box_ in boxs_temp_:
                boxs.append(box_)

            lenght_box_ = len(boxs)

            result_box_.append(box_temp_)

        print(len(result_box_))

        for box_ in result_box_:
            box1_x1_, box1_y1_, box1_x2_, box1_y2_ = box_[:4]

            class_id_,prob_=box_[4:]

            width = box1_x2_-box1_x1_
            height = box1_y2_-box1_y1_

            center_x_= (box1_x2_+box1_x1_)/2
            center_y_ = (box1_y2_+box1_y1_)/2

            self.BoxX.append(float(center_x_))
            self.BoxY.append(float(center_y_))
            self.BoxWidth.append(float(width))
            self.BoxHeight.append(float(height))

            if class_id_==0:
                self.BoxClass.append('head')

            if class_id_==1:
                self.BoxClass.append('helmet')

            if class_id_==2:
                self.BoxClass.append('person')

4.4这里是一个使用onnx检测安全帽子的demo
https://gitee.com/wenyuanmo/py-qt-load-yolo-or-onnx-check-hat/tree/master

视频讲解:
https://www.bilibili.com/video/BV1XK421k7HJ/?spm_id_from=333.999.0.0&vd_source=a858ab6f3e2b18f287232b03ba9022e2

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_46648511/article/details/136032406

智能推荐

使用nginx解决浏览器跨域问题_nginx不停的xhr-程序员宅基地

文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr

在 Oracle 中配置 extproc 以访问 ST_Geometry-程序员宅基地

文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc

Linux C++ gbk转为utf-8_linux c++ gbk->utf8-程序员宅基地

文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8

IMP-00009: 导出文件异常结束-程序员宅基地

文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束

python程序员需要深入掌握的技能_Python用数据说明程序员需要掌握的技能-程序员宅基地

文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求

Spring @Service生成bean名称的规则(当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致)_@service beanname-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname

随便推点

二叉树的各种创建方法_二叉树的建立-程序员宅基地

文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include&lt;stdio.h&gt;#include&lt;string.h&gt;#include&lt;stdlib.h&gt;#include&lt;malloc.h&gt;#include&lt;iostream&gt;#include&lt;stack&gt;#include&lt;queue&gt;using namespace std;typed_二叉树的建立

解决asp.net导出excel时中文文件名乱码_asp.net utf8 导出中文字符乱码-程序员宅基地

文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码

笔记-编译原理-实验一-词法分析器设计_对pl/0作以下修改扩充。增加单词-程序员宅基地

文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词

android adb shell 权限,android adb shell权限被拒绝-程序员宅基地

文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限

投影仪-相机标定_相机-投影仪标定-程序员宅基地

文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定

Wayland架构、渲染、硬件支持-程序员宅基地

文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland

推荐文章

热门文章

相关标签