目录
1 转换方法
将yolov5的pth模型转成rknn模型,具体方法分两步
- 利用yolov5工程中自带的export.py将pt模型转成onnx模型
- 利用如下脚本生成rknn模型
将onnx模型转化为RV1126平台的rknn模型_cumtchw-CSDN博客
这篇笔记不是为了介绍具体转换方法,而是记录一下中间转换过程中的一些问题。
2 yolov5版本问题
我们想在瑞芯微的板子用C++推理yolov5的rknn模型,目前一般是利用瑞芯微提供的C++ demo
这个demo的后处理针对的三个输出的模型,如果我们想用这个demo,那么我们使用的yolov5要用v5.0版本,不能使用v6.0版本,因为v5.0版本模型是三个输出的,v6.0版本最后是把三个输出合到一起的。
3 yolov5的输出格式问题
标准的yolov5-5.0的输出有三个,分别是
1x255x80x80
1x255x40x40
1x255x20x20
其中这里的255是85*3,这里的3是指3个anchor产生的3个box(不是RGB三个通道,最后输出那里已经没有RGB的概念了),而这里的85是指5+80=85,其中80是类别数量,每个类别数量对应一个label score,一共80个label score,而5是指box的四个坐标加一个box score.
如果是yolov5-6.0版本,6.0是把三个输出合到一起的,那么排列是x y w h box_score id Id1_score id2_score .... idn_score,那么如果3*80*80*12,则输出类别数是6不是7,因为里面有个id,相当于把id计算出来了,而yolov5-5.0版本三个输出没合到一起的,里面只有类别得分,没有类别。
4 转成rknn模型时的格式问题
这里我们以一个3标签(没带口罩,正确佩戴口罩,不正确佩戴口罩)的口罩识别模型为例,3标签的口罩识别模型输出如下,其中24是3通道*8输出,8输出是x y w h box_score Id1_score id2_score id3_score;
1*24*80*80
1*24*40*40
1*24*20*20
我之前第一次转换时,发现转出的rknn模型在瑞芯微的RV1126板子上推理的时候结果完全不对,整个图片上都是各种小框,经查找我发现是我的输出格式不是1*24*20*20,而是成了例如1*3*20*20*8这种,于是我在用export.py生成onnx模型前,把yolov5-5.0工程中的yolo.py做了如下修改,然后再用export.py生成onnx模型,然后再转成rknn模型即可。
注意修改是把permute去掉,并且view()里面是把self.na和self.no乘起来了。
或者按照如下方式修改,把self.training |= self.export注释掉,然后直接添加一个export分支:
def forward(self, x):
# x = x.copy() # for profiling
z = [] # inference output
# self.training |= self.export
if self.export:
for i in range(self.nl):
x[i] = self.m[i](x[i])
bs, _, ny, nx = x[i].shape # x(bs,48,20,20) to x(bs,3,20,20,16)
x[i] = x[i].view(bs, self.na*self.no, ny, nx).contiguous()
return x
for i in range(self.nl):
x[i] = self.m[i](x[i]) # conv
bs, _, ny, nx = x[i].shape # x(bs,255,20,20) to x(bs,3,20,20,85)
x[i] = x[i].view(bs, self.na, self.no, ny, nx).permute(0, 1, 3, 4, 2).contiguous()
.......后面代码........
经过这样修改后的输出格式如下:
netron查看onnx模型时
netron查看rknn模型时:
在RV1126板子上运行时的打印如下: