Yolov7如期而至,奉上ONNXRuntime的推理部署流程(CPU/GPU)

这篇具有很好参考价值的文章主要介绍了Yolov7如期而至,奉上ONNXRuntime的推理部署流程(CPU/GPU)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、V7效果真的的v587,识别率和速度都有了极大的提升,这里先放最新鲜的github链接:

https://github.com/WongKinYiu/yolov7

二、v7的训练我这里就不做过多的赘述了,这里主要是进行讲解怎么把.pt文件转为onnx和后续的推理问题:

 2.1首先是pip的版本非常重要,博主亲自测试了,发现确实只有对应版本,ONNX才能成功,以至于后续的onnxruntime才能正常的ReadLoad~~

pip install onnx==1.12.0
pip install onnx-simplifier==0.4.0
pip install coloredlogs==15.0.1
pip install humanfriendly==10.0
pip install onnxruntime-gpu==1.12.0
pip isntall onnxsim-no-ort==0.4.0
pip install opencv-python==4.5.2.52(注意cv2一定不能用4.6.0)
pip install protobuf==3.19.4
pip install setuptools==63.2.0

我进行运行的torch和torchvision版本是:

torch1.12.0+cu113  +  torchvision 0.13.0+cu113 + python3.8

这里值得注意的是,在v7的requirements.txt中备注了不要使用这个版本训练,但是做推理的时候我发现,就这个版本可以完成推理,太难了QAQ。。。。

这里推荐一个下载torch的.whl文件的链接:https://download.pytorch.org/whl/torch_stable.html

在里面找到对应的版本就行了(PS:只要torch与torchvison版本对应上就行,cu前缀其实限制没那么多,我的cuda是11.0,但是我pip install 的torch轮子的cu113的O(∩_∩)O):

Yolov7如期而至,奉上ONNXRuntime的推理部署流程(CPU/GPU)

2.2 有了转换环境之后我们进行export.py的关键步骤:

在V7项目的根目录下有export.py文件,这里不对文件内部做修改,可以直接执行命令语句:

python export.py --grid --end2end --simplify --topk-all 100 --iou-thres 0.3 --conf-thres 0.8 --img-size 640 640 --max-wh 640 --weights weights/onnxruntime.pt

 切记需要将这些超参数打上,看了下解释因该是做了模型剪枝simple啥的,所以相关的参数必须齐全,--weights这里写你们自己的模型pt文件就可以了,其它参数根据自己的模型进行修改就好了,我这里拿V7官方的预训练好的模型(yolov7-tiny.pt)进行演示:

Yolov7如期而至,奉上ONNXRuntime的推理部署流程(CPU/GPU)

 忽略一些警告,如下图所示就这么轻松转换成功啦:Yolov7如期而至,奉上ONNXRuntime的推理部署流程(CPU/GPU)

 我们在netro(https://netron.app/)中打开这个onnx看一看,发现在输出已经处理好变为7维的向量了:

Yolov7如期而至,奉上ONNXRuntime的推理部署流程(CPU/GPU)

 三、关于推理部署

有了onnx文件,我们需要放在onnxruntime工具包下做推理

3.1 加载推理模型:

    def init_engine(self):
        providers = ['CUDAExecutionProvider', 'CPUExecutionProvider'] if self.device else ['CPUExecutionProvider']
        self.session = ort.InferenceSession(self.weights, providers=providers)

3.2 对输入图像进行前处理(做灰条填充)+变为tensor能认的4维:

    def letterbox(self, im, color=(114, 114, 114), auto=True, scaleup=True, stride=32):
        # 调整大小和垫图像,同时满足跨步多约束
        shape = im.shape[:2]  # current shape [height, width]
        new_shape = self.img_new_shape

        # 如果是单个size的话,就在这里变成一双
        if isinstance(new_shape, int):
            new_shape = (new_shape, new_shape)

        # 尺度比 (new / old)
        r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
        if not scaleup:  # 只缩小,不扩大(为了更好的val mAP)
            r = min(r, 1.0)

        # 计算填充
        new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
        dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1]  # wh padding

        if auto:  # 最小矩形区域
            dw, dh = np.mod(dw, stride), np.mod(dh, stride)  # wh padding

        dw /= 2  # divide padding into 2 sides
        dh /= 2

        if shape[::-1] != new_unpad:  # resize
            im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
        top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
        left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
        im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)  # add border
        im = im.transpose((2, 0, 1))
        im = np.expand_dims(im, 0)
        im = np.ascontiguousarray(im)
        im = im.astype(np.float32)
        im /= 255
        return im, r, (dw, dh)

3.3 然后就可以放如onnxruntime中得到那7维的输出结果了:

    def preprocess(self, image_path):
        self.img = cv2.imread(image_path)
        self.img = cv2.cvtColor(self.img, cv2.COLOR_BGR2RGB)
        image = self.img.copy()
        im, ratio, dwdh = self.letterbox(image, auto=False)
        t1 = time.time()
        outputs = self.predict(im)
        print("推理时间", (time.time() - t1) * 1000, ' ms')
        ori_images = [self.img.copy()]
        for i, (batch_id, x0, y0, x1, y1, cls_id, score) in enumerate(outputs):
            image = ori_images[int(batch_id)]
            box = np.array([x0, y0, x1, y1])
            box -= np.array(dwdh * 2)
            box /= ratio
            box = box.round().astype(np.int32).tolist()
            cls_id = int(cls_id)
            score = round(float(score), 3)
            name = self.names[cls_id]
            color = self.colors[name]
            name += ' ' + str(score)
            cv2.rectangle(image, box[:2], box[2:], color, 2)
            cv2.putText(image, name, (box[0], box[1] - 2), cv2.FONT_HERSHEY_SIMPLEX, 0.75, [225, 255, 255], thickness=2)
        a = Image.fromarray(ori_images[0])
        return a

3.4 pre的部分比较简单基本onnx都处理过了,直接拿字典结果就可以

    def predict(self, im):
        outname = [i.name for i in self.session.get_outputs()]
        inname = [i.name for i in self.session.get_inputs()]
        inp = {inname[0]: im}
        outputs = self.session.run(outname, inp)[0]
        return outputs

3.5 可以看看推理时间还是非常快的,单帧在10ms左右,真是100FPS!!!!!

Yolov7如期而至,奉上ONNXRuntime的推理部署流程(CPU/GPU)

3.6 放一张马的传统,哈哈:

Yolov7如期而至,奉上ONNXRuntime的推理部署流程(CPU/GPU)

2022年9月21日 最后补充下,其实上面就是源码,把它拼接到一起就是一个整体脚本了呀😂

import os
import cv2
import time
import requests
import argparse
import random
import numpy as np
import onnxruntime as ort
from PIL import Image

names = ["1", "2", "3", "4", "5", "6", "unknow" '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']


class ONNX_engine():
    def __init__(self, weights, size, cuda) -> None:
        self.img_new_shape = (size, size)
        self.weights = weights
        self.device = cuda
        self.init_engine()
        self.names = names
        self.colors = {name: [random.randint(0, 255) for _ in range(3)] for i, name in enumerate(self.names)}

    def init_engine(self):
        providers = ['CUDAExecutionProvider', 'CPUExecutionProvider'] if self.device else ['CPUExecutionProvider']
        self.session = ort.InferenceSession(self.weights, providers=providers)

    def predict(self, im):
        outname = [i.name for i in self.session.get_outputs()]
        inname = [i.name for i in self.session.get_inputs()]
        inp = {inname[0]: im}
        outputs = self.session.run(outname, inp)[0]
        # print(outputs.shape)
        return outputs

    def preprocess(self, image_path):
        print('----------', image_path, '---------------')
        self.img = cv2.imread(image_path)
        self.img = cv2.cvtColor(self.img, cv2.COLOR_BGR2RGB)
        image = self.img.copy()
        im, ratio, dwdh = self.letterbox(image, auto=False)
        t1 = time.time()
        outputs = self.predict(im)
        print("推理时间", (time.time() - t1) * 1000, ' ms')
        ori_images = [self.img.copy()]
        for i, (batch_id, x0, y0, x1, y1, cls_id, score) in enumerate(outputs):
            image = ori_images[int(batch_id)]
            box = np.array([x0, y0, x1, y1])
            box -= np.array(dwdh * 2)
            box /= ratio
            box = box.round().astype(np.int32).tolist()
            cls_id = int(cls_id)
            score = round(float(score), 3)
            name = self.names[cls_id]
            color = self.colors[name]
            name += ' ' + str(score)
            print("pre result is :", box, name)
            cv2.rectangle(image, box[:2], box[2:], color, 2)
            cv2.putText(image, name, (box[0], box[1] - 2), cv2.FONT_HERSHEY_SIMPLEX, 0.75, [225, 255, 255], thickness=1)
        a = Image.fromarray(ori_images[0])
        return a

    def letterbox(self, im, color=(114, 114, 114), auto=True, scaleup=True, stride=32):
        # 调整大小和垫图像,同时满足跨步多约束
        shape = im.shape[:2]  # current shape [height, width]
        new_shape = self.img_new_shape

        # 如果是单个size的话,就在这里变成一双
        if isinstance(new_shape, int):
            new_shape = (new_shape, new_shape)

        # 尺度比 (new / old)
        r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
        if not scaleup:  # 只缩小,不扩大(为了更好的val mAP)
            r = min(r, 1.0)

        # 计算填充
        new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
        dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1]  # wh padding

        if auto:  # 最小矩形区域
            dw, dh = np.mod(dw, stride), np.mod(dh, stride)  # wh padding

        dw /= 2  # divide padding into 2 sides
        dh /= 2

        if shape[::-1] != new_unpad:  # resize
            im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
        top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
        left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
        im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)  # add border
        im = im.transpose((2, 0, 1))
        im = np.expand_dims(im, 0)
        im = np.ascontiguousarray(im)
        im = im.astype(np.float32)
        im /= 255
        return im, r, (dw, dh)


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--weights', type=str, default='./weights/coil_onnxruntime.onnx', help='weights path of onnx')
    parser.add_argument('--cuda', type=bool, default=True, help='if your pc have cuda')
    parser.add_argument('--imgs_path', type=str, default='inference/images', help='infer the img of path')
    parser.add_argument('--size', type=int, default=640, help='infer the img size')
    opt = parser.parse_args()

    onnx_engine = ONNX_engine(opt.weights, opt.size, opt.cuda)
    save_path = './inference'
    for img_path in os.listdir(opt.imgs_path):
        img_path_file = opt.imgs_path + '/' + img_path
        # print('The img path is: ', img_path_file)
        a = onnx_engine.preprocess(img_path_file)
        # a.save(save_path + '/' + 'pre_img' + '/' + img_path)
        print('*'*50)

参考代码:https://colab.research.google.com/github/WongKinYiu/yolov7/blob/main/tools/YOLOv7onnx.ipynb文章来源地址https://www.toymoban.com/news/detail-496481.html

到了这里,关于Yolov7如期而至,奉上ONNXRuntime的推理部署流程(CPU/GPU)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ONNXRuntime介绍及如何使用ONNXRuntime进行模型推理

    ONNXRuntime介绍及如何使用ONNXRuntime进行模型推理 随着人工智能的发展,越来越多的深度学习模型被应用到实际场景中。ONNX(Open Neural Network Exchange)是一个可跨平台、可扩展的开源模型交换格式,许多常见的深度学习框架都支持导出ONNX模型。而ONNXRuntime是由微软开发的一个高性

    2024年02月16日
    浏览(38)
  • 使用onnxruntime-gpu 模型推理

    1.安装onnxruntime-gpu 新版的onnxruntime-gpu 即支持gpu的推理,也支持cpu的推理。 卸载旧的1.7.1 cpu版本,安装新的gpu版本: 检查是否安装成功: 2.修改推理代码 在推理代码上增加 providers参数,选择推理的框架。看自己支持哪个就选择自己支持的就可以了。 如果运行推理代码出现

    2024年02月15日
    浏览(39)
  • C++使用onnxruntime/opencv对onnx模型进行推理(附代码)

    结果: current image classification : French bulldog, possible : 16.17 对两张图片同时进行推理 current image classification : French bulldog, possible : 16.17 current image class ification : hare, possible : 8.47 https://download.csdn.net/download/qq_44747572/87810859 https://blog.csdn.net/qq_44747572/article/details/131631153

    2024年02月05日
    浏览(50)
  • onnxruntime推理时切换CPU/GPU以及修改onnx输入输出为动态

    前言 onnx模型作为中间模型,相较于pytorch直接推理,是有加速度效果的,且推理代码简单,不需要load各种网络。最近某些项目因为显存不够,onnxruntime推理时切换CPU/GPU,实现某些模型在CPU上推理,某些在GPU上推理。 查了一些别人的文章发现很多人都说onnxruntime推理没法像py

    2024年02月12日
    浏览(51)
  • 自定义 bert 在 onnxruntime 推理错误:TypeError: run(): incompatible function arguments

    arg0: List[str] arg1: Dict[str, object] 对应的参数 arg0=[‘output’] 参数类型正确 arg1=toks 表面看参数也正常,打印看看toks的每个值的类型 type(toks[‘input_ids’]) 输出为 class ‘torch.Tensor’, 实际需要输入类型为 class ‘numpy.ndarray’ 再次执行代码,正常运行,无报错!!

    2024年01月23日
    浏览(32)
  • TRT4-trt-integrate - 3 使用onnxruntime进行onnx的模型推理过程

    onnx是microsoft开发的一个中间格式,而onnxruntime简称ort是microsoft为onnx开发的推理引擎。 允许使用onnx作为输入进行直接推理得到结果。 建立一个InferenceSession,塞进去的是onnx的路径,实际运算的后端选用的是CPU 也可以选用cuda等等 之后就是预处理 session.run就是运行的inference过程

    2024年02月15日
    浏览(39)
  • 【模型部署 01】C++实现GoogLeNet在OpenCV DNN、ONNXRuntime、TensorRT、OpenVINO上的推理部署

    深度学习领域常用的基于CPU/GPU的推理方式有OpenCV DNN、ONNXRuntime、TensorRT以及OpenVINO。这几种方式的推理过程可以统一用下图来概述。整体可分为模型初始化部分和推理部分,后者包括步骤2-5。 以GoogLeNet模型为例,测得几种推理方式在推理部分的耗时如下: 结论: GPU加速首选

    2024年02月06日
    浏览(54)
  • VS c++ onnxruntime 环境配置、onnx教程、部署推理模型、sklearn pkl模型转onnx、问题汇总

    目录 一、初步认识ONNX 二、pkl转ONNX+可视化模型 三、ONNX Runtime运行时 3.1 相关介绍(了解此运行时): 3.2 VS、c++部署onnxruntime 3.3 头文件引用的一些问题 四、问题汇总: 1. 类没有成员 2. 版本兼容问题 3. 3.“GetInputName“: 不是 “Ort::Session“ 的成员 官网: ONNX Runtime | Home GitHub

    2024年04月09日
    浏览(39)
  • 如何加载模型YOLOv8 ONNXRuntime

    YOLOv8 是 YOLO(You Only Look Once)目标检测系统的最新版本(v8)。YOLO 是一种实时、一次性目标检测系统,旨在在网络的单次前向传递中执行目标检测,使其快速高效。YOLOv8是之前YOLO模型的改进版本,具有更高的精度和更快的推理速度。 ONNX(开放神经网络交换)是一种表示深度

    2024年02月14日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包