YOLOv8目标检测算法在地平线Bernoulli2架构BPU上高效摆设参考(PTQ方案)——RDK X3(旭日X3派)30fps

[复制链接]
发表于 2026-4-24 09:10:12 | 显示全部楼层 |阅读模式
—— 以RDK X3为例,修改Head部分,8ms疾速Python后处理处罚步调,30fps稳妥当当

本文在地平线对YOLOv8s的Backbone修改的根本上,提出一种在地平线Bernoulli2架构BPU上摆设YOLOv8的后处理处罚思绪。使用640×640分辨率,80种别基于COCO数据集的预练习权重,让BPU加速Backbone的Neck的部分,推理时间约62ms,使用numpy优化的后处理处罚部分,约8ms。并使用高效的Dataflow,充实使用X3的盘算资源,Python多进程推理+Web推流的方式完成了一个30fps的实时目标检测demo。本文全部步调均开源。
1.媒介

串行步调筹划结果如下图所示,RDK X3,4×A53@1.8Ghz,2×Bernoulli2 BPU@5TOPS,YOLOv8s,微调Backbone,1120万参数,640x640分辨率,80种别,单核模子,单CPU单帧单线程,纯numpy向量化后处理处罚。
使用OpenCV从当地读取一张图片,调解为NCHW的输入给bin模子,使用numpy后处理处罚,末了绘制检测结果。

并行步调筹划扬弃了OpenCV的BGR8的Mat,使用了nv12的数据作为关键数据,将bin模子设置为了nv12的输入,而且使用Python多进程来推理,使用TROS相干工具完成可视化,终极在X3大将YOLOv8跑到了30fps。
【RDK X3开辟板 推理YOLOv8s,30fps,Python多进程】 https://www.bilibili.com/video/BV1rz421B7jL/?share_source=copy_web&vd_source=5b24829d168bb2d02896ddeeaa6a20d2
2.后处理处罚优化

如下图所示,Backbone和Neck部分的算子均能较好的被Bernoulli2架构的BPU加速。
Head部分不能较好的被BPU加速,以是只能完全摘出来放到后处理处罚中,用CPU实现。同时由于摆设时只思量前向传播,以是不须要对8400个Grid Cell的信息全部盘算。紧张的优化加速思绪为先筛选,再盘算,这个盘算包罗Classify部分的Sigmoid,Bounding Box部分的DFL盘算(SoftMax回归 + Conv卷积求渴望)和特性解码盘算(dist2bbox, ltrb2xyxy)。

除NMS外的表明请参考作者YOLOv10的文章。
NMS操纵:去掉重复辨认的目标,得到终极的检测结果了,包罗种别(id),分数(score)和位置(xyxy)。
3. 步调参考

注:任何No such file or directory, No module named "xxx", command not found.等报错请细致查抄,请勿逐条复制运行,如果对修改过程不明确请前去地平线开辟者社区从YOLOv5开始相识。
下载地平线优化过的Backbone的堆栈,并参考YOLOv8官方文档,设置好情况

相干权重文件存储在HorizonRDK构造的model_zoo堆栈,相干的修改步调和性能、精度等数据请参考:【前沿算法】地平线适配 YOLOv8 -v1.0.0 (horizon.cc)
  1. $ git clone https://github.com/HorizonRDK/model_zoo.git
复制代码
卸载yolo相干的下令行下令,如许直接修改./ultralytics/ultralytics目次即可见效。

  1. $ conda list | grep ultralytics
  2. $ pip list | grep ultralytics # 或者
  3. # 如果存在,则卸载
  4. $ conda uninstall ultralytics
  5. $ pip uninstall ultralytics   # 或者
复制代码
修改Detect的输出头,直接将三个特性层的Bounding Box信息和Classify信息分开输出,一共6个输出头。

文件目次:./ultralytics/ultralytics/nn/modules/head.py,约第43行,Detect类的forward函数更换成以下内容:
  1. def forward(self, x):
  2.     bbox = []
  3.     cls = []
  4.     for i in range(self.nl):
  5.         bbox.append(self.cv2[i](x[i]))
  6.         cls.append(self.cv3[i](x[i]))
  7.     return (bbox, cls)
复制代码
运行以下Python脚本,如果有No module named onnxsim报错,安装一个即可

  1. from ultralytics import YOLO
  2. YOLO('yolov8s.pt').export(format='onnx', simplify=True, opset=11)
复制代码
参考天工开物工具链手册和OE包的参考,对模子举行查抄,全部算子均在BPU上,举行编译即可:

  1. (bpu) $ hb_mapper checker --model-type onnx --march bayes --model yolov8s.onnx
  2. (bpu) $ hb_mapper makertbin --model-type onnx --config ./yolov8s.yaml
复制代码
如果您须要使用OpenCV,发起使用NCHW的输入,编译时的yaml设置文件

  1. model_parameters:
  2.   onnx_model: './yolov8s_bernoulli2.onnx'
  3.   march: "bernoulli2"
  4.   layer_out_dump: False
  5.   working_dir: 'yolov8s_bernoulli2_NCHW'
  6.   output_model_file_prefix: 'yolov8s_bernoulli2_NCHW'
  7.   # remove_node_type: "Dequantize;"
  8. input_parameters:
  9.   input_name: ""
  10.   input_type_rt: 'rgb'
  11.   input_layout_rt: 'NCHW'
  12.   input_type_train: 'rgb'
  13.   input_layout_train: 'NCHW'
  14.   norm_type: 'data_scale'
  15.   scale_value: 0.003921568627451
  16. calibration_parameters:
  17.   cal_data_dir: './calibration_data_rgb_f32'
  18.   cal_data_type: 'float32'
  19. compiler_parameters:
  20.   compile_mode: 'latency'
  21.   debug: False
  22.   optimize_level: 'O3'
复制代码
如果您使用实时视频流检测,发起使用nv12为主的DataFlow筹划,共同hobot_dnn大概本文的hobot_py_dnn使用,编译时的yaml设置文件

  1. model_parameters:
  2.   onnx_model: './yolov8s_bernoulli2.onnx'
  3.   march: "bernoulli2"
  4.   layer_out_dump: False
  5.   working_dir: 'yolov8s_bernoulli2_nv12'
  6.   output_model_file_prefix: 'yolov8s_bernoulli2_nv12'
  7. input_parameters:
  8.   input_name: ""
  9.   input_type_rt: 'nv12'
  10.   input_type_train: 'rgb'
  11.   input_layout_train: 'NCHW'
  12.   norm_type: 'data_scale'
  13.   scale_value: 0.003921568627451
  14. calibration_parameters:
  15.   cal_data_dir: './calibration_data_rgb_f32'
  16.   cal_data_type: 'float32'
  17. compiler_parameters:
  18.   compile_mode: 'latency'
  19.   debug: False
  20.   optimize_level: 'O3'
复制代码
检察bbox信息的3个输出头的反量化节点名称

通过hb_mapper makerbin时的日志日志,看到巨细为[1, 64, 80, 80], [1, 64, 40, 40], [1, 64, 20, 20]的三个输出的名称为output0, 384, 394。
  1. ONNX IR version:          6
  2. Opset version:            ['ai.onnx v11', 'horizon v1']
  3. Producer:                 pytorch v2.2.0
  4. Domain:                   None
  5. Model version:            None
  6. Graph input:
  7.     images:               shape=[1, 3, 640, 640], dtype=FLOAT32
  8. Graph output:
  9.     output0:              shape=[1, 64, 80, 80], dtype=FLOAT32
  10.     384:                  shape=[1, 64, 40, 40], dtype=FLOAT32
  11.     394:                  shape=[1, 64, 20, 20], dtype=FLOAT32
  12.     379:                  shape=[1, 80, 80, 80], dtype=FLOAT32
  13.     389:                  shape=[1, 80, 40, 40], dtype=FLOAT32
  14.     399:                  shape=[1, 80, 20, 20], dtype=FLOAT32
复制代码
移除bbox信息的3个输出头的反量化节点

进入编译产物的目次
  1. $ cd yolov8s_bernoulli2
复制代码
检察可以被移除的反量化节点
  1. $ hb_model_modifier yolov8s_bernoulli2_nv12.bin
  2. $ hb_model_modifier yolov8s_bernoulli2_NCHW.bin
复制代码
输出日志日志如下,此中output0_HzDequantize, 384_HzDequantize, 394_HzDequantize三个节点是我们要移除的。
  1. 2024-06-08 06:53:54,548 INFO log will be stored in /ws/yolov8s_bernoulli2/hb_model_modifier.log
  2. 2024-06-08 06:53:54,566 INFO Nodes that can be deleted: ['output0_HzDequantize', '379_HzDequantize', '384_HzDequantize', '389_HzDequantize', '394_HzDequantize', '399_HzDequantize']
复制代码
使用以下下令移除上述三个反量化节点,注意,导出时这些名称大概差别,请细致确认。
  1. $ hb_model_modifier yolov8s_bernoulli2_nv12.bin -r output0_HzDequantize -r 384_HzDequantize -r 394_HzDequantize
  2. $ hb_model_modifier yolov8s_bernoulli2_NCHW.bin -r output0_HzDequantize -r 384_HzDequantize -r 394_HzDequantize
复制代码
板端性能测试

使用scp等工具将bin模子拷贝到板端,使用以下下令测试性能。约莫单线程能跑到17fps,占用BPU一个核到100%,双线程34fps,双核BPU占用到200%,推理的部分能高出30fps,不构成瓶颈,接下来偏重优化后处理处罚。
  1. hrt_model_exec perf --model_file yolov8s_bernoulli2.bin \
  2.                       --model_name="" \
  3.                       --core_id=0 \
  4.                       --frame_count=200 \
  5.                       --perf_time=0 \
  6.                       --thread_num=2 \
  7.                       --profile_path="."
复制代码
4. 串行步调筹划

使用以下步调时记得修改图片和模子文件路径,缺包少库请自行pip install安装。注意,此时使用的是NCHW输入的模子。
  1. # Copyright (c) 2024,WuChao D-Robotics.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. #     http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import cv2
  15. import numpy as np
  16. from scipy.special import softmax
  17. from time import time
  18. from hobot_dnn import pyeasy_dnn as dnn
  19. img_path = "kite.jpg"
  20. result_save_path = "kite.result.jpg"
  21. quantize_model_path = "./yolov8s_bernoulli2_NCHW_modified.bin"
  22. input_image_size = 640
  23. conf=0.5
  24. iou=0.5
  25. conf_inverse = -np.log(1/conf - 1)
  26. print("sigmoid_inverse threshol = %.2f"%conf_inverse)
  27. # 一些常量或函数
  28. coco_names = [
  29.     "person", "bicycle", "car", "motorcycle", "airplane",
  30.     "bus", "train", "truck", "boat", "traffic light",
  31.     "fire hydrant", "stop sign", "parking meter", "bench", "bird",
  32.     "cat", "dog", "horse", "sheep", "cow",
  33.     "elephant", "bear", "zebra", "giraffe", "backpack",
  34.     "umbrella", "handbag", "tie", "suitcase", "frisbee",
  35.     "skis", "snowboard", "sports ball", "kite", "baseball bat",
  36.     "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle",
  37.     "wine glass", "cup", "fork", "knife", "spoon",
  38.     "bowl", "banana", "apple", "sandwich", "orange",
  39.     "broccoli", "carrot", "hot dog", "pizza", "donut",
  40.     "cake", "chair", "couch", "potted plant", "bed",
  41.     "dining table", "toilet", "tv", "laptop", "mouse",
  42.     "remote", "keyboard", "cell phone", "microwave", "oven",
  43.     "toaster", "sink", "refrigerator", "book", "clock",
  44.     "vase", "scissors", "teddy bear", "hair drier", "toothbrush"
  45.     ]
  46. yolo_colors = [
  47.     (56, 56, 255), (151, 157, 255), (31, 112, 255), (29, 178, 255),
  48.     (49, 210, 207), (10, 249, 72), (23, 204, 146), (134, 219, 61),
  49.     (52, 147, 26), (187, 212, 0), (168, 153, 44), (255, 194, 0),
  50.     (147, 69, 52), (255, 115, 100), (236, 24, 0), (255, 56, 132),
  51.     (133, 0, 82), (255, 56, 203), (200, 149, 255), (199, 55, 255)]
  52. def draw_detection(img, box, score, class_id):
  53.     x1, y1, x2, y2 = box
  54.     color = yolo_colors[class_id%20]
  55.     cv2.rectangle(img, (x1, y1),
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表