什么是网站接入商,江门网站建设企业,武进网站建设效果,项目网络图关键路径计算1.上几篇文件写了#xff0c;怎么自定义自己的yolo数据#xff0c;怎么训练自己自定义的数据#xff0c;怎么用onnxruntime调用yolo导出的onnx模型#xff0c;这文章进一步写用onnxruntime调用yolo导出的onnx模型进行图片分割。
视频讲解地址:https://www.bilibili.com/vi…1.上几篇文件写了怎么自定义自己的yolo数据怎么训练自己自定义的数据怎么用onnxruntime调用yolo导出的onnx模型这文章进一步写用onnxruntime调用yolo导出的onnx模型进行图片分割。
视频讲解地址:https://www.bilibili.com/video/BV1Y1421Z7LS/?spm_id_from333.999.0.0vd_sourcea858ab6f3e2b18f287232b03ba9022e2
公众号地址: https://mp.weixin.qq.com/s?__bizMzkzNzYyNTE0Ngmid2247483776idx1snad1b4a1e7715257acd347965dc76ee09chksmc28dd2d5f5fa5bc39749fb8770ee9480dcdc18313df3516f640770fcf58493cead77d8998dc6token909058031langzh_CN#rd
2.这里直接上核心代码 类名:ImageDealWith
说明:图片处理类
功能:1.加载图片
注意:文件中已经建立_image_deal_withImageDealWith() 可以直接调用模块使用
著作权信息:作者:照彩云归联系方式:
版本信息:日期: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):图片CurrentImageNone模板ModelNoneonnx模板OnnxModelNone###识别框的坐标BoxX NoneBoxY None###识别框的长宽BoxWidth NoneBoxHeight None###识别框的类别BoxClass None###onnx的阈值ConfidenceThresNone###onnx的iouIouNone###多边形x yPolygonsXYNone###yolo识别类Yolo_classesNone###当前图片的大小Img_width0Img_height0#初始化def __init__(self,parentNone):super(ImageDealWith,self).__init__(parent)self.CurrentImageQImage()self.ModelYOLO(yolov8m-seg.pt)self.OnnxModel ort.InferenceSession(yolov8m-seg.onnx)###这里初始化列表才有用self.BoxY []self.BoxX []self.BoxWidth []self.BoxHeight []self.BoxClass []self.ConfidenceThres0.5self.Iou20self.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_width0self.Img_height0pass读取图片def LoadImage(self,image_path_):read_dir_QImageReader(image_path_)self.CurrentImageread_dir_.read()self.Img_heightself.CurrentImage.height()self.Img_widthself.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]cbox_.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(formatonnx)# device torch.device(cpu)# nettorch.load(best.pt,map_locationcpu)# dummpy_input_torch.randn(1,3,640,640)# torch.onnx.export(net,# dummpy_input_,# best.onnx,# export_paramsTrue,# input_names[input],# output_names[output],# opset_version11)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,fxscale_precentage_x_,fyscale_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])###获取输出点outputsself.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)###运行推理outputsself.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 output1masksnp.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)# polygonpolygonobjects_.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, fxscale_precentage_x_, fyscale_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_withImageDealWith()这里建一个图片处理类: onnx推理的主要核心函数UseOnnxInference() onnx推理分割图片跟onnx推理识别图片基本相同唯一的不同在于最后推理输出的output数据不同。onnx推理分割图片和onnx推理识别图片输入节点input格式一样不同的是最后推理输出节点outputs推理输出的outputs包含两个矩阵分别是output0output1。 output0里面的信息是关于图片分割出来对象的boxes信息x1y1x2y2跟识别这个对象是哪一类的概率信息class output1里面的信息是关于图片分割出来对象的掩码信息但是里面的内容我们一般看不懂需要用激活函数sigmoid转成概率值然后进行概率值二值化想这里我们概率二值化就是大于0.5认为图片灰度为255小于0.5图片灰度为0。 这里的UseOnnxInference()函数对outputs处理还把output0output1整合到一个矩阵boxes列表然后在同一做对象概率筛选对象重叠帅选。 output0output1怎么整合一起的呢我们可以知道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