江大白 | YOLOv10检测算法,ONNX模型部署和性能对比分析

本文来源公众号“江大白”,仅用于学术分享,侵权删,干货满满。

原文链接:YOLOv10检测算法,ONNX模型部署和性能对比分析

以下文章来源于微信公众号:DeepDriving

作者:一天到晚潜水的鱼

链接:https://mp.weixin.qq.com/s/w0Ss9vcseNCEoK2UWugCNw

本文仅用于学术分享,如有侵权,请联系后台作删文处理

导读

YOLO系列目标检测算法迎来了其第十个版本,本文不仅对YOLOv10进行了详细介绍,还为大家演示了如何通过ONNX部署。部署后的模型与Pytorch推理结果无异,希望对大家有所帮助。

0. YOLOv10简介

YOLOv10是清华大学最近开源的一个实时端到端的目标检测算法,解决了以往版本YOLO系列目标检测算法在后处理和模型架构方面的不足。通过消除非极大值抑制(NMS)操作和优化模型架构YOLOv10显著降低计算开销的同时还实现了最先进的性能

YOLOv10的模型架构由以下几个部分组成:

  • 主干网络:使用增强版的CSPNet来提取图像特征,它能改善梯度流并减少计算量。

  • 颈部:采用PAN结构汇聚不同尺度的特征,有效地实现多尺度特征融合。

  • 一对多预测头:在训练过程中为每个对象生成多个预测,用来提供丰富的监督信号从而提高学习的准确性;在推理阶段不生效,从而减少计算量。

  • 一对一预测头:在推理过程中为每个对象生成一个最佳预测,无需NMS操作,从而减少延迟并提高推理效率。

YOLOv10的主要特点如下:

  • 利用一致的双重分配来消除对NMS的需求,从而减少推理延迟。

  • 从推理效率和准确性的角度出发全面优化各种组件,包括轻量级分类头、空间通道去耦下采样和等级引导块设计。

  • 引入大核卷积和部分自注意模块,在不增加大量计算成本的情况下提高性能。

官方发布了NX各种型号的模型,以满足不同应用的需求:

  • YOLOv10-N:用于资源极其有限环境的超小型版本。

  • YOLOv10-S:兼顾速度和精度的小型版本。

  • YOLOv10-M:通用的中型版本。

  • YOLOv10-B:平衡型,宽度增加,精度更高。

  • YOLOv10-L:大型版本,精度更高,但计算资源增加。

  • YOLOv10-X:超大型版本,可实现最高的精度和性能。

「本文主要介绍如何基于ONNXRuntime框架部署onnx格式的YOLOv10模型,以及YOLOv10RT-DETR等算法的性能对比。」

1. 准备工作

首先把代码从GitHubclone下来

git clone https://github.com/THU-MIG/yolov10.git

然后执行下面的命令用conda创建Python环境并安装相关的依赖库和YOLOv10

conda create -n yolov10 python=3.9conda activate yolov10pip install -r requirements.txtpip install -e .

这里需要注意的是,如果使用的是低版本的pip,可能会报类似下面的错误:

ERROR: File "setup.py" or "setup.cfg" not found. Directory cannot be installed in editable mode: /path/to/yolov10
(A "pyproject.toml" file was found, but editable mode currently requires a setuptools-based build.)

这种情况需要升级pip的版本,最新版本24.0实测是没有问题的。

pip install --upgrade pip

安装成功后,从GitHub的release中下载PyTorch格式的模型权重,然后执行下面的命令就可以导出onnx模型了。

yolo export model=yolov10n/s/m/b/l/x.pt format=onnx opset=13 simplify

2. onnx模型部署

2.1 加载onnx模型

首先导入onnxruntime包,然后调用其API加载模型即可:

import onnxruntime as ort

session = ort.InferenceSession("yolov10m.onnx", providers=["CUDAExecutionProvider"])

​​​​​​​这里的providers参数根据自己的实际情况设置,我使用的是GPU所以设置的是"CUDAExecutionProvider"。如果用CPU进行推理,则需设置为"CPUExecutionProvider";如果有TensorRT的环境,还可以设置为"TensorrtExecutionProvider"。​​​​​​​

模型加载成功后,我们可以查看一下模型的输入、输出层的属性:

for input in session.get_inputs():
    print("input name: ", input.name)
    print("input shape: ", input.shape)
    print("input type: ", input.type)

for output in session.get_outputs():
    print("output name: ", output.name)
    print("output shape: ", output.shape)
    print("output type: ", output.type)

结果如下:

input name:  images
input shape:  [1, 3, 640, 640]
input type:  tensor(float)
output name:  output0
output shape:  [1, 300, 6]
output type:  tensor(float)

从上面的打印信息可以知道,模型有一个尺寸为[1, 3, 640, 640]的输入层和一个尺寸分别为[1, 300, 6]的输出层。

2.2 数据预处理

OpenCV读入图片后,首先需要对图片做预处理:

image = cv2.imread("soccer.jpg")
print("image shape: ", image.shape)
image_height, image_width, _ = image.shape
_, _, model_height, model_width = session.get_inputs()[0].shape

input_tensor, ratio, x_offset, y_offset = preprocess(image, 
            image_width, image_height, model_width, model_height)

YOLOv10在做数据预处理的时候是对原始图像做等比例缩放的,如果缩放后的图像某个维度上比目标值小,那么就需要进行填充。举个例子:假设输入图像尺寸为1920x1058,模型输入尺寸为640x640,按照等比例缩放的原则缩放后的图像尺寸为640x352,那么在y方向上还需要填充640-352=288,即分别在图像的顶部和底部各填充144行像素。最终实现的效果如下:

整个数据预处理的流程如下:

  1. OpenCV读取的BGR格式图片转换为RGB格式;

  2. 计算缩放比例和需要填充的区域,把原始图片进行等比例缩放,对不足的区域进行填充让输入图片的尺寸匹配模型的输入尺寸;

  3. 对像素值除以255做归一化操作;

  4. 把图像数据的通道顺序由HWC调整为CHW

  5. 扩展数据维度,将数据的维度调整为NCHW

实现上述功能的预处理函数preprocess的代码如下:

def preprocess(bgr_image, src_w, src_h, dst_w, dst_h):
    image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB)

    ratio = min(dst_w/src_w, dst_h/src_h)
    border_w = int(round(src_w * ratio / 2) * 2)
    border_h = int(round(src_h * ratio / 2) * 2)
    x_offset = (dst_w - border_w ) // 2  
    y_offset = (dst_h - border_h ) // 2

    image = cv2.resize(image, (border_w, border_h))
    image = cv2.copyMakeBorder(
        image, y_offset, y_offset, x_offset, x_offset, 
        cv2.BORDER_CONSTANT, value=(114, 114, 114)
        )

    image = image.astype(np.float32) / 255.0
    image = np.transpose(image, (2, 0, 1))
    input_tensor = np.expand_dims(image, axis=0)
    return input_tensor, ratio, x_offset, y_offset

经过预处理后,输入数据input_tensor的维度变为[1, 3, 640, 640],与模型要求的输入尺寸一致。

2.3 模型推理

准备好输入数据以后,就可以送入模型进行推理:

outputs = session.run(None, {session.get_inputs()[0].name: input_tensor})
output = np.squeeze(outputs[0])
print("output shape: ", output.shape)

YOLOv10只有一个输出分支,所以只要取outputs[0]的数据进行处理,去掉batch这个维度后,模型输出的维度为300x6

output.shape:  (300, 6)
2.4 后处理

从前文知道模型输出的维度为300x6,其中300表示模型在一张图片上最多能检测的目标数量,6则表示每个目标包含4个坐标属性(xmin,ymin,xmax,ymax)和1个类别置信度以及1个类别索引。每个目标的坐标信息都是相对于模型的输入尺寸的,由于预处理的时候在边上做了填充,所以后处理的时候要把每个坐标值减掉对应的偏移值;如果要恢复到原始图像的尺寸,还需要除以预处理时使用的缩放比例系数。与RT-DETR一样,YOLOv10的检测结果不需要再做NMS这些额外的后处理操作,处理过程非常简单。后处理的代码如下:

for i in range(output.shape[0]):
  # 读取类别置信度
  confidence = output[i][4]
  # 用阈值进行过滤
  if confidence > 0.5:
      # 读取类别索引
      label = int(output[i][5])
      # 读取类坐标值,把坐标还原到原始图像
      xmin = int((output[i][0] - x_offset) / ratio)
      ymin = int((output[i][1] - y_offset) / ratio)
      xmax = int((output[i][2] - x_offset) / ratio)
      ymax = int((output[i][3] - y_offset) / ratio)

      # 可视化
      class_name = COCO_CLASSES[label]
      box_color = np.array(COLOR_LIST[label]) * 255
      box_color = (int(box_color[0]), int(box_color[1]), int(box_color[2]))
      cv2.rectangle(image, (xmin, ymin), (xmax, ymax), box_color, 4)
      # 省略.....

来看一下检测效果:

下面是用官方代码基于PyTorch推理的结果:

可以看到,ONNXRuntimePyTorch推理的结果是一致的。

3. 推理耗时对比

这里的对比仅对比模型本身的推理耗时,不包含后处理操作。本文在GeForce GTX 1650 Ti显卡上,基于ONNXRuntime框架分别采用CUDATensorRT后端对YOLOv10YOLOv9RT-DETR的各个模型进行测试,数据精度统一采用FP32,模型输入尺寸统一设置为640x640。各模型的推理耗时(单位为毫秒)测试结果如下:

模型CUDATensorRT
yolov10n107
yolov10s1713
yolov10m3427
yolov10b4437
yolov10l5546
yolov10x8064
yolov9-c5241
yolov9-e10682
rtdetr_r18vd_6x5226
rtdetr_r34vd_6x6636
rtdetr_r50vd_6x9452
rtdetr_r50vd_m_6x6640
rtdetr_r101vd_6x13389

YOLOv10的论文里说YOLOv10-SRT-DETR-R181.8倍,YOLOv10-XRT-DETR-R1011.3倍,YOLOv10-B的推理延迟比YOLOv9-C减少了46%。从我测试的结果来看,YOLOv10-S/X不止比RT-DETR-R18/R101快一点几倍,YOLOv10-B则没有比YOLOv9-C快那么多。

总的来说,YOLOv10的性能确实比之前的模型要强一些,新一代卷王名不虚传。

4. 参考资料

  • YOLOv10: Real-Time End-to-End Object Detection

  • https://docs.ultralytics.com/zh/models/yolov10/

THE END !

文章结束,感谢阅读。您的点赞,收藏,评论是我继续更新的动力。大家有推荐的公众号可以评论区留言,共同学习,一起进步。

  • 28
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: YOLOv5是一种流行的目标检测算法,且具有轻量级版本YOLOv5-Lite。而ONNX是一种跨平台、高性能深度学习模型表示格式。下面是关于YOLOv5-Lite模型转换为ONNX的描述: 首先,我们需要在本地安装好YOLOv5,并下载官方提供的权重文件。然后,通过运行以下命令在本地将权重文件转换为PyTorch模型: ``` python models/export.py --weights yolov5s.pt --img 640 --batch 1 ``` 接下来,我们可以运行以下命令将PyTorch模型转换为ONNX格式: ``` python -c "import torch; model = torch.hub.load('ultralytics/yolov5', 'custom', path='yolov5s.pt'); model.model[-1].export = torch.onnx.export(model.model[-1], torch.zeros(1, 3, 640, 640), 'yolov5s.onnx')" ``` 在这个命令中,我们首先加载了已经转换为PyTorch格式的YOLOv5-Lite模型,然后通过调用`export`属性来设置导出参数。我们创建了一个`torch.zeros`的输入张量,大小为1x3x640x640,作为模型的输入。最后,我们将模型保存为ONNX格式的文件`yolov5s.onnx`。 通过以上步骤,我们成功地将YOLOv5-Lite模型转换为了ONNX格式。这样,我们就可以在各种平台和框架上使用这个模型进行目标检测,如TensorFlow、Caffe等。同时,在ONNX格式的模型中,可以利用一些优化工具进一步优化模型的推理性能。 ### 回答2: YOLOv5-Lite是YOLOv5的一个轻量化版本,它具有更小的模型大小和更快的推理速度。在对YOLOv5-Lite模型进行ONNX转换时,需要先将模型从PyTorch格式转换为ONNX格式。 首先,我们需要确保已安装好PyTorch和ONNXPython库。接下来,可以使用以下步骤将YOLOv5-Lite模型转换为ONNX模型: 1. 下载YOLOv5-Lite的PyTorch模型文件。可以在YOLOv5的官方GitHub存储库中找到预训练的YOLOv5-Lite模型。 2. 导入所需的库:torch和torchvision。 3. 加载YOLOv5-Lite的PyTorch模型。使用torch.load函数加载模型文件,并将其放在eval模式下。 4. 创建一个示例输入张量。输入张量的形状应该与模型期望的输入大小相匹配。可以使用torch.randn函数创建一个具有正确形状的示例输入张量。 5. 使用torch.onnx.export函数将PyTorch模型转换为ONNX模型。该函数需要指定导出的ONNX文件名、示例输入张量和其他可选参数,例如输出文件的输入名称和输出名称。 6. 检查转换后的ONNX模型是否已成功创建。可以通过在Python中加载ONNX模型并检查其结构来验证。 完成上述步骤后,YOLOv5-Lite模型将转换为ONNX格式,可以在各种ONNX兼容的平台上进行部署和推理。这包括使用ONNX运行时进行推理、将模型转换为OpenVINO格式以在Intel设备上运行等。 需要注意的是,每个模型的转换过程可能会有所不同,具体实现取决于所使用的库和框架版本。在进行模型转换之前,建议查阅相关文档和参考资料,并根据具体情况进行适当的调整和优化。 ### 回答3: YOLOv5-Lite是一种轻量级的物体检测模型,可以在计算资源有限的设备上进行高效的推理。将其转换为ONNX模型可以使其在各种平台和框架上进行部署和使用。 要将YOLOv5-Lite模型转换为ONNX模型,需要执行以下步骤: 1. 从YOLOv5的代码库中下载YOLOv5-Lite模型的权重文件(.pt格式)。 2. 使用PyTorch框架加载YOLOv5的模型权重并构建模型。 3. 将模型设置为推理模式,并将输入和输出的维度设置为合适的尺寸。 4. 使用torch.onnx.export方法将模型转换为ONNX格式。这个方法需要指定导出的模型、输入张量的形状和类型,以及导出ONNX模型的路径。 5. 确保安装了torch和onnx这两个Python库。 6. 运行转换代码,将YOLOv5-Lite模型转换为ONNX模型,并保存到指定路径。 转换后的ONNX模型可以在多个平台上进行部署和使用。可以使用ONNX Runtime库在各种设备上进行推理,包括CPU、GPU和边缘设备等。 总结来说,将YOLOv5-Lite转换为ONNX模型的过程包括下载权重文件、加载和构建模型、设置输入输出维度,然后使用torch.onnx.export方法将模型转换为ONNX格式。转换后的模型可以在不同平台上使用ONNX Runtime库进行推理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值