yolo导出的onnx怎么使用onnxruntime进行图片分割

1.上几篇文件写了,怎么自定义自己的yolo数据,怎么训练自己自定义的数据,怎么用onnxruntime调用yolo导出的onnx模型,这文章进一步写用onnxruntime调用yolo导出的onnx模型进行图片分割。

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

公众号地址:
https://mp.weixin.qq.com/s?__biz=MzkzNzYyNTE0Ng==&mid=2247483776&idx=1&sn=ad1b4a1e7715257acd347965dc76ee09&chksm=c28dd2d5f5fa5bc39749fb8770ee9480dcdc18313df3516f640770fcf58493cead77d8998dc6&token=909058031&lang=zh_CN#rd

2.这里直接上核心代码

'''
类名:ImageDealWith
说明:图片处理类
功能:1.加载图片
注意:文件中已经建立_image_deal_with=ImageDealWith() 可以直接调用模块使用
著作权信息:作者:照彩云归联系方式:
版本信息:日期:2023-12-25版本:v1.0.0描述:基本类
'''
import mathimport cv2
from PySide6.QtCore import QObject
from PySide6.QtGui import QImage,QPixmap,QPainter,QImageReader
from ultralytics import YOLO
import cv2 as cv
import numpy as np
import torch
import onnxruntime as ort
import onnx
import torchclass ImageDealWith(QObject):'''图片'''CurrentImage=None'''模板'''Model=None'''onnx模板'''OnnxModel=None###识别框的坐标BoxX = NoneBoxY = None###识别框的长宽BoxWidth = NoneBoxHeight = None###识别框的类别BoxClass = None###onnx的阈值ConfidenceThres=None###onnx的iouIou=None###多边形x yPolygonsXY=None###yolo识别类Yolo_classes=None###当前图片的大小Img_width=0Img_height=0#初始化def __init__(self,parent=None):super(ImageDealWith,self).__init__(parent)self.CurrentImage=QImage()self.Model=YOLO('yolov8m-seg.pt')self.OnnxModel = ort.InferenceSession('yolov8m-seg.onnx')###这里初始化列表才有用self.BoxY = []self.BoxX = []self.BoxWidth = []self.BoxHeight = []self.BoxClass = []self.ConfidenceThres=0.5self.Iou=20self.PolygonsXY=[]self.Yolo_classes = ["person", "bicycle", "car", "motorcycle", "airplane", "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", "couch", "potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse","remote", "keyboard", "cell phone", "microwave", "oven", "toaster", "sink", "refrigerator", "book","clock", "vase", "scissors", "teddy bear", "hair drier", "toothbrush"]###图片大小self.Img_width=0self.Img_height=0pass'''读取图片'''def LoadImage(self,image_path_):read_dir_=QImageReader(image_path_)self.CurrentImage=read_dir_.read()self.Img_height=self.CurrentImage.height()self.Img_width=self.CurrentImage.width()pass'''图片分析'''def ImageAnalyze(self):self.BoxY.clear()self.BoxX.clear()self.BoxWidth.clear()self.BoxHeight.clear()self.BoxClass.clear()self.PolygonsXY.clear()if (self.CurrentImage.width() > 0) & (self.CurrentImage.height() > 0):image_mat_ = self.CoverQImageToMat()results_=self.Model(image_mat_)len(results_)for result_ in  results_:boxes_ = result_.boxesmasks = result_.masks#names_=results_.names#获取对象边界for box_ in boxes_:x_,y_,w_,h_=box_.xywh[0]c=box_.clscls_=self.Model.names[int(c)]self.BoxX.append(float(x_))self.BoxY.append(float(y_))self.BoxWidth.append(float(w_))self.BoxHeight.append(float(h_))self.BoxClass.append(cls_)###获取对象掩码for mask in masks:xys_=mask.xy[0]self.PolygonsXY.append(xys_)passpass###Qimage转Matdef CoverQImageToMat(self):ptr_=self.CurrentImage.constBits()# ptr_.setsize(self.CurrentImage.byteCount())###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_###Mat转成QImagedef CoverMatToQImage(self,image_mat:cv.Mat):qimage_=QImage(image_mat.data,image_mat.shape[1],image_mat.shape[0],image_mat.shape[1]*3,QImage.Format.Format_RGB888)return qimage_###清空结果def ClearResult(self):self.PolygonsXY.clear()self.BoxY.clear()self.BoxX.clear()self.BoxWidth.clear()self.BoxHeight.clear()self.BoxClass.clear()###导出onnxdef ExportOnnx(self):self.Model.export(format='onnx')# device = torch.device('cpu')# net=torch.load('best.pt',map_location='cpu')# dummpy_input_=torch.randn(1,3,640,640)# torch.onnx.export(net,#                   dummpy_input_,#                   'best.onnx',#                   export_params=True,#                   input_names=['input'],#                   output_names=['output'],#                   opset_version=11)pass###使用onnx推理def UseOnnxInference(self):if (self.CurrentImage.width() > 0) & (self.CurrentImage.height() > 0):self.PolygonsXY.clear()self.BoxY.clear()self.BoxX.clear()self.BoxWidth.clear()self.BoxHeight.clear()self.BoxClass.clear()#获取输入点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)##获取图片输入输出self.Img_width = image_mat_.shape[1]self.Img_height = image_mat_.shape[0]target_image_height_ = 640target_image_width_ = 640# scale_precentage_=min(target_image_height_/image_mat_.shape[0],target_image_width_/image_mat_.shape[1])scale_precentage_x_=target_image_width_/image_mat_.shape[1]scale_precentage_y_ = target_image_height_ / image_mat_.shape[0]image_mat_=cv2.resize(image_mat_,None,fx=scale_precentage_x_,fy=scale_precentage_y_)#缩放成固定大小# image_mat_=image_mat_.resize(target_image_width_,target_image_height_)# print("ImageMatShape:", image_mat_.shape)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)##添加一个新维度image_np_[0, 0, 0, 0]print(image_np_[0, 0, 0, 0])print("ImageNpShape:", image_np_.shape)image_np_ = image_np_.astype(np.float32)image_np_=image_np_/255.0##数据归一化print(image_np_[0, 0, 0, 0])###获取输出点outputs=self.OnnxModel.get_outputs()print(len(outputs))###获取第一个矩阵输出 检测到的特征output_onnx1_=outputs[0]print("Name:",output_onnx1_.name)print("Type:",output_onnx1_.type)print("Shape:",output_onnx1_.shape)###获取第二个矩阵输出  掩码output_onnx2_ = outputs[1]print("Name:", output_onnx2_.name)print("Type:", output_onnx2_.type)print("Shape:", output_onnx2_.shape)###运行推理outputs=self.OnnxModel.run(None,{"images":image_np_})len(outputs)###获取第一个输出output0 = outputs[0]
###获取第二个输出output1 = outputs[1]print("Output0:", output0.shape, "Output1:", output1.shape)###第一个输出转置output0 = output0[0].transpose()output1 = output1[0]print("Output0:", output0.shape, "Output1:", output1.shape)
###获取边界跟掩码boxes = output0[:, 0:84]masks = output0[:, 84:]print("Boxes:", boxes.shape, "Masks:", masks.shape)print("Masks:",masks.shape,"Output1:", output1.shape)
###转置下输出output1 = output1.reshape(32, 160 * 160)print("Masks:",masks.shape, "Output1:",output1.shape)###两个数组链接# masks = masks @ output1masks=np.dot(masks,output1)print("Masks:",masks.shape)"""把boxes跟mask链接在一起0-4 - x_center, y_center, width and height of bounding box4-84 - Object class probabilities for all 80 classes, that this YOLOv8 model can detect84-25684 - Pixels of segmentation mask as a single row. Actually, the segmentation mask is a 160x160 matrix, but we just flattened it            """boxes = np.hstack((boxes, masks))print("Boxes:",boxes.shape)objects_ = []
###先判断是否满足for boxe in boxes:prob_ = boxe[4:84].max()if prob_ > self.ConfidenceThres:xc, yc, w, h = boxe[:4]class_id = boxe[4:84].argmax()###转成图片大小x1 = (xc - w / 2) / target_image_width_ * self.Img_widthy1 = (yc - h / 2) / target_image_height_ * self.Img_heightx2 = (xc + w / 2) / target_image_width_ * self.Img_widthy2 = (yc + h / 2) / target_image_height_ * self.Img_heightlabel = self.Yolo_classes[class_id]###获取掩码mask =self.get_mask(boxe[84:25684], (x1, y1, x2, y2))polygons =self.get_polygon(mask,x1,y1)# polygon=polygonobjects_.append([x1, y1, x2, y2, label, prob_, mask, polygons])# self.BoxX.append(float(x1))# self.BoxY.append(float(y1))# self.BoxWidth.append(float(x2-x1))# self.BoxHeight.append(float(y2-y1))# self.BoxClass.append(label)# self.PolygonsXY.append(polygon)pass###判断是否重叠lenght_box_ = len(objects_)resulets_object_=[]while lenght_box_ > 0:object_temp_ = objects_[0].copy()objects_temp_ = []##不是重叠的添加进去boxs_temp_for object_ in objects_:###计算intersectionbox1_x1_, box1_y1_, box1_x2_, box1_y2_ = object_temp_[:4]box2_x1_, box2_y1_, box2_x2_, box2_y2_ = object_[: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):passelse:objects_temp_.append(object_)passpassobjects_.clear()  ###清空原来的for object_ in objects_temp_:objects_.append(object_)lenght_box_ = len(objects_)resulets_object_.append(object_temp_)for object_ in resulets_object_:box1_x1_, box1_y1_, box1_x2_, box1_y2_,class_id_, prob_,mask_,polygons_ = object_label = self.Yolo_classes[class_id]# class_id_, prob_ = object_[3:5]# polygon_=object_[7]width = box1_x2_ - box1_x1_height = box1_y2_ - box1_y1_center_x_ = (box1_x2_ + box1_x1_) / 2center_y_ = (box1_y2_ + box1_y1_) / 2self.BoxX.append(float(center_x_))self.BoxY.append(float(center_y_))self.BoxWidth.append(float(width))self.BoxHeight.append(float(height))self.BoxClass.append(label)for polygon_ in polygons_:self.PolygonsXY.append(polygon_)pass###获取掩码def get_mask(self,row, box):mask = row.reshape(160, 160)###打印mask数据print("mask data:",mask)###把mask转换成概率mask = self.sigmoid(mask)###打印mask数据print("mask probably:",mask)###概率大于0.5的认为是前景物体  小于0.5的认为是背景mask = (mask > 0.5).astype('uint8') * 255###取出box边界x1, y1, x2, y2 = box###转换成mask的box点mask_x1 = round(x1 / self.Img_width * 160)mask_y1 = round(y1 / self.Img_height * 160)mask_x2 = round(x2 / self.Img_width * 160)mask_y2 = round(y2 / self.Img_height * 160)###裁剪对象mask = mask[mask_y1:mask_y2, mask_x1:mask_x2]###转换成图片大小mask = np.array(mask)###转成图片img_=cv2.Mat(mask)###换成对应大小scale_precentage_x_ = round(x2 - x1) / img_.shape[1]scale_precentage_y_ =  round(y2 - y1)/ img_.shape[0]img_ = cv2.resize(img_, None, fx=scale_precentage_x_, fy=scale_precentage_y_)  # 缩放成固定大小# mask = mask.resize((round(x2 - x1), round(y2 - y1)))mask = np.array(img_)return mask###获取mask的多边形def get_polygon(self,mask,x1_,y1_):contours = cv2.findContours(mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)# print(len(contours))polygons_ = []# lenght_ = len(contours)for contour1_ in contours[0]:polygon_ = []for contour2_ in contour1_:polygon_.append([contour2_[0][0]+x1_,contour2_[0][1]+y1_])polygons_.append(polygon_)###polygons_ = [[contour[0][0]+x1_, contour[0][1]+y1_] for contour in contours[0][0]]return polygons_###激活函数def sigmoid(self,z):return 1 / (1 + np.exp(-z))###是否资源def ReleaseSource(self):self.ClearResult()pass_image_deal_with=ImageDealWith()

这里建一个图片处理类:
onnx推理的主要核心函数UseOnnxInference()
onnx推理分割图片跟onnx推理识别图片基本相同,唯一的不同在于最后推理输出的output数据不同。onnx推理分割图片和onnx推理识别图片,输入节点input格式一样,不同的是最后推理输出节点outputs,推理输出的outputs包含两个矩阵分别是output0,output1。
output0里面的信息是关于图片分割出来对象的boxes信息(x1,y1,x2,y2)跟识别这个对象是哪一类的概率信息(class)
output1里面的信息是关于图片分割出来对象的掩码信息,但是里面的内容我们一般看不懂,需要用激活函数sigmoid,转成概率值,然后进行概率值二值化,想这里我们概率二值化就是大于0.5认为图片灰度为255,小于0.5图片灰度为0。
这里的UseOnnxInference()函数对outputs处理,还把output0,output1,整合到一个矩阵boxes列表,然后在同一做对象概率筛选,对象重叠帅选。
output0,output1怎么整合一起的呢?我们可以知道output0固定8400行,也就是yolo最多识别到的物体是8400个,每一行前4个元素是boxex信息(x1,y1,x2,y2),着就是识别物体的对象概率,这里识别对象的种类80种,也就是每一行4到84元素是识别物体对象概率的信息,然后剩下的就是识别物体掩码的信息,会发现剩下的元素个数跟output1维度能对上,通过这个维度,可以把两个output整合成一个boxes。
后面对boxes数据进行处理就容易了。
def get_mask(self,row, box)这个函数是把掩码数据转成黑白图片mask。
def get_polygon(self,mask,x1_,y1_)这个函数是提取mask中对象的边缘。

3.代码地址
https://gitee.com/wenyuanmo/py-qt-load-yolo-model-onnx-segment-thing/tree/master

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

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

相关文章

Java学习——常用API Runtime

Java的Runtime类是用来与Java运行时环境进行交互的。它提供了执行系统命令、获取内存信息等功能。Runtime类是一个单例类&#xff0c;即在Java应用程序中只能获得一个Runtime实例&#xff0c;用于代表Java应用程序的运行时环境。 获取Runtime实例 由于Runtime类的构造函数是私…

【GTK+-编程指南*】

GTK-编程指南 ■ GTK 简介 (GIMP Toolkit)■ GTK和GTK■ GTK 常用的库■ GTK 环境搭建■ GTK 语法■ GTK ■ GTK 简介 (GIMP Toolkit) GIMP全称&#xff1a;GNU 图像处理程序(Gnu Image Manipulation Program) GTK 是一套源码以LGPL许可协议分发、跨平台的图形工具包。 GTK也是…

基础光学系列:(一)光学在机器视觉中的角色:原理、应用与学习途径

光学是一门研究光的产生、传播以及与物质相互作用的科学&#xff0c;对于机器视觉技术的发展至关重要。机器视觉利用计算机和相机系统模拟人类视觉&#xff0c;解释和理解图像&#xff0c;广泛应用于制造业、医疗、安全监控等领域。本文旨在探讨光的传播原理及其在机器视觉中的…

处理器后面的字母什么意思?

我们在挑选电脑时&#xff0c;会见到各种各样的CPU型号&#xff0c;很多人可能不太了解处理器后面的各字母究竟代表着什么&#xff0c;今天我和大家分享一下常见的几种处理器后缀。 一&#xff0c;U 处理器后面跟字母U代表着移动平台低电压处理器&#xff0c;移动平台也就是笔…

低于API等级30的应用将无法在上述应用商店

minSdkVersion minSdkVersion用于指定应用兼容的最低Android版本&#xff08;API等级&#xff09;。 如果APP某些功能无法支持低版本Android系统的设备&#xff0c;可以配置minSdkVersion确保APP只能安装到指定Android版本以上的设备。HBuilder|HBuilderX中可在manifest.json中…

Essential C++ 基于对象的编程风格

Essential C 前言 前言 通过Essential C笔记的形式对C相关重点知识进行汇总&#xff0c;读者通读此系列文章就可以轻松的把该语言基础捡起来。

Linux的目录操作

Linux目录操作 获取当前工作目录 getcwd() 声明&#xff1a;char *getcwd(char *buf, size_t size);使用方法&#xff1a; getcwd用于获取当前工作目录&#xff0c;并将其保存在buf指向的缓冲区中。返回值&#xff1a; 返回一个指向buf的指针&#xff0c;若失败则返回NULL。注…

Linux快速修改ip地址

Linux修改IP配置 一 、查找ip配置文件 ifcfg-ens33二、编辑 vi ifcfg-ens33文件三、重启网络或者重启系统 一 、查找ip配置文件 ifcfg-ens33 cd /etc/sysconfig/network-scripts/ls //查看network-scripts文件夹下面的文件二、编辑 vi ifcfg-ens33文件 vi ifcfg-ens33注意&…

机器学习 深度学习资料 资源machine learning

Kaggle入门&#xff0c;看这一篇就够了 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/25686876 day1-1.什么是机器学习_哔哩哔哩_bilibiliday1-1.什么是机器学习是10天学会机器学习从入门到深度学习的第1集视频&#xff0c;该合集共计62集&#xff0c;视频收藏或关注UP主&a…

【MySQL】如何理解MySQL的存储引擎

一、常见存储引擎 我们可以知道表的类型是由存储引擎决定的&#xff0c;如图所示&#xff0c;我们可以看到MySQL中支持八种储存引擎&#xff0c;那么我们这里就介绍常用的三种存储引擎&#xff0c;分别是Innodb、MyISAM、Memory。 二、Innodb、MyISAM、Memory的特点 1、Inno…

day10-项目集成sharding-jdbc-今日指数

项目集成sharding-jdbc 目标 1.掌握shardingjdbc标准分片模式&#xff1b; 2.理解项目分库分表的设计思路&#xff1b; 3.理解分库分表代码实现流程&#xff1b; 第一章 项目分库分表实现 1、股票数据预期增长分析 ​ 由于今日指数是偏向海量数据分析的产品&#xff0c;而…

Go语言基础总结

一、Go语言结构 包声明 引入包 函数 变量 语句&表达式 注释 下面简单给出hello.go文件。 package src /*定义包名*/import "fmt" /*引入包*/func hello() { /*函数*/fmt.Println("Hello,World!") /*语句&表达式*/fmt.Println("菜鸟教…

2024年华为OD机试真题-抢7游戏-Python-OD统一考试(C卷)

题目描述: A、B两个人玩抢7游戏,游戏规则为A先报一个起始数字X(10<起始数字<10000),B报下一个数字Y(X-Y<3),A再报一个数字Z(Y-Z<3),以此类推,直到其中一个抢到7,抢到7即为胜者;在B赢得比赛的情况下,一共有多少种组合? 输入描述: 起始数字M,如100;10<…

Linux系统下防火墙端口操作

防火墙端口的认识 防火墙是一种网络安全设备&#xff0c;用于监控和控制网络进出流量&#xff0c;其中开放端口是防火墙功能中的一个重要部分&#xff0c;可以确保应用程序和服务正常通信。端口是不同应用程序或服务之间通信的入口或出口&#xff0c;每个端口都有一个数字标识…

go - 学习笔记 - 1

go - 学习笔记 -1 hello world变量值拷贝匿名变量语句分隔符整型&浮点型&布尔型字符串类型strings包的字符串函数 hello world package mainimport "fmt"func main() {fmt.Println("hello world") }变量 package mainimport "fmt"func…

深度学习环境配置常见指令

首先打开anaconda prompt&#xff0c;激活对应虚拟环境。 导入torch并获取对应版本 import torch torch.__version__导入torchvision并获取对应版本 import torchvision torchvision.__version__ 检查cuda是否可用 torch.cuda.is_available() 获取CUDA设备数 torch.cuda.…

OpenBMC的c++代码中的变量初始化问题(一)

1 开发平台 Win11、VS2022、Fedora39。 2 作业目的 通过VS2022跨平台Linux构建openbmc/intel-ipmi-oem的x64可执行模块。 3 问题描述 该模块启动后&#xff0c;在执行subprojects\phosphor-host-ipmid\user_channel\channel_mgmt.cpp 中的函数convertToMediumTypeIndex出现…

leetcode-回溯法-矩阵中的路径

https://www.nowcoder.com/practice/c61c6999eecb4b8f88a98f66b273a3cc?tpId13&tqId11218&tPage4&rp4&ru/ta/coding-interviews&qru/ta/coding-interviews/question-ranking 请设计一个函数&#xff0c;用来判断在一个矩阵中是否存在一条包含某字符串所有…

基于SpringBoot的气象数据监测分析大屏

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

数据仓库选型建议

1 数仓分层 1.1 数仓分层的意义 **数据复用&#xff0c;减少重复开发&#xff1a;**规范数据分层&#xff0c;开发一些通用的中间层数据&#xff0c;能够减少极大的重复计算。数据的逐层加工原则&#xff0c;下层包含了上层数据加工所需要的全量数据&#xff0c;这样的加工方…