tensorflow / tensorflow/models
SSD ResNet from model zoo not working after conversion to TFLite
@tombstone is already working on this.
Since Nov 16, 2020.
- Dominant language
- Python
- Stars
- 77.7k
- Forks
- 44.8k
- PR merge metrics
- No merged PRs in 30d
Description
- I am using the latest TensorFlow Model Garden release and TensorFlow 2.
- I am reporting the issue to the correct repository. (Model Garden official or research directory)
- I checked to make sure that this issue has not already been filed.
1. The entire URL of the file you are using
2. Describe the bug
I tried to convert these unchanged models from model zoo to tflite
After conversion ResNet models returned meaningless predictions
SSD MobileNet v2 320x320 - Working
SSD MobileNet V1 FPN 640x640 - Working
SSD MobileNet V2 FPNLite 320x320 - Working
SSD MobileNet V2 FPNLite 640x640 - Working
SSD ResNet50 V1 FPN 640x640 - Not Working
SSD ResNet50 V1 FPN 1024x1024 - Not Working
3. Steps to reproduce
python ~/models/research/object_detection/export_tflite_graph_tf2.py \
--pipeline_config_path 'path/to/model/ssd_resnet50_v1_fpn_640x640_coco17_tpu-8/pipeline.config' \
--trained_checkpoint_dir 'path/to/model/ssd_resnet50_v1_fpn_640x640_coco17_tpu-8/checkpoint' \
--output_directory '/output/path'
import tensorflow as tf
saved_model_dir = 'path/to/saved/model/saved_model'
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
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()
Inference with just created tflite model:
import tensorflow as tf
import matplotlib
import matplotlib.pyplot as plt
import cv2
import time
import numpy as np
from PIL import Image
tf.__version__
MODEL_PATH = '/path/to/tflite/model/ssd_resnet50_v1_fpn_640x640.tflite'
def set_input_tensor(interpreter, image):
"""Sets the input tensor."""
tensor_index = interpreter.get_input_details()[0]['index']
input_tensor = interpreter.tensor(tensor_index)()[0]
input_tensor[:, :] = image
def get_output_tensor(interpreter, index):
"""Returns the output tensor at the given index."""
output_details = interpreter.get_output_details()[index]
tensor = np.squeeze(interpreter.get_tensor(output_details['index']))
return tensor
def detect_objects(interpreter, image, threshold):
"""Returns a list of detection results, each a dictionary of object info."""
set_input_tensor(interpreter, image)
interpreter.invoke()
# Get all output details
boxes = get_output_tensor(interpreter, 0)
classes = get_output_tensor(interpreter, 1)
scores = get_output_tensor(interpreter, 2)
count = int(get_output_tensor(interpreter, 3))
results = []
for i in range(count):
if scores[i] >= threshold:
result = {
'bounding_box': boxes[i],
'class_id': classes[i],
'score': scores[i]
}
results.append(result)
return results
interpreter = tf.lite.Interpreter(model_path=MODEL_PATH)
interpreter.allocate_tensors()
_, HEIGHT, WIDTH, _ = interpreter.get_input_details()[0]['shape']
print(f"Height and width accepted by the model: {HEIGHT, WIDTH}")
def preprocess_image(image_path):
img = tf.io.read_file(image_path)
img = tf.io.decode_image(img, channels=3)
img = tf.image.convert_image_dtype(img, tf.float32)
original_image = img
resized_img = tf.image.resize(img, (HEIGHT, WIDTH))
resized_img = resized_img[tf.newaxis, :]
return resized_img, original_image
LABEL_DICT = {
1: "person",
2: "bicycle",
3: "car",
4: "motorcycle",
5: "airplane",
6: "bus",
7: "train",
8: "truck",
9: "boat",
10: "traffic light",
11: "fire hydrant",
13: "stop sign",
14: "parking meter",
15: "bench",
16: "bird",
17: "cat",
18: "dog",
19: "horse",
20: "sheep",
21: "cow",
22: "elephant",
23: "bear",
24: "zebra",
25: "giraffe",
27: "backpack",
28: "umbrella",
31: "handbag",
32: "tie",
33: "suitcase",
34: "frisbee",
35: "skis",
36: "snowboard",
37: "sports ball",
38: "kite",
39: "baseball bat",
40: "baseball glove",
41: "skateboard",
42: "surfboard",
43: "tennis racket",
44: "bottle",
46: "wine glass",
47: "cup",
48: "fork",
49: "knife",
50: "spoon",
51: "bowl",
52: "banana",
53: "apple",
54: "sandwich",
55: "orange",
56: "broccoli",
57: "carrot",
58: "hot dog",
59: "pizza",
60: "donut",
61: "cake",
62: "chair",
63: "couch",
64: "potted plant",
65: "bed",
67: "dining table",
70: "toilet",
72: "tv",
73: "laptop",
74: "mouse",
75: "remote",
76: "keyboard",
77: "cell phone",
78: "microwave",
79: "oven",
80: "toaster",
81: "sink",
82: "refrigerator",
84: "book",
85: "clock",
86: "vase",
87: "scissors",
88: "teddy bear",
89: "hair drier",
90: "toothbrush",
91: "__background__"
}
COLORS = np.random.randint(0, 255, size=(len(LABEL_DICT), 3),
dtype="uint8")
def display_results(image_path, threshold=0.3):
# Load the input image and preprocess it
preprocessed_image, original_image = preprocess_image(image_path)
# print(preprocessed_image.shape, original_image.shape)
# =============Perform inference=====================
start_time = time.monotonic()
results = detect_objects(interpreter, preprocessed_image, threshold=threshold)
print(f"Elapsed time: {(time.monotonic() - start_time)*1000} miliseconds")
# =============Display the results====================
original_numpy = original_image.numpy()
for obj in results:
# Convert the bounding box figures from relative coordinates
# to absolute coordinates based on the original resolution
ymin, xmin, ymax, xmax = obj['bounding_box']
xmin = int(xmin * original_numpy.shape[1])
xmax = int(xmax * original_numpy.shape[1])
ymin = int(ymin * original_numpy.shape[0])
ymax = int(ymax * original_numpy.shape[0])
# Grab the class index for the current iteration
idx = int(obj['class_id']) + 1
# Skip the background
if idx >= len(LABEL_DICT):
continue
# draw the bounding box and label on the image
color = [int(c) for c in COLORS[idx]]
cv2.rectangle(original_numpy, (xmin, ymin), (xmax, ymax),
color, 2)
y = ymin - 15 if ymin - 15 > 15 else ymin + 15
label = "{}: {:.2f}%".format(LABEL_DICT[int(obj['class_id']) + 1],
obj['score'] * 100)
cv2.putText(original_numpy, label, (xmin, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
# return the final ima
original_int = (original_numpy * 255).astype(np.uint8)
return original_int
resultant_image = display_results("/path/to/example/image/apple.jpg")
Image.fromarray(resultant_image)
4. Expected behavior
I Expected SSD ResNet50 to work after converting to tflite
5. Additional context
There are some warning while running export_tflite_graph_tf2.py
6. System information
- OS Platform and Distribution: Linux Ubuntu 18.04
- TensorFlow installed from source
- TensorFlow version: v1.12.1-42078-g80dcd0fbbf 2.4.0-dev20200922
- Python version: 3.6
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.