|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| """Exports trained model to TensorFlow frozen graph."""
|
|
|
| import os
|
| import tensorflow as tf
|
|
|
| from tensorflow.contrib import quantize as contrib_quantize
|
| from tensorflow.python.tools import freeze_graph
|
| from deeplab import common
|
| from deeplab import input_preprocess
|
| from deeplab import model
|
|
|
| slim = tf.contrib.slim
|
| flags = tf.app.flags
|
|
|
| FLAGS = flags.FLAGS
|
|
|
| flags.DEFINE_string('checkpoint_path', None, 'Checkpoint path')
|
|
|
| flags.DEFINE_string('export_path', None,
|
| 'Path to output Tensorflow frozen graph.')
|
|
|
| flags.DEFINE_integer('num_classes', 21, 'Number of classes.')
|
|
|
| flags.DEFINE_multi_integer('crop_size', [513, 513],
|
| 'Crop size [height, width].')
|
|
|
|
|
|
|
|
|
| flags.DEFINE_multi_integer('atrous_rates', None,
|
| 'Atrous rates for atrous spatial pyramid pooling.')
|
|
|
| flags.DEFINE_integer('output_stride', 8,
|
| 'The ratio of input to output spatial resolution.')
|
|
|
|
|
| flags.DEFINE_multi_float('inference_scales', [1.0],
|
| 'The scales to resize images for inference.')
|
|
|
| flags.DEFINE_bool('add_flipped_images', False,
|
| 'Add flipped images during inference or not.')
|
|
|
| flags.DEFINE_integer(
|
| 'quantize_delay_step', -1,
|
| 'Steps to start quantized training. If < 0, will not quantize model.')
|
|
|
| flags.DEFINE_bool('save_inference_graph', False,
|
| 'Save inference graph in text proto.')
|
|
|
|
|
| _INPUT_NAME = 'ImageTensor'
|
|
|
|
|
| _OUTPUT_NAME = 'SemanticPredictions'
|
| _RAW_OUTPUT_NAME = 'RawSemanticPredictions'
|
|
|
|
|
| _OUTPUT_PROB_NAME = 'SemanticProbabilities'
|
| _RAW_OUTPUT_PROB_NAME = 'RawSemanticProbabilities'
|
|
|
|
|
| def _create_input_tensors():
|
| """Creates and prepares input tensors for DeepLab model.
|
|
|
| This method creates a 4-D uint8 image tensor 'ImageTensor' with shape
|
| [1, None, None, 3]. The actual input tensor name to use during inference is
|
| 'ImageTensor:0'.
|
|
|
| Returns:
|
| image: Preprocessed 4-D float32 tensor with shape [1, crop_height,
|
| crop_width, 3].
|
| original_image_size: Original image shape tensor [height, width].
|
| resized_image_size: Resized image shape tensor [height, width].
|
| """
|
|
|
| input_image = tf.placeholder(tf.uint8, [1, None, None, 3], name=_INPUT_NAME)
|
| original_image_size = tf.shape(input_image)[1:3]
|
|
|
|
|
|
|
| image = tf.squeeze(input_image, axis=0)
|
| resized_image, image, _ = input_preprocess.preprocess_image_and_label(
|
| image,
|
| label=None,
|
| crop_height=FLAGS.crop_size[0],
|
| crop_width=FLAGS.crop_size[1],
|
| min_resize_value=FLAGS.min_resize_value,
|
| max_resize_value=FLAGS.max_resize_value,
|
| resize_factor=FLAGS.resize_factor,
|
| is_training=False,
|
| model_variant=FLAGS.model_variant)
|
| resized_image_size = tf.shape(resized_image)[:2]
|
|
|
|
|
|
|
| image = tf.expand_dims(image, 0)
|
|
|
| return image, original_image_size, resized_image_size
|
|
|
|
|
| def main(unused_argv):
|
| tf.logging.set_verbosity(tf.logging.INFO)
|
| tf.logging.info('Prepare to export model to: %s', FLAGS.export_path)
|
|
|
| with tf.Graph().as_default():
|
| image, image_size, resized_image_size = _create_input_tensors()
|
|
|
| model_options = common.ModelOptions(
|
| outputs_to_num_classes={common.OUTPUT_TYPE: FLAGS.num_classes},
|
| crop_size=FLAGS.crop_size,
|
| atrous_rates=FLAGS.atrous_rates,
|
| output_stride=FLAGS.output_stride)
|
|
|
| if tuple(FLAGS.inference_scales) == (1.0,):
|
| tf.logging.info('Exported model performs single-scale inference.')
|
| predictions = model.predict_labels(
|
| image,
|
| model_options=model_options,
|
| image_pyramid=FLAGS.image_pyramid)
|
| else:
|
| tf.logging.info('Exported model performs multi-scale inference.')
|
| if FLAGS.quantize_delay_step >= 0:
|
| raise ValueError(
|
| 'Quantize mode is not supported with multi-scale test.')
|
| predictions = model.predict_labels_multi_scale(
|
| image,
|
| model_options=model_options,
|
| eval_scales=FLAGS.inference_scales,
|
| add_flipped_images=FLAGS.add_flipped_images)
|
| raw_predictions = tf.identity(
|
| tf.cast(predictions[common.OUTPUT_TYPE], tf.float32),
|
| _RAW_OUTPUT_NAME)
|
| raw_probabilities = tf.identity(
|
| predictions[common.OUTPUT_TYPE + model.PROB_SUFFIX],
|
| _RAW_OUTPUT_PROB_NAME)
|
|
|
|
|
| semantic_predictions = raw_predictions[
|
| :, :resized_image_size[0], :resized_image_size[1]]
|
| semantic_probabilities = raw_probabilities[
|
| :, :resized_image_size[0], :resized_image_size[1]]
|
|
|
|
|
| def _resize_label(label, label_size):
|
|
|
| label = tf.expand_dims(label, 3)
|
| resized_label = tf.image.resize_images(
|
| label,
|
| label_size,
|
| method=tf.image.ResizeMethod.NEAREST_NEIGHBOR,
|
| align_corners=True)
|
| return tf.cast(tf.squeeze(resized_label, 3), tf.int32)
|
| semantic_predictions = _resize_label(semantic_predictions, image_size)
|
| semantic_predictions = tf.identity(semantic_predictions, name=_OUTPUT_NAME)
|
|
|
| semantic_probabilities = tf.image.resize_bilinear(
|
| semantic_probabilities, image_size, align_corners=True,
|
| name=_OUTPUT_PROB_NAME)
|
|
|
| if FLAGS.quantize_delay_step >= 0:
|
| contrib_quantize.create_eval_graph()
|
|
|
| saver = tf.train.Saver(tf.all_variables())
|
|
|
| dirname = os.path.dirname(FLAGS.export_path)
|
| tf.gfile.MakeDirs(dirname)
|
| graph_def = tf.get_default_graph().as_graph_def(add_shapes=True)
|
| freeze_graph.freeze_graph_with_def_protos(
|
| graph_def,
|
| saver.as_saver_def(),
|
| FLAGS.checkpoint_path,
|
| _OUTPUT_NAME + ',' + _OUTPUT_PROB_NAME,
|
| restore_op_name=None,
|
| filename_tensor_name=None,
|
| output_graph=FLAGS.export_path,
|
| clear_devices=True,
|
| initializer_nodes=None)
|
|
|
| if FLAGS.save_inference_graph:
|
| tf.train.write_graph(graph_def, dirname, 'inference_graph.pbtxt')
|
|
|
|
|
| if __name__ == '__main__':
|
| flags.mark_flag_as_required('checkpoint_path')
|
| flags.mark_flag_as_required('export_path')
|
| tf.app.run()
|
|
|