当前位置:   article > 正文

YOLOv5 Android(完结)_yolov5s_relu.onnx

yolov5s_relu.onnx

最近在搞移动端的模型部署包括coreML IOS端的部署,tf-Lite Android端的部署。但是自己并不是前端开发工程师,所以移动端的代码只是修修改改,主要还是如何将模型转换到对应的格式并可以运行。

这篇主要说下YOLOv5s在Android端的部署,模型是官方最新的的pytorch转ONNX,然后自己再转tf-lite,中间需要自己去修改NMS相关部分的代码,遇到一堆坑。

效果录像

流程概述

  1. Step 1:用pytorch训练YoloV5s模型,并生成pt模型文件。
  2. Step 2:将pt模型加载并利用pytorch torch.jit.trace功能生成jit模型。
  3. Step 3:将jit模型转换(torch.onnx.export)到onnx模型。
  4. Step 4:利用onnx-tf脚本将onnx导出到tensorflow支持的savedModel模型。
  5. Step 5:tensorflow加载savedModel模型并编写后处理算法并添加到模型尾部然后保存为savedModel模型。
  6. Step 6:利用tensorflow-lite将 savedModel模型转换为tflite模型。
  7. Step 7:手机端tflite模型部署。

 

Step 1:用pytorch训练YoloV5s模型,并生成pt模型文件。

       工程链接:https://github.com/ultralytics/yolov5

       具体看readme教程

Step 2:将pt模型加载并利用pytorch torch.jit.trace功能生成jit模型。

        这一步主要是转onnx时确保pytorch模型不要有onnx不支持的算子,如果只是卷积操作基本问题不大,但是还是会有奇奇怪怪的问题需要去克服。

Step 3:将jit模型转换(torch.onnx.export)到onnx模型。

这一步主要就是几行代码问题,就用export.py 即可. 需要注意的是

model.model[-1].export = False 这里要改成 False 否则无法导出,主要还是版本问题,tf新版本有些是可以,但是会导致一个AddV2算子无法支持新版本只有tf2.1.1支持。但是tf2.1.1版本也会有其他问题需要改比如NMSV3不支持需要改成V4.以及算法中不要用类似省略号去张量的操作[…,:,:,3],tf-lite会报错,直接用:,:,:代替。还有tf-lite不支持超过4d维度的张量操作。需要修改yolo.py文件模型代码如下。实际上这里就是模型输出后NMS前导工作。

  1. def forward(self, x):
  2.         # x = x.copy()  # for profiling
  3.         z = []  # inference output
  4.         self.training |= self.export
  5.         for i in range(self.nl):
  6.             x[i] = self.m[i](x[i])  # conv
  7.             bs, _, ny, nx = x[i].shape  # x(bs,255,20,20) to x(bs,3,20,20,85)
  8.             if not self.training:  # inference
  9.                 x[i] = x[i].view(bs, self.na, self.no, ny, nx).permute(0, 1, 3, 4, 2).contiguous()
  10.                 if self.grid[i].shape[2:4] != x[i].shape[2:4]:
  11.                     self.grid[i] = self._make_grid(nx, ny).to(x[i].device)
  12.                 y = x[i].sigmoid()
  13.                 y[..., 0:2] = (y[..., 0:2] * 2. - 0.5 + self.grid[i].to(x[i].device)) * self.stride[i]  # xy
  14.                 y[..., 2:4] = (y[..., 2:4] * 2) ** 2 * self.anchor_grid[i]  # wh
  15.                 z.append(y.view(bs, -1, self.no))
  16.         return x if self.training else (torch.cat(z, 1), x)

 

Step 4:利用onnx-tf脚本将onnx导出到tensorflow支持的savedModel模型。

这个倒是很简单一行命令:onnx模型地址, 导出savedmodel位置

onnx-tf convert -i ./models/5.onnx -o ./model_new

注:如果你用的老版本onnx-tf 导出模型可能是冻结模型pb,我觉得还是用savedmodel最好,冻结模型pb已经用的少了。

Step 5:tensorflow加载savedModel模型并编写NMS算法并添加到模型尾部然后保存为savedModel模型。

这一块主要是先导入savedModel利用TF的tf.function()添加可追踪对象在,主要是添加两部分代码:

  1. 图片预处理代码
  2. def preprocess(image):
  3.         image = image[:, :, ::-1]
  4.         image = tf.transpose(image, (2, 0, 1))
  5.         image = tf.cast(image, tf.float32)/255.0
  6.         image = tf.expand_dims(image, axis=0)
  7.         return image
  8. NMS算法的前后代码
  9. def mynms(inp):
  10.         stride = [8., 16., 32.]
  11.         anchor_grid = [[[[[10., 13.]]],
  12.                         [[[16., 30.]]],
  13.                         [[[33., 23.]]]],
  14.                        [[[[30., 61.]]],
  15.                         [[[62., 45.]]],
  16.                         [[[59., 119.]]]],
  17.                        [[[[116., 90.]]],
  18.                         [[[156., 198.]]],
  19.                         [[[373., 326.]]]]]
  20.         z = []
  21.         for i, one in enumerate(inp):
  22.             layer_ = one
  23.             ny, nx = layer_.shape[-2:]
  24.             layer_ = tf.transpose(tf.reshape(layer_, [3, 85, ny, nx]), [0, 2, 3, 1])
  25.             yv, xv = tf.meshgrid(tf.range(0, ny), tf.range(0, nx), indexing='ij')
  26.             l_meshgrid = tf.cast(tf.reshape(tf.stack([xv, yv], 2), [1, ny, nx, 2]), tf.float32)
  27.             layer_ = tf.sigmoid(layer_)
  28.             cxcy = (layer_[:, :, :, 0:2] * 2. - 0.5 + l_meshgrid) * stride[i]
  29.             wh = (layer_[:, :, :, 2:4] * 2) ** 2 * anchor_grid[i]
  30.             layer_ = tf.concat([cxcy, wh, layer_[:, :, :, 4:]], axis=-1)
  31.             layer_ = tf.reshape(layer_, [-1, 85])
  32.             z.append(layer_)
  33.         layers_out = tf.concat(z, axis=0)
  34.         layers_out = tf.expand_dims(layers_out, 0)
  35.         boxes = layers_out[0, :, :4]
  36.         # cx, cy, w, h to x0 y0 x1 y1
  37.         x0 = boxes[:, 0] - boxes[:, 2] / 2
  38.         y0 = boxes[:, 1] - boxes[:, 3] / 2
  39.         x1 = boxes[:, 0] + boxes[:, 2] / 2
  40.         y1 = boxes[:, 1] + boxes[:, 3] / 2
  41.         boxes = tf.stack((x0, y0, x1, y1), 1)
  42.         conf = layers_out[0, :, 4]
  43.         classes = layers_out[0, :, 5:]
  44.         selected_indices, _ = tf.image.non_max_suppression_with_scores(boxes, conf, 30, 0.3)
  45.         boxes = tf.gather(boxes, selected_indices, name="boxes")
  46.         conf = tf.gather(conf, selected_indices, name="conf")
  47.         classes = tf.gather(classes, selected_indices, name="classes")
  48.         return boxes, conf, classes

Step 6:利用tensorflow-lite将 savedModel模型转换为tflite模型。

这里需要注意就是GPU可能会显示不够需要内存自增长设置。

  1. import tensorflow as tf
  2. import numpy as np
  3. import predict_
  4. gpus = tf.config.experimental.list_physical_devices(device_type='GPU')
  5. for gpu in gpus:
  6.     tf.config.experimental.set_memory_growth(gpu, True)
  7. # input_arrays = ["input"]
  8. # output_arrays = ["boxes", 'conf', 'classes']
  9. # converter = tf.lite.TFLiteConverter.from_saved_model("/media/george/DATASETS1/pycharm_workspace/yolov5/tf2.1.1")
  10. converter = tf.lite.TFLiteConverter.from_saved_model("/media/george/DATASETS1/pycharm_workspace/ai_learning/onnx/pb_yolov5_meshgrid_nms")
  11. converter.target_spec.supported_ops = [
  12. tf.lite.OpsSet.TFLITE_BUILTINS, # enable TensorFlow Lite ops.
  13. ]
  14. converter.allow_custom_ops = True
  15. converter.experimental_new_converter = True
  16. # converter.optimizations = [tf.lite.Optimize.DEFAULT]
  17. # converter.target_spec.supported_types = [tf.float16]
  18. # converter.post_training_quantize = True
  19. tflite_model = converter.convert()
  20. open("y5s.tflite", "wb").write(tflite_model)

Step 7:手机端tflite模型部署。

利用Android studio 加载tensorflow官方Android detection代码

https://github.com/tensorflow/examples/tree/master/lite/examples/object_detection/android

修改的地方也比较多,具体要看自己的模型流程是怎么样的,主要还是模型输入尺寸和输出参数是什么,修改对应的java代码即可。

如果哪里有说错或者有不清楚的可以留言.

 

 

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

闽ICP备14008679号