Convert Custom Tensorflow 2 SSD mobilenet model to Tensorflow Lite Flatbuffer

Viewed 1100

I am trying to convert my custom trained SSD mobilenet TF2 Object Detection model to .tflite format (flatbuffer), it will be used with Raspberry pi, I've followed the official tensorflow tutorials of converting my model to tflite model:

Note: I've used Colab with Tensorflow 2.5-gpu for training and Tensorflow 2.7-nightly for conversion (some Github issues related to SSD to tflite model conversion were mentioned to use nightly version)

1- I started by trying to export tflite graph using export_tflite_ssd_graph.py with these args:

!python object_detection/export_tflite_ssd_graph.py \
--pipeline_config_path models/myssd_mobile/pipeline.config \
--trained_checkpoint_prefix models/myssd_mobile/ckpt-9.index \
--output_directory exported_models/tflite_model

but it showed the following error:

RuntimeError: tf.placeholder() is not compatible with eager execution.

even after I disabled it by adding tf.disable_eager_execution() it showed the following error:

NameError: name 'graph_matcher' is not defined

so I realized that it might be not created for tf2 so I converted the model with export_tflite_graph_tf2.py using the code below, and I got the savedmodel:

!python object_detection/export_tflite_graph_tf2.py \
--pipeline_config_path models/myssd_mobile/pipeline.config \
--trained_checkpoint_dir models/myssd_mobile \
--output_directory exported_models/tflite_model

2- I converted the tflite savedmodel to .tflite model using the code below which is taken from tensorflow docs:

import tensorflow as tf

converter = tf.lite.TFLiteConverter.from_saved_model('exported_models/tflite_model/saved_model')
converter.target_spec.supported_ops = [
  tf.lite.OpsSet.TFLITE_BUILTINS, # enable TensorFlow Lite ops.
  tf.lite.OpsSet.SELECT_TF_OPS # enable TensorFlow ops.
]
tflite_model = converter.convert()
open("converted_model.tflite", "wb").write(tflite_model)

After that I've created tflite labels.txt manually and here it is:

t1
t2
t3
t4
t5
t6
t7
t8
t9
t10
t11

then I ran the following script:

TFLite_detection_image.py

but it shows this error:

Traceback (most recent call last):
  File "TFLite_detection_image.py", line 157, in <module>
    for i in range(len(scores)):
TypeError: object of type 'numpy.float32' has no len()

where is the wrong?

Thanks in advance

2 Answers

I had the same problem on both SSD MobileNet v2 320x320 and SSD MobileNet V2 FPNLite 640x640. So I figured out that it should not be related to the model itself. This morning I just fixed this error by generating once again all needed files : Your split of data into train/test (and val) ; the ones for Tensorflow like train.record, test.record ... Also I checked the labelmap I used to ensure that it has all my classes.

After this pretreatment, I exported my model using export_tflite_graph_tf2.py and then my TF Lite converter that is the following :

import tensorflow as tf
import argparse
# Define model and output directory arguments
parser = argparse.ArgumentParser()
parser.add_argument('--model', help='Folder that the saved model is located in',
                    default='exported-models/my_tflite_model/saved_model')
parser.add_argument('--output', help='Folder that the tflite model will be written to',
                    default='exported-models/my_tflite_model')
args = parser.parse_args()

converter = tf.lite.TFLiteConverter.from_saved_model(args.model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.experimental_new_converter = True
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS, tf.lite.OpsSet.SELECT_TF_OPS]

tflite_model = converter.convert()

output = args.output + '/model.tflite'
with tf.io.gfile.GFile(output, 'wb') as f:
  f.write(tflite_model)

Note : When I used TF Lite Nighty, I also had the error so I just used this script with TF2.

After that, I can confirm that both models are working on Raspberry Pi 4B+ with the same precision/recall scores I got on GPU.

I had the same error of you TypeError: object of type 'numpy.float32' has no len(), and the solution was to change the indexings of scores, boxes and classes in the python code because that means scores is a scaller value not an array. Please refere to this answer.

BTW, this error happened when I used tflite-runtime on Jetson Nano, but when I ran the code on TF2.5 on Raspberry PI it ran without chaning anything.

Related