当前位置:   article > 正文

Hi3516(海思)训练yolov5-6.0-->转oonx-->转caffe-转.wk文件_yolov5 海思3516

yolov5 海思3516

1 训练

1 更改模型结构,将Upsample变成ConvTranspose2d,

  1. # YOLOv5 v6.0 head
  2. head:
  3. [[-1, 1, Conv, [512, 1, 1]],
  4. # [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  5. [-1, -1, nn.ConvTranspose2d,[256, 256, 2, 2]],
  6. [[-1, 6], 1, Concat, [1]], # cat backbone P4
  7. [-1, 3, C3, [512, False]], # 13
  8. [-1, 1, Conv, [256, 1, 1]],
  9. # [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  10. [-1, -1, nn.ConvTranspose2d,[128, 128, 2, 2]],
  11. [[-1, 4], 1, Concat, [1]], # cat backbone P3
  12. [-1, 3, C3, [256, False]], # 17 (P3/8-small)

二. 导出模型

1. 导出onnx模型:
(1) 在export中opset改为9
(2) 在models/yolo.py中修改detect中代码如下:

  1. # 为海思3561dv300更改 train use 官方
  2. class Detect(nn.Module):
  3. stride = None # strides computed during build
  4. onnx_dynamic = False # ONNX export parameter
  5. def __init__(self, nc=80, anchors=(), ch=(), inplace=True): # detection layer
  6. super().__init__()
  7. self.nc = nc # number of classes
  8. self.no = nc + 5 # number of outputs per anchor
  9. self.nl = len(anchors) # number of detection layers
  10. self.na = len(anchors[0]) // 2 # number of anchors
  11. self.grid = [torch.zeros(1)] * self.nl # init grid
  12. self.anchor_grid = [torch.zeros(1)] * self.nl # init anchor grid
  13. self.register_buffer('anchors', torch.tensor(anchors).float().view(self.nl, -1, 2)) # shape(nl,na,2)
  14. self.m = nn.ModuleList(nn.Conv2d(x, self.no * self.na, 1) for x in ch) # output conv
  15. self.inplace = inplace # use in-place ops (e.g. slice assignment)
  16. def forward(self, x):
  17. # print_feature=2
  18. z = [] # inference output
  19. for i in range(self.nl):
  20. x[i] = self.m[i](x[i]) # conv
  21. bs, _, ny, nx = x[i].shape # x(bs,255,20,20) to x(bs,3,20,20,85)
  22. # x[i] = self.m[i](x[i]) # **增加这行代码**
  23. # x[i] = x[i].view(bs, self.na, self.no, ny, nx).permute(0, 1, 3, 4, 2).contiguous()
  24. x[i] = x[i].view(bs, self.na, self.no, ny*nx)
  25. if not self.training: # inference
  26. if self.grid[i].shape[2:4] != x[i].shape[2:4] or self.onnx_dynamic:
  27. self.grid[i], self.anchor_grid[i] = self._make_grid(nx, ny, i)
  28. # y = x[i].sigmoid()
  29. y = x[i]
  30. # if self.inplace:
  31. # y[..., 0:2] = (y[..., 0:2] * 2. - 0.5 + self.grid[i]) * self.stride[i] # xy
  32. # y[..., 2:4] = (y[..., 2:4] * 2) ** 2 * self.anchor_grid[i] # wh
  33. # else: # for YOLOv5 on AWS Inferentia https://github.com/ultralytics/yolov5/pull/2953
  34. # xy = (y[..., 0:2] * 2. - 0.5 + self.grid[i]) * self.stride[i] # xy
  35. # wh = (y[..., 2:4] * 2) ** 2 * self.anchor_grid[i] # wh
  36. # y = torch.cat((xy, wh, y[..., 4:]), -1)
  37. # z.append(y.view(bs, -1, self.no))
  38. z.append(y)
  39. return z
  40. # return x if self.training else (torch.cat(z, 1), x)
  41. def _make_grid(self, nx=20, ny=20, i=0):
  42. d = self.anchors[i].device
  43. yv, xv = torch.meshgrid([torch.arange(ny).to(d), torch.arange(nx).to(d)])
  44. grid = torch.stack((xv, yv), 2).expand((1, self.na, ny, nx, 2)).float()
  45. anchor_grid = (self.anchors[i].clone() * self.stride[i]) \
  46. .view((1, self.na, 1, 1, 2)).expand((1, self.na, ny, nx, 2)).float()
  47. return grid, anchor_grid
  48. # 官方原先的DETAECT
  49. class Detect1(nn.Module):
  50. stride = None # strides computed during build
  51. onnx_dynamic = False # ONNX export parameter
  52. def __init__(self, nc=80, anchors=(), ch=(), inplace=True): # detection layer
  53. super().__init__()
  54. self.nc = nc # number of classes
  55. self.no = nc + 5 # number of outputs per anchor
  56. self.nl = len(anchors) # number of detection layers
  57. self.na = len(anchors[0]) // 2 # number of anchors
  58. self.grid = [torch.zeros(1)] * self.nl # init grid
  59. self.anchor_grid = [torch.zeros(1)] * self.nl # init anchor grid
  60. self.register_buffer('anchors', torch.tensor(anchors).float().view(self.nl, -1, 2)) # shape(nl,na,2)
  61. self.m = nn.ModuleList(nn.Conv2d(x, self.no * self.na, 1) for x in ch) # output conv
  62. self.inplace = inplace # use in-place ops (e.g. slice assignment)
  63. def forward(self, x):
  64. z = [] # inference output
  65. for i in range(self.nl):
  66. x[i] = self.m[i](x[i]) # conv
  67. bs, _, ny, nx = x[i].shape # x(bs,255,20,20) to x(bs,3,20,20,85)
  68. x[i] = x[i].view(bs, self.na, self.no, ny, nx).permute(0, 1, 3, 4, 2).contiguous()
  69. if not self.training: # inference
  70. if self.grid[i].shape[2:4] != x[i].shape[2:4] or self.onnx_dynamic:
  71. self.grid[i], self.anchor_grid[i] = self._make_grid(nx, ny, i)
  72. y = x[i].sigmoid()
  73. if self.inplace:
  74. y[..., 0:2] = (y[..., 0:2] * 2. - 0.5 + self.grid[i]) * self.stride[i] # xy
  75. y[..., 2:4] = (y[..., 2:4] * 2) ** 2 * self.anchor_grid[i] # wh
  76. else: # for YOLOv5 on AWS Inferentia https://github.com/ultralytics/yolov5/pull/2953
  77. xy = (y[..., 0:2] * 2. - 0.5 + self.grid[i]) * self.stride[i] # xy
  78. wh = (y[..., 2:4] * 2) ** 2 * self.anchor_grid[i] # wh
  79. y = torch.cat((xy, wh, y[..., 4:]), -1)
  80. z.append(y.view(bs, -1, self.no))
  81. return x if self.training else (torch.cat(z, 1), x)
  82. def _make_grid(self, nx=20, ny=20, i=0):
  83. d = self.anchors[i].device
  84. yv, xv = torch.meshgrid([torch.arange(ny).to(d), torch.arange(nx).to(d)])
  85. grid = torch.stack((xv, yv), 2).expand((1, self.na, ny, nx, 2)).float()
  86. anchor_grid = (self.anchors[i].clone() * self.stride[i]) \
  87. .view((1, self.na, 1, 1, 2)).expand((1, self.na, ny, nx, 2)).float()
  88. return grid, anchor_grid

改动有以下几点:
1:去掉了原先的permute;
2:将view原来的输出维度(bs, na, no, ny, nx) 改为 (bs, na, no, ny * nx);
3:去除了后处理坐标点和宽高decode代码,去除cat操作

现在来分析下为什么这么改:
1:nnie不支持5个维度的permute(即transpose),且只支持0231的方式,过于局限,我们不妨删掉这一层,在后处理中按照合适的读取方式去找结果就好了。
2:nnie的reshape也只支持4维,且第一维必须是0,为了能用nnie的reshape,我们不得不把x和y共享一个维度,这导致的结果是输出结果中,x和y在同一行,我们只需按个数取值即可。
3:后处理中,对三个检测层分别处理,所以不需要concat

执行

python export.py --opset 9 --imgsz 640  640  --simplify --weights best.pt

导出onnx-sim模型

python -m onnxsim xxx.onnx xxx-sim.onnx

3 转caffe

github上搜索 yolov5_onnx2caffe 项目(https://github.com/Wulingtian/yolov5_onnx2caffe

vim convertCaffe.py

设置onnx_path(上面转换得到的onnx模型),prototxt_path(caffe的prototxt保存路径),caffemodel_path(caffe的caffemodel保存路径)

执行

python ./yolov5_onnx2caffe/convertCaffe.py

4 caffe转 wk文件

 2

 注意将.cfg文件中compile_mode = 0 改成compile_mode = 1

 说明:

image_list 字段表示测试的数据,具体如下

 

 点击运行

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/287258
推荐阅读
相关标签
  

闽ICP备14008679号