【ORT部署】对bubbliiiing的yolo系列进行进行onnxruntime推理部署

简介: 【ORT部署】对bubbliiiing的yolo系列进行进行onnxruntime推理部署

前言

  当今深度学习技术已经成为人工智能领域的核心技术之一,越来越多的企业和研究机构开始将其应用到实际业务中。但是,要将深度学习模型应用到实际业务中,需要先将其转换为可部署的模型并进行推理部署。这个过程需要考虑到多个方面,例如模型的性能、效率、精度等。ONNX Runtime是一种跨平台的深度学习推理引擎,可以帮助用户快速地将深度学习模型部署到各种不同的硬件设备上,并实现高效、高性能的推理。

  在本文中我将为大家介绍如何使用onnxruntime替代opencv.dnn模块中的net.forward,并综合比对二者推理的差异。

注: 本实验代码以及源码是从使用python&C++对bubbliiiing的yolo系列进行opencv.dnn进行推理部署中变换而来,如大家需要更加详细的代码的话,可以点击连接或者在文末进行评论告知。

ORT推理

  在使用onnxruntime推理部署(后续简称ORT推理部署)之前,应当了解其大体流程:

  1. 准备模型:使用支持ONNX格式的机器学习框架(如PyTorch、TensorFlow等)训练或导出一个ONNX格式的模型。
  2. 加载模型:使用ONNX Runtime提供的API将ONNX格式的模型加载到内存中。
  3. 创建会话:使用ONNX Runtime提供的API创建一个会话对象,用于执行推理任务。
  4. 配置会话:根据需要配置会话,包括硬件加速、运行优化等。
  5. 输入数据:将输入数据传递给会话。
  6. 执行推理:使用会话对象的API执行推理任务。
  7. 输出结果:从会话对象中获取推理结果。

  我们通过上篇文章我们已经知道了第一步准备模型阶段以及根据网络的输出进行解码的部分,因此在本文中我们将重点放在加载模型、创建会话、配置会话、输出数据和执行推理。

读取网络

  查看官网例子,我们容易得到,使用ort读取onnx的方式如下:

scss

复制代码

def readModel(netPath):
    net = ort.InferenceSession(netPath, providers=ort.get_available_providers())
    return net

数据预处理阶段

  在输入数据方面我们仍然是沿用了opencv.dnn模块的blobFromImage函数进行输入图像的处理,这样保证了可以在让网络正常输出图像数据。

ini

复制代码

blob = cv2.dnn.blobFromImage(netInputImg, scalefactor=1 / 255.0, size=(netWidth, netHeight), mean=[104, 117, 123], swapRB=True, crop=False)

网络推理阶段

  在读取了onnx权重文件后我们需要进行ort推理了,我们需要知道在转onnx权重文件时的输入和输出名字(这两个可以通过代码获取,在这里我省去便于快速执行),将数据转为float32的格式

ini

复制代码

input_name = "images"
output_name = "output"
netOutputImg = net.run([output_name], {input_name: blob.astype(np.float32)})

  在后续的解码部分和上篇文章中保持一致。这里就不过多的介绍了。

ORT推理输出结果&DNN推理输出结果

ORT

image.png

DNN

image.png

综合比对DNN与ORT推理

  OpenCV和ONNX Runtime都是流行的深度学习推理框架,它们都支持跨平台的模型部署。下面是它们之间的一些比较:

模型支持:

  OpenCV DNN支持许多深度学习框架的模型,例如Caffe、TensorFlow、Darknet、PyTorch等。但是,它不支持ONNX格式的模型。ONNX Runtime是专门为ONNX模型设计的,因此它支持ONNX格式的模型,但是它也可以加载和运行其他框架的模型。不过需要将其他框架的模型转换为ONNX格式。

模型转换

  OpenCV DNN提供了一些工具和API,可以将各种深度学习框架的模型转换为OpenCV可用的格式,以便在OpenCV中进行推理。ONNX Runtime本身不提供模型转换的功能,但是有许多第三方工具可以将其他框架的模型转换为ONNX格式,例如ONNX官方提供的ONNX Converter。

性能

  在相同硬件和模型条件下,ONNX Runtime通常比OpenCV DNN更快。这是因为ONNX Runtime使用了更先进的推理优化技术,例如TensorRT、OpenVINO等,可以在各种硬件平台上获得更好的性能。

API和易用性

  OpenCV DNN的API相对简单,易于学习和使用。而ONNX Runtime的API更为复杂,需要一些深度学习和编程知识才能使用。

  总体来说,OpenCV DNN和ONNX Runtime都是优秀的深度学习推理框架,可以满足不同的部署需求。如果您的模型已经是ONNX格式的,推荐使用ONNX Runtime进行部署。

结论与吐槽:

  不管是在CPU端或是在GPU端,对于在深度学习有一定基础的同学们来说,在选择推理部署框架的时候,一律选择ORT推理部署框架作为首选!

代码:

ini

复制代码

import random
import time
from math import exp, pow
import cv2
import numpy as np
import onnxruntime as ort
className = ["1", "2", "3", "4"]
# 替换对应yolo的Anchors值
netAnchors = np.asarray([[10.0, 13.0, 16.0, 30.0, 33.0, 23.0],
                         [30.0, 61.0, 62.0, 45.0, 59.0, 119.0],
                         [116.0, 90.0, 156.0, 198.0, 373.0, 326.0]], dtype=np.float32)
netStride = np.asarray([8.0, 16.0, 32.0], dtype=np.float32)
netWidth = 512
netHeight = 512
nmsThreshold = 0.80
boxThreshold = 0.80
classThreshold = 0.80
def GetColors(color_num):
    ColorList = []
    for num in range(color_num):
        R = random.randint(0, 255)
        G = random.randint(0, 255)
        B = random.randint(0, 255)
        BGR = (B, G, R)
        ColorList.append(BGR)
    return ColorList
def Sigmoid(x):
    # x = float(x)
    # out = max(x, 0)
    out = (float(1.) / (float(1.) + exp(-x)))
    return out
def readModel(netPath):
    net = ort.InferenceSession(netPath, providers=ort.get_available_providers())
    return net
def Detect(SrcImg, net, netWidth, netHeight):
    netInputImg = SrcImg
    blob = cv2.dnn.blobFromImage(netInputImg, scalefactor=1 / 255.0, size=(netWidth, netHeight), mean=[104, 117, 123],
                                 swapRB=True, crop=False)
    input_name = "images"
    output_name = "output"
    netOutputImg = net.run([output_name], {input_name: blob.astype(np.float32)})
    ratio_h = float(netInputImg.shape[1] / netHeight)
    ratio_w = float(netInputImg.shape[0] / netWidth)
    pdata = netOutputImg[0]
    classIds = []  # 定义结果线性表
    confidences = []  # 定义置信度线性表
    boxes = []  # 定义坐标线性表
    count = 0
    for stride in range(3):  # netStride = {8.0, 16.0, 32.0} = 3
        grid_x = netWidth / netStride[stride]
        grid_y = netHeight / netStride[stride]
        grid_x, grid_y = int(grid_x), int(grid_y)  # 系统默认是float32,这里是为了下面的循环转为int
        for anchor in range(3):  # netAnchors 的层数 = 3
            anchor_w = netAnchors[stride][anchor * 2]
            anchor_h = netAnchors[stride][anchor * 2 + 1]
            anchor_w, anchor_h = float(anchor_w), float(anchor_h)
            for i in range(grid_x):
                for j in range(grid_y):  
                    pdatabox = pdata[0][count][4]
                    box_score = Sigmoid(pdatabox)  # 获取每一行的box框中含有某个物体的概率
                    if box_score > boxThreshold:  # box的阈值起作用了
                        scores = pdata[0][count][5:]  # 这里的scores理应是一个多维矩阵
                        _, max_class_socre, _, classIdPoint = cv2.minMaxLoc(scores)  # 求最大值以及最大值的位置&位置是元组
                        max_class_socre = np.asarray(max_class_socre, dtype=np.float64)
                        max_class_socre = Sigmoid(max_class_socre)
                        if max_class_socre > classThreshold:  # 类别的置信度起作用
                            # rect[x,y,w,h]
                            pdatax = pdata[0][count][0]
                            x = (Sigmoid(pdatax) * float(2.) - float(0.5) + j) * netStride[stride]  # x
                            pdatay = np.asarray(pdata[0][count][1], dtype=np.float64)
                            y = (Sigmoid(pdatay) * float(2.) - float(0.5) + i) * netStride[stride]  # y
                            pdataw = pdata[0][count][2]
                            w = pow(Sigmoid(pdataw) * float(2.), float(2.0)) * anchor_w  # w
                            pdatah = pdata[0][count][3]
                            h = pow(Sigmoid(pdatah) * float(2.), float(2.0)) * anchor_h  # h
                            left = (x - 0.5 * w) * ratio_w
                            top = (y - 0.5 * h) * ratio_h
                            left, top, W, H = int(left), int(top), int(w * ratio_w), int(h * ratio_h)
                            # 对classIds & confidences & boxes
                            classIds.append(classIdPoint[1])  # 获取最大值的位置
                            confidences.append(max_class_socre * box_score)
                            boxes.append((left, top, W, H))
                    count += 1
    # cv2.dnn.NMSBoxes的bboxes框应该是左上角坐标(x,y)和 w,h, 那么针对不同模型的,要具体情况转化一下,才能应用该函数。
    nms_result = cv2.dnn.NMSBoxes(boxes, confidences, classThreshold, nmsThreshold)  # 抑制处理 返回的是一个数组
    if len(nms_result) == 0:
        return
    else:
        for idx in nms_result:
            classIdx = classIds[idx]
            confidenceIdx = confidences[idx]
            boxsIdx = boxes[idx]
            pt1 = (boxsIdx[0], boxsIdx[1])
            pt2 = (boxsIdx[0] + boxsIdx[2], boxsIdx[1] + boxsIdx[3])
            # 绘制图像目标位置
            # x1, y1, x2, y2 = box[0], box[1], box[0] + box[2], box[1] + box[3]
            cv2.rectangle(SrcImg, pt1, pt2, classIdx, 2, 2)
            cv2.rectangle(SrcImg, (boxsIdx[0], boxsIdx[1] - 18), (boxsIdx[0] + boxsIdx[2], boxsIdx[1]), (255, 0, 255),
                          -1)
            label = "%s:%s" % (className[classIdx], confidenceIdx)  # 给目标进行添加类别名称以及置信度
            FONT_FACE = cv2.FONT_HERSHEY_SIMPLEX
            cv2.putText(SrcImg, label, (boxsIdx[0] - 2, boxsIdx[1] - 5), FONT_FACE, 0.5, (0, 0, 0), 1)



相关文章
|
7月前
|
监控 计算机视觉 知识图谱
YOLOv10的改进、部署和微调训练总结
YOLOv10在实时目标检测中提升性能与效率,通过无NMS训练解决延迟问题,采用一致的双任务和效率-精度驱动的模型设计。YOLOv10-S比RT-DETR-R18快1.8倍,YOLOv10-B比YOLOv9-C延迟减少46%。新方法包括一致性双标签分配,优化计算冗余和增强模型能力。实验结果显示YOLOv10在AP和延迟上均有显著改善。文章还提供了部署和微调YOLOv10的示例代码。
818 2
|
8月前
|
缓存 并行计算 C++
实践教程|旋转目标检测模型-TensorRT 部署(C++)
实践教程|旋转目标检测模型-TensorRT 部署(C++)
204 0
|
PyTorch 测试技术 API
Pytorch模型训练与在线部署
本文以CIFAR10数据集为例,通过自定义神经元网络,完成模型的训练,并通过Flask完成模型的在线部署与调用,考略到实际生产模型高并发调用的述求,使用service_streamer提升模型在线并发能力。
712 1
|
8月前
|
人工智能 算法 开发工具
Mixtral 8X7B MoE模型在阿里云PAI平台的微调部署实践
Mixtral 8x7B 是Mixtral AI最新发布的大语言模型,是当前最为先进的开源大语言模型之一。阿里云人工智能平台PAI,提供了对于 Mixtral 8x7B 模型的全面支持,开发者和企业用户可以基于 PAI-快速开始轻松完成Mixtral 8x7B 模型的微调和部署。
|
1月前
基于VisualGLM-6B大模型的本地部署与推理
本文是基于清华开源的VisualGLM-6B 支持图像中英文的多模态对话语言模型,进行了一系列本地的简单部署,包括环境配置、模型部署、演示推理、模型微调(官方提供的代码),由于个人电脑显存不足,最后是在阿里云服务器交互式平台DSW终端进行微调和训练操作的。
82 17
|
3月前
|
机器学习/深度学习 人工智能 自然语言处理
NVIDIA Triton系列13-用 FasterTransformer 和 Triton 加速大型 Transformer 模型的推理
本文介绍了 NVIDIA FasterTransformer 库及其在加速大型 Transformer 模型推理中的应用。FasterTransformer 是一个高效、可扩展的库,支持分布式多 GPU 推理,特别适合处理具有数万亿参数的模型。文章还详细讲解了如何使用 FasterTransformer 和 NVIDIA Triton 推理服务器优化 GPT-J 和 T5 模型的推理性能,包括张量并行、流水线并行等技术。
106 0
NVIDIA Triton系列13-用 FasterTransformer 和 Triton 加速大型 Transformer 模型的推理
|
5月前
|
机器学习/深度学习 并行计算 PyTorch
PyTorch与CUDA:加速深度学习模型训练的最佳实践
【8月更文第27天】随着深度学习应用的广泛普及,高效利用GPU硬件成为提升模型训练速度的关键。PyTorch 是一个强大的深度学习框架,它支持动态计算图,易于使用且高度灵活。CUDA (Compute Unified Device Architecture) 则是 NVIDIA 开发的一种并行计算平台和编程模型,允许开发者直接访问 GPU 的并行计算能力。本文将详细介绍如何利用 PyTorch 与 CUDA 的集成来加速深度学习模型的训练过程,并提供具体的代码示例。
301 1
|
5月前
|
数据采集 人工智能 小程序
如何制作数据集并基于yolov5训练成模型并部署
这篇文章介绍了如何为YOLOv5制作数据集、训练模型、进行模型部署的整个流程,包括搜集和标注图片、创建数据集文件夹结构、编写配置文件、训练和评估模型,以及将训练好的模型部署到不同平台如ROS机器人、微信小程序和移动应用等。
如何制作数据集并基于yolov5训练成模型并部署
|
6月前
|
机器学习/深度学习 数据采集 PyTorch
PyTorch模型训练与部署流程详解
【7月更文挑战第14天】PyTorch以其灵活性和易用性在模型训练与部署中展现出强大的优势。通过遵循上述流程,我们可以有效地完成模型的构建、训练和部署工作,并将深度学习技术应用于各种实际场景中。随着技术的不断进步和应用的深入,我们相信PyTorch将在未来的机器学习和深度学习领域发挥更加重要的作用。
|
7月前
|
固态存储
【YOLO系列】YOLOv10模型结构详解与推理部署实现
【YOLO系列】YOLOv10模型结构详解与推理部署实现
1282 0