keras-yolo部署 - 权重转换(h5 ->tflite) (2.0版)

本来我tensorflow1.13转换tflite还能转换的,但是后面我们对模型改造了一下,代码突然就抽风了,直接说当前版本不支持’流‘(Switch、Merge…)等等问题,我顿时懵了。后面看了GitHub大佬们的交流,发现如果想用tensorflow1.0版本去转换也不是不行,就是很麻烦,对于我这种懒人来说肯定是对这种麻烦事表示抗拒的(其实改的时候还容易报出一连串未知错误,浪费时间),最终,我索性创了个tensorflow2.0版本的环境,专门用来转换模型。

环境如下:
python 3.6.2
tensorflow-cpu 2.2.0
opencv-python 4.2.0.34

完整的模型转换代码已上传至GitHub:https://github.com/DeepVegChicken/Learning-Yolo_Deployment

由于我之前的代码是keras2.2.4 和 tensorflow1.13写的,而tensorflow2.2.0本身自带keras,所以我们需要对包的导入做一定修改,如:

之前我是这样导包的:
from keras.models import *
from keras.layers import *
现在:
from tensorflow.keras.models import *
from tensorflow.keras.layers import *

最终,2.0版本的转换代码如下(我们可以不需要将.h5先转成pd格式,再转成tflite了),直接将h5转成tflite(由于我保存的是训练好的权值文件,因此,我需要创建出一个空的网络,然后再让创建的网络去读取对应的权值,以此来完整的加载到一个模型):

import os
import cv2
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import *
from tensorflow.keras.layers import *

“”“ 
这一部分是网络的代码,就不放上来了。或者你也可以从其他文件中读网络 
对了,再提醒一下,由于我们需要将转换好的tflite放到单片机上跑,这里面就涉及到了单片机支不支持这个模块的问题。
就比如对于上采样问题,我这个就是不支持上采样UpSampling2D的,但是居然支持转置卷积Conv2DTranspose(万万没想到,草率了)
”“”

# 用来产生一些数据,用于量化操作
# 如果你只要float32型,不需要量化成Int8型,那么你就不需要这一步的操作
class Generator(object):
    def __init__(self):
    	# 图片数据保存的的所在目录
        self.image_dir = 'DataSet/11/'
        self.input_size = [128, 128]
        # [self.image_dir + 图片的名字, ... , ] -> 用于读取图片
        self.imgSet = [os.path.join(self.image_dir, f) for f in os.listdir(
            self.image_dir) if os.path.isfile(os.path.join(self.image_dir, f))]

    def generate(self):
        for img_path in self.imgSet:
        	# 这里面的操作根据你测试模型的操作一样就行
        	# 假设你测试的时候不需要 /255.0, 那就不要进行这一步的操作即可
            orig_image = cv2.imread(img_path)
            rgb_image = cv2.cvtColor(orig_image, cv2.COLOR_BGR2RGB)
            image_tensor = cv2.resize(rgb_image, dsize=tuple(self.input_size))
            image_tensor = np.asarray(image_tensor / 255.0, dtype=np.float32)
            image_tensor = image_tensor[np.newaxis, :]
            yield [image_tensor]


h5Input_path = 'DataSet/Weights/TrainedWeights_Tiger.h5'
tfliteOutput_path = 'DataSet/Weights/TrainedWeights_Tiger.tflite'

h5Model = YOLONet(Input(shape=(128, 128, 3)), 3, 1)
h5Model.load_weights(h5Input_path)

converter = tf.lite.TFLiteConverter.from_keras_model(h5Model)

converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]
converter.representative_dataset = Generator().generate
converter.target_spec.supported_types = [tf.int8]

tfliteModel = converter.convert()
open(tfliteOutput_path, "wb").write(tfliteModel)
print("successfully convert to tflite done")

——————————————————————————————————————
2022.2.23 - 全量化成int8

# Data iterator
class Generator(object):
    def __init__(self):
        self.image_dir = 'DataSet/11/'
        self.input_size = [128, 128]
        self.imgSet = [os.path.join(self.image_dir, f) for f in os.listdir(
            self.image_dir) if os.path.isfile(os.path.join(self.image_dir, f))]

    def generate(self):
        for img_path in self.imgSet:
            # Assuming you don't need (/255.0 or other) when testing, skip these steps
            orig_image = cv2.imread(img_path)
            rgb_image = cv2.cvtColor(orig_image, cv2.COLOR_BGR2RGB)
            image_tensor = cv2.resize(rgb_image, dsize=tuple(self.input_size))
            image_tensor = np.asarray(image_tensor / 255.0, dtype=np.float32)
            image_tensor = image_tensor[np.newaxis, :]
            yield [image_tensor]


h5Input_path = 'DataSet/Weights/TrainedWeights_Tiger.h5'
tfliteOutput_path = 'DataSet/Weights/TrainedWeights_Tiger.tflite'

h5Model = YOLONet(Input(shape=(128, 128, 3)), 3, 1)
h5Model.load_weights(h5Input_path)

# quantitative...
converter = tf.lite.TFLiteConverter.from_keras_model(h5Model)
converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]
converter.representative_dataset = Generator().generate

converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.experimental_new_converter = True

# converter.target_spec.supported_types = [tf.int8]
converter.inference_input_type = tf.int8
converter.inference_output_type = tf.int8

# convert
tfliteModel = converter.convert()

# save converted tflite file
open(tfliteOutput_path, "wb").write(tfliteModel)
print("successfully convert to tflite done")

你可能感兴趣的:(目标检测,keras,tensorflow,python)