首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Tensorflow对象-API:将ssd模型转换为tflite并在python中使用它

Tensorflow对象-API:将ssd模型转换为tflite并在python中使用它
EN

Stack Overflow用户
提问于 2021-09-24 17:08:21
回答 2查看 693关注 0票数 0

我很难将给定的tensorflow模型转换为tflite模型,然后使用它。我已经发布了一个问题,其中我描述了我的问题,但没有分享我正在工作的模型,因为我是不允许的。因为我找不到这样的答案,所以我尝试转换一个公共模型(tpu)。

这里是来自对象检测api的colab教程。我只是运行整个脚本而没有更改(它是相同的模型),并下载了生成的模型(有元数据和没有元数据)。我上传了他们的这里和coco17列车数据集的一个样本图片。

我试图在python中直接使用这些模型,但是结果就像垃圾一样。

下面是我使用的代码,我遵循了这个指南。我更改了rects、分数和类的索引,因为否则结果格式不正确。

代码语言:javascript
复制
#interpreter = tf.lite.Interpreter("original_models/model.tflite")
interpreter = tf.lite.Interpreter("original_models/model_with_metadata.tflite")

interpreter.allocate_tensors()
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()

size = 640

def draw_rect(image, box):
    y_min = int(max(1, (box[0] * size)))
    x_min = int(max(1, (box[1] * size)))
    y_max = int(min(size, (box[2] * size)))
    x_max = int(min(size, (box[3] * size)))
    
    # draw a rectangle on the image
    cv2.rectangle(image, (x_min, y_min), (x_max, y_max), (255, 255, 255), 2)

file = "images/000000000034.jpg"


img = cv2.imread(file)
new_img = cv2.resize(img, (size, size))
new_img = cv2.cvtColor(new_img, cv2.COLOR_BGR2RGB)

interpreter.set_tensor(input_details[0]['index'], [new_img.astype("f")])

interpreter.invoke()
rects = interpreter.get_tensor(
    output_details[1]['index'])

scores = interpreter.get_tensor(
    output_details[0]['index'])

classes = interpreter.get_tensor(
    output_details[3]['index'])


for index, score in enumerate(scores[0]):
        draw_rect(new_img,rects[0][index])
        #print(rects[0][index])
        print("scores: ",scores[0][index])
        print("class id: ", classes[0][index])
        print("______________________________")


cv2.imshow("image", new_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

这将导致以下控制台输出

代码语言:javascript
复制
scores:  0.20041436
class id:  51.0
______________________________
scores:  0.08925027
class id:  34.0
______________________________
scores:  0.079722285
class id:  34.0
______________________________
scores:  0.06676647
class id:  71.0
______________________________
scores:  0.06626186
class id:  15.0
______________________________
scores:  0.059938848
class id:  86.0
______________________________
scores:  0.058229476
class id:  34.0
______________________________
scores:  0.053791136
class id:  37.0
______________________________
scores:  0.053478718
class id:  15.0
______________________________
scores:  0.052847564
class id:  43.0
______________________________

以及由此产生的图像

我尝试了不同的图像从口腔训练数据集,但没有得到良好的结果。我认为输出层被破坏了,或者可能缺少了一些后处理?

我还尝试使用来自官方媒体--流动文献的转换方法。

代码语言:javascript
复制
import tensorflow as tf

saved_model_dir = 'tf_models/ssd_mobilenet_v2_fpnlite_640x640_coco17_tpu-8/saved_model/'
    # Convert the model
    converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) # path to the SavedModel directory
tflite_model = converter.convert()
    
# Save the model.
with open('model.tflite', 'wb') as f:
      f.write(tflite_model)

但是当我尝试使用这个模型时,我得到了一个ValueError: Cannot set tensor: Dimension mismatch. Got 640 but expected 1 for dimension 1 of input 0.

有人知道我做错了什么吗?

更新:在Farmmakers建议之后,我尝试在最后通过简短的脚本更改模型的输入维度。以前的形状是:

代码语言:javascript
复制
[{'name': 'serving_default_input_tensor:0',
  'index': 0,
  'shape': array([1, 1, 1, 3], dtype=int32),
  'shape_signature': array([ 1, -1, -1,  3], dtype=int32),
  'dtype': numpy.uint8,
  'quantization': (0.0, 0),
  'quantization_parameters': {'scales': array([], dtype=float32),
   'zero_points': array([], dtype=int32),
   'quantized_dimension': 0},
  'sparsity_parameters': {}}]

因此,仅仅增加一维是不够的。因此我使用了interpreter.resize_tensor_input(0, [1,640,640,3])。现在,它可以通过网络传送图像。

不幸的是,我无法理解输出的意义。以下是输出细节的打印:

代码语言:javascript
复制
[{'name': 'StatefulPartitionedCall:6',
  'index': 473,
  'shape': array([    1, 51150,     4], dtype=int32),
  'shape_signature': array([    1, 51150,     4], dtype=int32),
  'dtype': numpy.float32,
  'quantization': (0.0, 0),
  'quantization_parameters': {'scales': array([], dtype=float32),
   'zero_points': array([], dtype=int32),
   'quantized_dimension': 0},
  'sparsity_parameters': {}},
 {'name': 'StatefulPartitionedCall:0',
  'index': 2233,
  'shape': array([1, 1], dtype=int32),
  'shape_signature': array([ 1, -1], dtype=int32),
  'dtype': numpy.float32,
  'quantization': (0.0, 0),
  'quantization_parameters': {'scales': array([], dtype=float32),
   'zero_points': array([], dtype=int32),
   'quantized_dimension': 0},
  'sparsity_parameters': {}},
 {'name': 'StatefulPartitionedCall:5',
  'index': 2198,
  'shape': array([1], dtype=int32),
  'shape_signature': array([1], dtype=int32),
  'dtype': numpy.float32,
  'quantization': (0.0, 0),
  'quantization_parameters': {'scales': array([], dtype=float32),
   'zero_points': array([], dtype=int32),
   'quantized_dimension': 0},
  'sparsity_parameters': {}},
 {'name': 'StatefulPartitionedCall:7',
  'index': 493,
  'shape': array([    1, 51150,    91], dtype=int32),
  'shape_signature': array([    1, 51150,    91], dtype=int32),
  'dtype': numpy.float32,
  'quantization': (0.0, 0),
  'quantization_parameters': {'scales': array([], dtype=float32),
   'zero_points': array([], dtype=int32),
   'quantized_dimension': 0},
  'sparsity_parameters': {}},
 {'name': 'StatefulPartitionedCall:1',
  'index': 2286,
  'shape': array([1, 1, 1], dtype=int32),
  'shape_signature': array([ 1, -1, -1], dtype=int32),
  'dtype': numpy.float32,
  'quantization': (0.0, 0),
  'quantization_parameters': {'scales': array([], dtype=float32),
   'zero_points': array([], dtype=int32),
   'quantized_dimension': 0},
  'sparsity_parameters': {}},
 {'name': 'StatefulPartitionedCall:2',
  'index': 2268,
  'shape': array([1, 1], dtype=int32),
  'shape_signature': array([ 1, -1], dtype=int32),
  'dtype': numpy.float32,
  'quantization': (0.0, 0),
  'quantization_parameters': {'scales': array([], dtype=float32),
   'zero_points': array([], dtype=int32),
   'quantized_dimension': 0},
  'sparsity_parameters': {}},
 {'name': 'StatefulPartitionedCall:4',
  'index': 2215,
  'shape': array([1, 1], dtype=int32),
  'shape_signature': array([ 1, -1], dtype=int32),
  'dtype': numpy.float32,
  'quantization': (0.0, 0),
  'quantization_parameters': {'scales': array([], dtype=float32),
   'zero_points': array([], dtype=int32),
   'quantized_dimension': 0},
  'sparsity_parameters': {}},
 {'name': 'StatefulPartitionedCall:3',
  'index': 2251,
  'shape': array([1, 1, 1], dtype=int32),
  'shape_signature': array([ 1, -1, -1], dtype=int32),
  'dtype': numpy.float32,
  'quantization': (0.0, 0),
  'quantization_parameters': {'scales': array([], dtype=float32),
   'zero_points': array([], dtype=int32),
   'quantized_dimension': 0},
  'sparsity_parameters': {}}]  

我将so生成的tflite模型添加到谷歌驱动器中。

Update2: --我在谷歌驱动器中添加了一个目录,其中包含一个笔记本,它使用全尺寸模型并生成正确的输出。如果您执行整个笔记本,它应该产生以下图像到您的磁盘。

EN

回答 2

Stack Overflow用户

发布于 2021-09-27 11:54:36

为了使来自对象检测API的模型与TFLite很好地工作,您必须将其转换为具有自定义op的TFLite友好的图形。

tf2.md

(TF1文档)

您也可以尝试使用TensorFlow Lite模型制造者

票数 1
EN

Stack Overflow用户

发布于 2021-09-29 21:43:00

我遵循了您所显示的精确过程(丹索尔流医生中提到的标准过程)。

首先,与正式文档中描述的不同,tflite模型返回的输出具有不同的格式(不同的索引)。

代码语言:javascript
复制
  boxes = get_output_tensor(interpreter, 1)
  classes = get_output_tensor(interpreter, 3)
  scores = get_output_tensor(interpreter, 0)
  count = int(get_output_tensor(interpreter, 2))

第二,调整后的包围框的数量总是10,我不知道如何将其更改为数据集中的自定义对象数。

最后,我解决这个问题的方法是使用索引1检索边框,然后用分数过滤掉它们。然而,我得到的结果与原来的模型相去甚远,而且,tflite模型比原始模型花费更多的时间,这与tflite的意义相反。可能是因为我在笔记本电脑上运行它,因此x86指令集(tflite优化为在ARM CPU上运行(移动,raspberry pi))。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69318826

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档