YOLOv4 Darknet模型转成Tflite模型然后进行Android设备端部署
文章目录
前言
最近在搞一些边端部署相关的内容,需要在安卓的设备上面运行YOLOv4的模型,由于本人不会Java和Android的开发,所以就找了一个开源的项目进行实践。但是开源的项目中使用的是YOLOv5s的模型,所以需要进行一些改动。
1. 安卓apk项目的开源
我们是找到了安卓项目的开源地址,如下:
https://github.com/lp6m/yolov5s_android
把项目克隆下来,琢磨了好久,才知道需要用Android Studio软件打开app/tflite_yolov5_test文件夹,才能进行编译与apk的输出,原模型以及相关apk的代码是针对pytorch版本的YOLOv5s进行转换和部署的。因为移动端部署是需要tensorflow的tflite模型,所以原文是通过以下的多重转换步骤得到最终的模型:
pytorch(pt模型)—— onnx模型 —— OpenVino模型 —— tensorflow tflite模型 —— int8量化(如果需要)
至于具体的转换步骤,我们这里就不展开说了,大家可以看看convert_model/README.md
文件就可以明白,虽然是有点绕,但是实测是可以完成转换的。
我们转换出来的模型精度有fp32(文件名model_float32.tflite),大小和原来pytorch的模型是一样的,还有int8(model_quantized.tflite),通过模型量化得到的,大小只有原来模型的1/4。其实还有一个fp16,也是通过模型量化得到的,大小为原来模型1/2。
1.1 uint8模型的量化
这里有必要讲一下,模型int8的量化,我们把convert_model/quantize.py
的代码贴上来。
import argparse
import sys
import os
import numpy as np
import tensorflow as tf
import tensorflow_datasets as tfds
def quantize_model(INPUT_SIZE, pb_path, output_path, calib_num, tfds_root, download_flag):
raw_test_data = tfds.load(name='coco/2017',
with_info=False,
split='validation',
data_dir=tfds_root,
download=True)
input_shapes = [(3, INPUT_SIZE, INPUT_SIZE)]
def representative_dataset_gen():
for i, data in enumerate(raw_test_data.take(calib_num)):
print('calibrating...', i)
image = data['image'].numpy()
images = []
for shape in input_shapes:
data = tf.image.resize(image, (shape[1], shape[2]))
tmp_image = data / 255.
tmp_image = tmp_image[np.newaxis,:,:,:]
images.append(tmp_image)
yield images
input_arrays = ['inputs']
output_arrays = ['Identity', 'Identity_1', 'Identity_2']
print(pb_path, input_arrays, output_arrays)
quit()
converter = tf.compat.v1.lite.TFLiteConverter.from_frozen_graph(pb_path, input_arrays, output_arrays)
converter.experimental_new_quantizer = False
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.allow_custom_ops = False
converter.inference_input_type = tf.uint8
# To commonalize postprocess, output_type is float32
converter.inference_output_type = tf.float32
converter.representative_dataset = representative_dataset_gen
tflite_model = converter.convert()
with open(output_path, 'wb') as w:
w.write(tflite_model)
print('Quantization Completed!', output_path)
if __name__