【RK3588】YOLO V5在瑞芯微板子上部署问题记录汇总
YOLO V5
训练模型部署到瑞芯微的板子上面,官方是有给出案例和转过详情的。并且也提供了Python
版本的推理代码,以及C语言
的代码。
但是,对于转换过程中的细节,哪些需要改?怎么改?如何改,和为什么这样改的问题,并没有给出详细的介绍。于是,本文就是对官方给出部分外的一个补充。这部分都是踩过坑的总结,相信会对你的操作会有较大帮助的。
一、从pytorch
的pt
到rknn
转换
- 第一步: 使用
yolov5
提供的export.py
函数导出yolov5.onnx
模型
python3 export.py --weights yolov5s.pt --img-size 640 --include onnx
- 第二步:使用
onnxsim
简化导出的yolov5.onnx
模型
onnxsim是一个基于ONNX规范的工具,通过简化ONNX模型和优化ONNX模型,帮助用户减小模型大小、提高模型的推理速度和减少推理过程中的内存开销。
onnxsim的工作原理是将一个ONNX模型简化成最少的节点,并优化这些节点,以最小化推理过程中的开销。
同时,onnxsim还可以处理支持的神经网络层类型,支持多个平台,例如:CPU,GPU, FPGA等。
onnxsim
安装和使用:onnx-simplifier
pip3 install onnxsimThen:onnxsim input_onnx_model output_onnx_model
- 第三步:要完全使用rknn提供的部署转换代码,需要根据简化后的onnx模型,选取合适层的输出,以替代以下代码中的
‘378’,‘439’和‘500’
,如下图onnx例子中的'onnx::Reshape_446',‘onnx::Reshape_484’,‘onnx::Reshape_522’
。(这三个name,可能都是不一样的,是什么就填什么即可)
# Load ONNX model
print('--> Loading model')
ret = rknn.load_onnx(model=ONNX_MODEL, outputs=['onnx::Reshape_446', 'onnx::Reshape_484', 'onnx::Reshape_522'])
if ret != 0:print('Load yolov5 failed!')exit(ret)
print('done')
采用Netron
打开的onnx
文件,如下:
疑问:为什么不用最后合并后的输出结果?
因为,最后的形状不固定导致的,有可能5个框,有可能10个框
。输出模型到固定大小,后续操作放到后处理,目的是为了加快模型的npu上
的推理速度(这里是我的理解,不一定正确,欢迎补充)
在
PyTorch
中,神经网络的输出形状通常是根据输入形状来自动计算的,而在ONNX
中,输出形状需要在转换时进行显式指定,这是由于ONNX
的静态图执行模型与PyTorch
的动态图执行模型不同所致。
当你将PyTorch
模型转换为ONNX
模型时,你需要为ONNX
模型中的每个输出定义固定的形状,以便在模型执行时为其分配正确的内存空间。如果输出形状不固定,那么ONNX
运行时就需要在运行时动态调整输出形状,这将使得模型在部署时的性能受到影响。
因此,在转换PyTorch
模型为ONNX
模型时,你需要手动指定每个输出的固定形状,以便在执行时能够顺利运行。
Yolo v5
的输出格式一般为a × b × c × 85
的形式,其中:
a*b*c
表示框的数目85
则涵盖框的位置信息(xc,yc,w,h)
、前景的置信度Pc
和80
个类别的预测条件概率c1,...,c80。(4+1+80
,无背景类)
如果是你自己的模型,可能是只有3个目标类别,那么最后就是4+1+3=8,这个值记得在onnx
模型中查看到。
二、需要注意事项
2.1、 设定anchor
值
anchor
的设定,在训练yolo v5
模型时候,是可以设定自动适应,采用聚类的方式,通过标注的目标框的大小,给出anchor
的值。在train.py
中,noaotoanchor
的默认为False
,如果设定为True
,则会使用默认的anchor
设定。
所以,如果经过autoanchor
,给出了新的anchor
设定,那么在推理和转完rknn
后的设定,都需要与之相匹配的anchor
,这个很重要。
为什么官方和很多博客,都没有注意到这个问题呢?因为大多数情况下,aotoanchor
并没有发挥作用。都是使用了默认的,导致很多人即便没有注意到这个问题,最后的结果也不差。
但是,如果是不一样的,结果就会比较差,这个值就需要对应的做修改了。
2.1.1、训练阶段记录
如果在训练阶段,你已经关注到autoAnchor
的输出结果,可以在这里直接进行记录,在terminal
打印的内容,大致如下:
AutoAnchor: 3.60 anchors/target, 0.974 Best Possible Recall (BPR). Anchors are a poor fit to dataset ⚠, attempting to improve...
AutoAnchor: WARNING ⚠ Extremely small objects found: 764 of 27545 labels are <3 pixels in size
AutoAnchor: Running kmeans for 9 anchors on 27522 points...
AutoAnchor: Evolving anchors with Genetic Algorithm: fitness = 0.8052: 100%|██████████| 1000/1000 00:10
AutoAnchor: thr=0.25: 0.9996 best possible recall, 5.11 anchors past thr
AutoAnchor: n=9, img_size=640, metric_all=0.358/0.805-mean/best, past_thr=0.532-mean: 5,5, 7,8, 11,11, 17,17, 28,28, 41,37, 56,56, 79,82, 143,140
2.1.2、pt文件查询记录
查询autoAnchor
记录到.pt
文件内的anchor
设定,如下:
import torch
import sys
sys.path.append("path/yolov5-master")
weights = 'best.pt'
model = torch.load(str(weights[0] if isinstance(weights, list) else weights), map_location='cpu')
model1 = model['ema' if model.get('ema') else 'model']
model2 = model1.float().fuse().model.state_dict()for k,v in model2.items():if 'anchor' in k:# print(k)# print(v)print(v.numpy().flatten().tolist())
打印结果:
Fusing layers...
[0.54345703125, 0.58251953125, 0.8525390625, 0.88818359375, 1.353515625, 1.318359375, 1.0859375, 1.0380859375, 1.75390625, 1.705078125, 2.38671875, 2.462890625, 1.7421875, 1.6787109375, 2.578125, 2.458984375, 3.904296875, 3.75]
[4.34765625, 4.66015625, 6.8203125, 7.10546875, 10.828125, 10.546875, 17.375, 16.609375, 28.0625, 27.28125, 38.1875, 39.40625, 55.75, 53.71875, 82.5, 78.6875, 124.9375, 120.0]
YOLOv5m summary: 308 layers, 21037791 parameters, 0 gradients
第二行是真的,需要取整。第一行…
经过我的发现,如果你打印的anchor
就一行,那么可能是默认的anchor
(默认使用COCO
数据集的anchor
),就是good fit to dataset
,也就是默认的:
[[10, 13], [16, 30], [33, 23],
[30, 61], [62, 45],[59, 119],
[116, 90], [156, 198], [373, 326]]
2.2、rk3588推理性能
yolo v5m
量化前性能:
推理性能:Performance
Total Time(us): 194162
FPS: 5.15占用内存:Memory Profile Info Dump NPU model memory detail(bytes):Total Weight Memory: 39.83 MiBTotal Internal Tensor Memory: 19.50 MiBTotal Memory: 59.33 MiB
量化后性能
推理性能:Performance
Total Time(us): 137508
FPS: 7.27占用内存:Memory Profile Info Dump
NPU model memory detail(bytes):Total Weight Memory: 20.03 MiBTotal Internal Tensor Memory: 8.75 MiBTotal Memory: 28.78 MiB
总的来说:
- 模型时间效率上,量化后能降低
30%
,194ms
到137ms
; - 占用内存上,量化后减少
50%
,59Mib
到29Mib
;
三、C/C++ API部署
-
目标检测 YOLOv5 - 基于 瑞芯微 Rockchip RKNN C API 实现 ----------- github代码
-
yolov8 瑞芯微 RKNN 的 C++部署------------- github代码
上述两个参考链接,基本囊括了一下几个部分:
rknn
模型转换Python rknn
推理c/c++ rknn
推理(YOLO v5
部分是瑞芯微官方开放的代码)
如果你也是参考瑞芯微官方的C API
代码,那么替换上你的模型后,有几个地方需要修改:
- 输入图像大小要改
anchor
尺寸要改
const int anchor0[6] = {4, 5, 7, 7, 11, 11};
const int anchor1[6] = {17, 17, 28, 27, 38, 39};
const int anchor2[6] = {56, 54, 83, 79, 125, 120};
- 前景
box
阈值修改
const float box_conf_threswin = 0.25;
nms
阈值修改
const float nms_threswin = 0.1;
- 类别置信度重新调整
objProbs.push_back(current_prob*box_confidence);
- 针对各个类,采用不同的阈值(待补充,这部分瑞芯微未采用这种二次过滤方式)
尤其是anchor
这里,如果设定的不对,那么输出的结果就会非常的奇怪。如果是对的,那么差异性相对会小很多(和本地pt
测试结果对比)。
四、总结
本文是对YOLO V5
模型部署到瑞芯微板子上遇到的问题汇总。当然可能还会存在其他的更多问题,但是暂时还没有遇到,所以后面如果还会遇到什么问题,还会补充到这里。
如果你也正在做这块,并且遇到了问题,可以评论交流。目前还发现就是转模型后的评估问题,这个后面也会按照官方教程进行测试,这是下一篇的预告,期待。
相关文章:

【RK3588】YOLO V5在瑞芯微板子上部署问题记录汇总
YOLO V5训练模型部署到瑞芯微的板子上面,官方是有给出案例和转过详情的。并且也提供了Python版本的推理代码,以及C语言的代码。 但是,对于转换过程中的细节,哪些需要改?怎么改?如何改,和为什么…...
别人做的百度百科词条信息不全,如何更正自己的百度百科词条
很多人自己的百度百科词条是别人上传上去的,自己压根不知道,而且里面的信息内容要么不全,要么是有错漏的,但自己想要更正自己的百度百科词条又不知道如何更正,下面洛希爱做百科网和大家介绍一些百科经验知识。 首先百…...

[论文精读]U-Net: Convolutional Networks for BiomedicalImage Segmentation
论文原文:U-Net: Convolutional Networks for Biomedical Image Segmentation (arxiv.org) 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔…...

Godot Identifier “File“ not declared in the current scope.
解决方案: f FileAccess.open(savedir, FileAccess.READ)...
Java ORM Bee,多表关联更新
Bee V2.1.8 增加支持多表的update, insert, delete; 使用FK注解进行关联. 如果子实体没有用上FK声明的字段(即FK的字段没有值),则不执行,防止更新到多余记录 外键有一个没有设置时,跳过。 更多实例,请查看样例工程:https://gitee.com/automvc/bee-exam 或:h…...
Java 读取excel文件
导入: 先导入依赖: <!-- 文件上传 --> <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpmime</artifactId><version>4.5.7</version> </dependency> <!-- JSON -…...
PageRank(上):数据分析 | 数据挖掘 | 十大算法之一
⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据开发、数据分析等。 🐴欢迎小伙伴们点赞👍🏻、收藏⭐️、…...

吃鸡达人专享!提高战斗力,分享干货,查询装备皮肤,保护账号安全!
大家好!作为专业吃鸡行家,我将为您带来一些热门话题和实用内容,帮助您提升游戏战斗力,分享顶级游戏作战干货,并提供便捷的作图工具和查询服务。让我们一起享受吃鸡的乐趣! 首先,我要推荐一款绝地…...

力扣第101题 c++ 递归 迭代 双方法 +注释 ~
题目 101. 对称二叉树 简单 给你一个二叉树的根节点 root , 检查它是否轴对称。 示例 1: 输入:root [1,2,2,3,4,4,3] 输出:true示例 2: 输入:root [1,2,2,null,3,null,3] 输出:false提示&a…...

Go:实现SMTP邮件发送订阅功能(包含163邮箱、163企业邮箱、谷歌gmail邮箱)
需求很简单,就是用户输入自己的邮箱后,使用官方邮箱给用户发送替邮件模版 目录 前置邮件模版邮箱开启SMTP服务163邮箱163企业邮箱谷歌gmail邮箱腾讯企业邮箱-失败其他邮箱-未操作 邮件发送核心代码config.yaml配置读取邮件相关配置发送邮件 附录 前置 邮…...

Scala第十六章节
Scala第十六章节 scala总目录 文档资料下载 章节目标 掌握泛型方法, 类, 特质的用法了解泛型上下界相关内容了解协变, 逆变, 非变的用法掌握列表去重排序案例 1. 泛型 泛型的意思是泛指某种具体的数据类型, 在Scala中, 泛型用[数据类型]表示. 在实际开发中, 泛型一般是结合…...
C语言 实现 链 显示 效果 查找 修改 删除
显示所有信息 2023年10月1日的描述:今天放假 2023年10月2日的描述:今天有体育 2023年10月3日的描述:今天有数学 2023年10月4日的描述:今天有语文 2023年10月5日的描述:今天有政治 2023年10月6日的描述:今天交学费 2023年10月7日的描述:今天周末 2023年10月8日的描述:今天给家里…...
CSS基础语法第一天
目录 一、CSS 简介 1.1 CSS简介 1.2 CSS语法 1.3 CSS 语法规范 1.4 CSS 代码风格 1.4.1 样式格式书写 1.4.2 样式大小写 1.4.3 空格规范 二、CSS 基础选择器 2.1选择器分类 2.2标签选择器 2.3 类选择器 2.4 id选择器 2.5 通配符选择器 三、盒子尺寸和背景色 …...

Leetcode 1492.n的第k个因子
给你两个正整数 n 和 k 。 如果正整数 i 满足 n % i 0 ,那么我们就说正整数 i 是整数 n 的因子。 考虑整数 n 的所有因子,将它们 升序排列 。请你返回第 k 个因子。如果 n 的因子数少于 k ,请你返回 -1 。 示例 1: 输入&#…...

十一工具箱流量主小程序源码
无授权,去过滤机制版本 看到网上发布的都是要授权的 朋友叫我把他去授权,能用就行 就把过滤去了 这样就不用授权 可以免费使用 白嫖党专属 一切接口可用,无需担心不能用 授权者不关站一直可以用 源码下载:https://download.csdn.…...

10.5汇编语言整理
【汇编语言相关语法】 1.汇编语言的组成部分 1.伪操作:不参与程序的执行,但是用于告诉编译器程序该怎么编译 .text .global .end .if .else .endif .data 2.汇编指令 编译器将一条汇编指令编译成一条机器码,在内存里一条指令占4字节内存&…...

Connect to 127.0.0.1:1080 [/127.0.0.1] failed: Connection refused: connect
报错信息 A problem occurred configuring root project CourseSelection. > Could not resolve all artifacts for configuration :classpath.> Could not resolve com.android.tools.build:gradle:3.6.1.Required by:project :> Could not resolve com.android.tool…...

驱动器类产品的接口EMC拓扑方案
驱动器类产品的接口EMC拓扑方案 1. 概述 本文以高压伺服驱动器和变频器类产品为例,对常用端口滤波拓扑方案进行总结,后续根据不同的应用场景可进行适当删减,希望对大家有帮助。 2. 驱动器验证等级 本文推荐拓扑的实验结果,满足…...

2023最新ICP备案查询系统源码 附教程 Thinkphp框架
2023最新ICP备案查询系统源码 附教程 thinkphp框架 本系统支持网址备案,小程序备案,APP备案查询,快应用备案查询 优势: 响应速度快,没有延迟,没有缓存,数据与官方同步 源码下载:ht…...

大数据Doris(六):编译 Doris遇到的问题
文章目录 编译 Doris遇到的问题 一、js_generator.cc:(.text+0xfc3c): undefined reference to `well_known_types_js’...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...

DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...