YOLOv3_TensorFlow icon indicating copy to clipboard operation
YOLOv3_TensorFlow copied to clipboard

about freeze graph and convert TFlite problem

Open PanJinquan opened this issue 5 years ago • 20 comments

Hi, thank you so much for sharing your code! I have some questions and hope you could help me.I try to freeze graph and convert *.pb to TFlite model, so that can transport to Android mobile phones.This is my source code as follow:

But,I get a unsupported operation error as shown below:

b'2019-01-29 16:12:22.550452: I tensorflow/contrib/lite/toco/import_tensorflow.cc:1080] Converting unsupported operation: ResizeNearestNeighbor\n

Yes, about TFlite unsupported operation error,Could you help how to modify the yolov3 source code to support operation?

PanJinquan avatar Jan 29 '19 08:01 PanJinquan

This is my source code as follow: `

--coding: utf-8 --

""" @Project: tensorflow-yolov3 @File : freeze.py @Author : panjq @E-mail : [email protected] @Date : 2019-01-22 18:39:28 """

import os import time import numpy as np import tensorflow as tf import cv2 from utils.nms_utils import gpu_nms from utils.misc_utils import parse_anchors, read_class_names import tensorflow.contrib.lite as lite from utils.plot_utils import get_color_table, plot_one_box from model import yolov3

def show_image(img_ori,boxes_,scores_,classes,num_class,labels_,width_ori,height_ori,new_size): # rescale the coordinates to the original image color_table = get_color_table(num_class) boxes_[:, 0] *= (width_ori / float(new_size[0])) boxes_[:, 2] *= (width_ori / float(new_size[0])) boxes_[:, 1] *= (height_ori / float(new_size[1])) boxes_[:, 3] *= (height_ori / float(new_size[1]))

print("box coords:")
print(boxes_)
print('*' * 30)
print("scores:")
print(scores_)
print('*' * 30)
print("labels:")
print(labels_)

for i in range(len(boxes_)):
    x0, y0, x1, y1 = boxes_[i]
    scores=scores_[i]
    plot_one_box(img_ori, [x0, y0, x1, y1], label=classes[labels_[i]]+':'+str(scores)[:6], color=color_table[labels_[i]])
cv2.imshow('Detection result', img_ori)
# cv2.imwrite('detection_result.jpg', img_ori)
cv2.waitKey(30)

def read_pb_return_tensors(pb_file, return_elements): with tf.gfile.FastGFile(pb_file, 'rb') as f: frozen_graph_def = tf.GraphDef() frozen_graph_def.ParseFromString(f.read()) return_elements = tf.import_graph_def(frozen_graph_def, return_elements=return_elements) input_tensor, output_tensors = return_elements[0], return_elements[1:] return input_tensor, output_tensors

def freeze(sess, output_file, output_node_names):

output_graph_def = tf.graph_util.convert_variables_to_constants(
    sess,
    sess.graph.as_graph_def(),
    output_node_names,
)

with tf.gfile.GFile(output_file, "wb") as f:
    f.write(output_graph_def.SerializeToString())

print("=> {} ops written to {}.".format(len(output_graph_def.node), output_file))

def freeze_graph(): # input_checkpoint = 'checkpoint/yolov3.ckpt-99' # cpu_pb_path='checkpoint/yolov3.pb' ckpt_path = "./data/darknet_weights/yolov3.ckpt" pb_path= "./data/darknet_weights/yolov3.pb" # 指定输出的节点名称,该节点名称必须是原模型中存在的节点 output_node_names = ["yolov3/yolov3_head/feature_map_1", "yolov3/yolov3_head/feature_map_2", 'yolov3/yolov3_head/feature_map_3'] saver = tf.train.import_meta_graph(ckpt_path + '.meta', clear_devices=True) with tf.Session() as sess: saver.restore(sess, ckpt_path) # 恢复图并得到数据 for op in sess.graph.get_operations(): print(op.name, op.values()) freeze(sess, pb_path, output_node_names)

def get_feature_map(input_image,pb_path): # 定义一个计算图graph,获得feature_map input_node_names = ["Placeholder:0"] output_node_names = ["yolov3/yolov3_head/feature_map_1:0", "yolov3/yolov3_head/feature_map_2:0", 'yolov3/yolov3_head/feature_map_3:0'] graph=tf.Graph() with graph.as_default(): input_tensor, output_tensors = read_pb_return_tensors(pb_path,input_node_names+output_node_names) with tf.Session(graph=graph) as sess: feature_map= sess.run(output_tensors, feed_dict={input_tensor: input_image}) return feature_map

def pb_test_tf(img_ori,feature_map,classes,num_class,anchors,score_threshold,iou_threshold): ''' :param img_ori: :param feature_map: :param classes: :param num_class: :param anchors: :param score_threshold: :param iou_threshold: :return: ''' height_ori, width_ori = img_ori.shape[:2] img_size = [416, 416] # 定义一个计算图graph,获得输出结果: graph = tf.Graph() with graph.as_default(): feature_map_1, feature_map_2, feature_map_3 = feature_map feature_map_1 = tf.constant(feature_map_1, dtype=tf.float32) feature_map_2 = tf.constant(feature_map_2, dtype=tf.float32) feature_map_3 = tf.constant(feature_map_3, dtype=tf.float32) tf_img_size = tf.constant(value=img_size, dtype=tf.int32) print("img_size:{}".format(img_size))

    # model = yolov3FeatureMap.tf_yolov3FeatureMap(num_classes=num_classes, anchors=anchors)
    yolo_model = yolov3(num_class, anchors)

with tf.Session(graph=graph) as sess:
    pred_boxes, pred_confs, pred_probs = yolo_model.predict2(feature_map_1, feature_map_2, feature_map_3,tf_img_size)
    pred_scores = pred_confs * pred_probs

    boxes, scores, labels = gpu_nms(pred_boxes, pred_scores, num_class, max_boxes=30, score_thresh=score_threshold,
                                    iou_thresh=iou_threshold)

    # saver = tf.train.Saver()
    # saver.restore(sess, ckpt_path)

    boxes_, scores_, labels_ = sess.run([boxes, scores, labels])

    show_image(img_ori, boxes_, scores_, classes, num_class, labels_, width_ori, height_ori,
                          img_size)

def freeze_graph_test(): image_path = './data/demo_data/dog.jpg' anchor_path = "./data/yolo_anchors.txt" input_size = [416, 416] class_name_path = "./data/coco.names" pb_path= "./data/darknet_weights/yolov3.pb" score_threshold = 0.5 iou_threshold = 0.5

anchors = parse_anchors(anchor_path)
classes = read_class_names(class_name_path)
num_class = len(classes)

# 读取图像数据
img_ori = cv2.imread(image_path)
img_resized = cv2.resize(img_ori, tuple(input_size))
img_resized = cv2.cvtColor(img_resized, cv2.COLOR_BGR2RGB)
img_resized = np.asarray(img_resized, np.float32)
img_resized = img_resized[np.newaxis, :] / 255.

feature_map = get_feature_map(img_resized, pb_path)
pb_test_tf(img_ori, feature_map, classes, num_class, anchors, score_threshold, iou_threshold)

def convert_tflite(): pb_path= "./data/darknet_weights/yolov3.pb" out_tflite ='./data/darknet_weights/converted_model.tflite' SIZE=416 input_arrays = ['Placeholder'] output_node_names = ["yolov3/yolov3_head/feature_map_1", "yolov3/yolov3_head/feature_map_2", 'yolov3/yolov3_head/feature_map_3'] input_shapes = {"Placeholder": [1, SIZE, SIZE, 3]} converter = lite.TFLiteConverter.from_frozen_graph( pb_path, input_arrays, output_node_names, input_shapes) tflite_model = converter.convert() open(out_tflite, "wb").write(tflite_model)

if name == 'main': freeze_graph() print("freeze_graph done...") freeze_graph_test() print("freeze_graph_test done...") convert_tflite() print("convert_tflite done...")

`

PanJinquan avatar Jan 29 '19 08:01 PanJinquan

Hi, I guess in your TFlite version, ResizeNearestNeighbor of tf.image module has not been supported. According to this Link, you can try newer tflite version. Or you may change this line to other resize functions in tf.image module, please refer to link and have a try.

wizyoung avatar Feb 19 '19 07:02 wizyoung

@PanJinquan Can you please send code for freeze graph. The indentations are not proper above. And were you successful in converting the model to tflite? Please help. I am currently struggling to export model to tflite.

BytesBrewer avatar May 12 '19 15:05 BytesBrewer

How do get the input node as Placeholder:0? I use that code to freeze the model but when I test it I got the error ValueError: Requested return tensor 'Placeholder:0' not found in graph def, thanks!

yuanzhedong avatar Jul 26 '19 03:07 yuanzhedong

@yuanzhedong Hi, you can refer to my answer in stackoverflow https://stackoverflow.com/a/49768479/6631854 to get the correct placeholder name.

wizyoung avatar Jul 26 '19 03:07 wizyoung

@wizyoung Thanks for the help!

After running your example I do find Placeholder in the graph, the shape is 1, -1, -1:

name: "phase_train"
op: "Placeholder"
attr {
  key: "dtype"
  value {
    type: DT_BOOL
  }
}
attr {
  key: "shape"
  value {
    shape {
      unknown_rank: true
    }
  }
}
name: "iterator_handle_flag"
op: "Placeholder"
attr {
  key: "dtype"
  value {
    type: DT_STRING
  }
}
attr {
  key: "shape"
  value {
    shape {
    }
  }
}
name: "Placeholder"
op: "Placeholder"
attr {
  key: "dtype"
  value {
    type: DT_FLOAT
  }
}
attr {
  key: "shape"
  value {
    shape {
      dim {
        size: 1
      }
      dim {
        size: -1
      }
      dim {
        size: -1
      }
    }
  }
}

Here're all the placehoders:

[<tf.Operation 'phase_train' type=Placeholder>, <tf.Operation 'iterator_handle_flag' type=Placeholder>, <tf.Operation 'Placeholder' type=Placeholder>, <tf.Operation 'Placeholder_1' type=Placeholder>, <tf.Operation 'phase_train_1' type=Placeholder>, <tf.Operation 'iterator_handle_flag_1' type=Placeholder>, <tf.Operation 'Placeholder_2' type=Placeholder>, <tf.Operation 'Placeholder_1_1' type=Placeholder>, <tf.Operation 'phase_train_2' type=Placeholder>, <tf.Operation 'iterator_handle_flag_2' type=Placeholder>, <tf.Operation 'Placeholder_3' type=Placeholder>, <tf.Operation 'Placeholder_1_2' type=Placeholder>]

yuanzhedong avatar Jul 26 '19 03:07 yuanzhedong

But after I freeze it I can't find the placeholder from the pb file:

code:

import tensorflow as tf
gf = tf.GraphDef()
gf.ParseFromString(open('./to_freeze/model.pb','rb').read())
print([n.name + '=>' +  n.op for n in gf.node if n.op in ('Placeholder')])

output:

['phase_train=>Placeholder']

yuanzhedong avatar Jul 26 '19 04:07 yuanzhedong

@yuanzhedong @wizyoung any news on this one? I am having the same error:

Merge/MergeSummary (<tf.Tensor 'Merge/MergeSummary:0' shape=() dtype=string>,) => 2243 ops written to ./. ['phase_train=>Placeholder'] freeze_graph done... WARNING:tensorflow:From freeze_graph.py:90: FastGFile.init (from tensorflow.python.platform.gfile) is deprecated and will be removed in a future version. Instructions for updating: Use tf.gfile.GFile. Traceback (most recent call last): File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/framework/importer.py", line 418, in import_graph_def graph._c_graph, serialized, options) # pylint: disable=protected-access tensorflow.python.framework.errors_impl.InvalidArgumentError: Requested return node 'Placeholder' not found in graph def

When I change freeze_graph to load the model before as in

   with tf.name_scope('input'):
       input_data = tf.placeholder(dtype=tf.float32, shape=[ 1, input_shape[0], input_shape[1], 3], name='input_data')
   model = yolov3(len(classes), anchors)
   with tf.variable_scope('yolov3'):
       feature_map = model.forward(input_data)
   sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True))
   saver = tf.train.Saver()
   saver.restore(sess, FLAGS.trained_checkpoint_prefix)

   # the op name of the Placeholder changes in different TensorFlow versions.
   # To find out the correct placeholder op name in the Graphdef part of the .meta file:
   imported_graph = tf.get_default_graph()
   graph_op = imported_graph.get_operations()
   with open(FLAGS.output_directory + 'graphdef_output.txt', 'w') as f:
       for i in graph_op:
           f.write(str(i))
   output_node_names = ["yolov3/yolov3_head/feature_map_1", "yolov3/yolov3_head/feature_map_2", 'yolov3/yolov3_head/feature_map_3']
   freeze(sess, FLAGS.output_directory, output_node_names)

my output.txt looks better, but I now get the placeholder ['input/input_data=>Placeholder']

AnikaP avatar Sep 04 '19 07:09 AnikaP

Hey everyone, I took the following steps:

  1. Change the utils/nms_utils.py lines 53-55 to:
boxes = tf.concat(boxes_list, axis=0, name='output/box_output')
score = tf.concat(score_list, axis=0, name='output/score_output')
label = tf.concat(label_list, axis=0, name='output/label_output')
  1. Freeze the graph link
  2. Test that the model works link

Hope this helps!

omarabid59 avatar Oct 11 '19 20:10 omarabid59

Hey everyone, I took the following steps:

  1. Change the utils/nms_utils.py lines 53-55 to:
boxes = tf.concat(boxes_list, axis=0, name='output/box_output')
score = tf.concat(score_list, axis=0, name='output/score_output')
label = tf.concat(label_list, axis=0, name='output/label_output')
  1. Freeze the graph link
  2. Test that the model works link

Hope this helps!

If I did not change the utils/nms_utils.py lines 53-55 at the training phase, will it work?

zpge avatar Oct 27 '19 02:10 zpge

After frozen to pb file, the model still takes over 5 Gb on GPU. Is it normal?

zpge avatar Oct 27 '19 03:10 zpge

hello,can you tell me the out_node and input nodes,I think the output nodes are:yolov3/yolov3_head/feature_map_2", 'yolov3/yolov3_head/feature_map_3 But I don't know the input nodes?Help.....

yjsdut avatar Nov 19 '19 11:11 yjsdut

https://lutzroeder.github.io/netron/ Maybe can use this to find it.

aluds123 avatar Jan 02 '20 13:01 aluds123

@wizyoung @omarabid59 @PanJinquan Can anyone guide me how to use tflite to test image or video ? (I maybe success to convert it to tflite) What should I modify in test_single_image.py?

aluds123 avatar Jan 02 '20 13:01 aluds123

请问有从rtsp流每隔n帧跑yolov3检测实时人数的脚本吗?

bujianyiwang avatar Jan 16 '20 06:01 bujianyiwang

@wizyoung @omarabid59 @PanJinquan Can anyone guide me how to use tflite to test image or video ? (I maybe success to convert it to tflite) What should I modify in test_single_image.py?

I already success. Thanks.

aluds123 avatar Feb 17 '20 08:02 aluds123

@aluds123 could you share here how you able to achieve it?

balajib363 avatar Apr 06 '20 10:04 balajib363

hello,can you tell me the out_node and input nodes,I think the output nodes are:yolov3/yolov3_head/feature_map_2", 'yolov3/yolov3_head/feature_map_3 But I don't know the input nodes?Help.....

i got the same problems,had you solved it?

Albert337 avatar May 16 '20 07:05 Albert337

Hi, @BalajiB197 This is a part of code to convert .ckpt to .pb:


frozen_graph_def = graph_util.convert_variables_to_constants( sess, sess.graph_def, ["yolov3/yolov3_head/feature_map_1","yolov3/yolov3_head/feature_map_2","yolov3/yolov3_head/feature_map_3"]) tf.train.write_graph( frozen_graph_def, os.path.dirname(output_file), os.path.basename(output_file), as_text=False) tf.logging.info('Saved frozen graph to %s',output_file)


And I use toco to convert .pb to .tflite:


toco tflite_convert --graph_def_file=abc.pb --output_file=abc.tflite --input_format=TENSORFLOW_GRAPHDEF --output_format=TFLITE --inference_type=QUANTIZED_UINT8 --input_shape="1,416, 416,3" --input_array=input_data --output_array=yolov3/yolov3_head/feature_map_1,yolov3/yolov3_head/feature_map_2,yolov3/yolov3_head/feature_map_3 --mean_values 0 --std_dev_values 255 --default_ranges_min 0 --default_ranges_max 6 (I use quantization aware training, so you should modify some parameter like "input_format", "inference_type" .......)


aluds123 avatar May 26 '20 11:05 aluds123

@PanJinquan @aluds123 I have already get pb file but I do not know how to test it. From code above, I select some code.

def freeze_graph_test():
    image_path = './data/demo_data/dog.jpg'
    anchor_path = "./data/yolo_anchors.txt"
    input_size = [416, 416]
    class_name_path = "./data/coco.names"
    pb_path= "./data/darknet_weights/yolov3.pb"
    score_threshold = 0.5
    iou_threshold = 0.5

    anchors = parse_anchors(anchor_path)
    classes = read_class_names(class_name_path)
    num_class = len(classes)

    # 读取图像数据
    img_ori = cv2.imread(image_path)
    img_resized = cv2.resize(img_ori, tuple(input_size))
    img_resized = cv2.cvtColor(img_resized, cv2.COLOR_BGR2RGB)
    img_resized = np.asarray(img_resized, np.float32)
    img_resized = img_resized[np.newaxis, :] / 255.

    feature_map = get_feature_map(img_resized, pb_path)
    pb_test_tf(img_ori, feature_map, classes, num_class, anchors, score_threshold, iou_threshold)
def pb_test_tf(img_ori,feature_map,classes,num_class,anchors,score_threshold,iou_threshold):
    '''
    :param img_ori:
    :param feature_map:
    :param classes:
    :param num_class:
    :param anchors:
    :param score_threshold:
    :param iou_threshold:
    :return:
    '''
    height_ori, width_ori = img_ori.shape[:2]
    img_size = [416, 416]
    # 定义一个计算图graph,获得输出结果:
    graph = tf.Graph()
    with graph.as_default():
        feature_map_1, feature_map_2, feature_map_3 = feature_map
        feature_map_1 = tf.constant(feature_map_1, dtype=tf.float32)
        feature_map_2 = tf.constant(feature_map_2, dtype=tf.float32)
        feature_map_3 = tf.constant(feature_map_3, dtype=tf.float32)
        tf_img_size = tf.constant(value=img_size, dtype=tf.int32)
        print("img_size:{}".format(img_size))

    # model = yolov3FeatureMap.tf_yolov3FeatureMap(num_classes=num_classes, anchors=anchors)
    yolo_model = yolov3(num_class, anchors)

    with tf.Session(graph=graph) as sess:
        pred_boxes, pred_confs, pred_probs = yolo_model.predict2(feature_map_1, feature_map_2, feature_map_3,tf_img_size)
        pred_scores = pred_confs * pred_probs

        boxes, scores, labels = gpu_nms(pred_boxes, pred_scores, num_class, max_boxes=30, score_thresh=score_threshold,
                                    iou_thresh=iou_threshold)

    # saver = tf.train.Saver()
    # saver.restore(sess, ckpt_path)

        boxes_, scores_, labels_ = sess.run([boxes, scores, labels])

        show_image(img_ori, boxes_, scores_, classes, num_class, labels_, width_ori, height_ori,
                          img_size)

def show_image(img_ori,boxes_,scores_,classes,num_class,labels_,width_ori,height_ori,new_size):
    #  rescale the coordinates to the original image
    color_table = get_color_table(num_class)
    boxes_[:, 0] *= (width_ori / float(new_size[0]))
    boxes_[:, 2] *= (width_ori / float(new_size[0]))
    boxes_[:, 1] *= (height_ori / float(new_size[1]))
    boxes_[:, 3] *= (height_ori / float(new_size[1]))

    print("box coords:")
    print(boxes_)
    print('*' * 30)
    print("scores:")
    print(scores_)
    print('*' * 30)
    print("labels:")
    print(labels_)

    for i in range(len(boxes_)):
        x0, y0, x1, y1 = boxes_[i]
        scores=scores_[i]
        plot_one_box(img_ori, [x0, y0, x1, y1], label=classes[labels_[i]]+':'+str(scores)[:6], color=color_table[labels_[i]])
    cv2.imshow('Detection result', img_ori)
    # cv2.imwrite('detection_result.jpg', img_ori)
    cv2.waitKey(30)

In function pb_test_tf()

yolo_model = yolov3(num_class, anchors)
pred_boxes, pred_confs, pred_probs = yolo_model.predict2(feature_map_1, feature_map_2, feature_map_3,tf_img_size)

It still uses yolov3 net structure, but it is known to us all that when inference with pb file, we do not need net structure. What we need are pb file, input_node_name(s) and out_put_name(s). Here is a sample code about using pb for inference. https://github.com/github2016-yuan/tensorflow-yolov3/blob/master/image_demo.py Need your help.

github2016-yuan avatar Jun 17 '20 03:06 github2016-yuan