Unverified Commit 9bbf8015 authored by pkulzc's avatar pkulzc Committed by GitHub
Browse files

Merged commit includes the following changes: (#6932)

250447559  by Zhichao Lu:

    Update expected files format for Instance Segmentation challenge:
    - add fields ImageWidth, ImageHeight and store the values per prediction
    - as mask, store only encoded image and assume its size is ImageWidth x ImageHeight

--
250402780  by rathodv:

    Fix failing Mask R-CNN TPU convergence test.

    Cast second stage prediction tensors from bfloat16 to float32 to prevent errors in third target assignment (Mask Prediction) - Concat with different types bfloat16 and bfloat32 isn't allowed.

--
250300240  by Zhichao Lu:

    Addion Open Images Challenge 2019 object detection and instance segmentation
    support into Estimator framework.

--
249944839  by rathodv:

    Modify exporter.py to add multiclass score nodes in exported inference graphs.

--
249935201  by rathodv:

    Modify postprocess methods to preserve multiclass scores after non max suppression.

--
249878079  by Zhich...
parent f42fddee
...@@ -22,6 +22,20 @@ message BatchNonMaxSuppression { ...@@ -22,6 +22,20 @@ message BatchNonMaxSuppression {
// Whether to use the implementation of NMS that guarantees static shapes. // Whether to use the implementation of NMS that guarantees static shapes.
optional bool use_static_shapes = 6 [default = false]; optional bool use_static_shapes = 6 [default = false];
// Whether to use class agnostic NMS.
// Class-agnostic NMS function implements a class-agnostic version
// of Non Maximal Suppression where if max_classes_per_detection=k,
// 1) we keep the top-k scores for each detection and
// 2) during NMS, each detection only uses the highest class score for sorting.
// 3) Compared to regular NMS, the worst runtime of this version is O(N^2)
// instead of O(KN^2) where N is the number of detections and K the number of
// classes.
optional bool use_class_agnostic_nms = 7 [default = false];
// Number of classes retained per detection in class agnostic NMS.
optional int32 max_classes_per_detection = 8 [default = 1];
} }
// Configuration proto for post-processing predicted boxes and // Configuration proto for post-processing predicted boxes and
......
...@@ -87,7 +87,7 @@ def get_prediction_tensor_shapes(pipeline_config): ...@@ -87,7 +87,7 @@ def get_prediction_tensor_shapes(pipeline_config):
_, input_tensors = exporter.input_placeholder_fn_map['image_tensor']() _, input_tensors = exporter.input_placeholder_fn_map['image_tensor']()
inputs = tf.to_float(input_tensors) inputs = tf.cast(input_tensors, dtype=tf.float32)
preprocessed_inputs, true_image_shapes = detection_model.preprocess(inputs) preprocessed_inputs, true_image_shapes = detection_model.preprocess(inputs)
prediction_dict = detection_model.predict(preprocessed_inputs, prediction_dict = detection_model.predict(preprocessed_inputs,
...@@ -125,7 +125,7 @@ def build_graph(pipeline_config, ...@@ -125,7 +125,7 @@ def build_graph(pipeline_config,
exporter.input_placeholder_fn_map[input_type]() exporter.input_placeholder_fn_map[input_type]()
# CPU pre-processing # CPU pre-processing
inputs = tf.to_float(input_tensors) inputs = tf.cast(input_tensors, dtype=tf.float32)
preprocessed_inputs, true_image_shapes = detection_model.preprocess(inputs) preprocessed_inputs, true_image_shapes = detection_model.preprocess(inputs)
# Dimshuffle: [b, h, w, c] -> [b, c, h, w] # Dimshuffle: [b, h, w, c] -> [b, c, h, w]
......
...@@ -57,7 +57,7 @@ def get_prediction_tensor_shapes(pipeline_config): ...@@ -57,7 +57,7 @@ def get_prediction_tensor_shapes(pipeline_config):
detection_model = model_builder.build( detection_model = model_builder.build(
pipeline_config.model, is_training=False) pipeline_config.model, is_training=False)
_, input_tensors = exporter.input_placeholder_fn_map['image_tensor']() _, input_tensors = exporter.input_placeholder_fn_map['image_tensor']()
inputs = tf.to_float(input_tensors) inputs = tf.cast(input_tensors, dtype=tf.float32)
preprocessed_inputs, true_image_shapes = detection_model.preprocess(inputs) preprocessed_inputs, true_image_shapes = detection_model.preprocess(inputs)
prediction_dict = detection_model.predict(preprocessed_inputs, prediction_dict = detection_model.predict(preprocessed_inputs,
true_image_shapes) true_image_shapes)
...@@ -138,7 +138,7 @@ def build_graph(pipeline_config, ...@@ -138,7 +138,7 @@ def build_graph(pipeline_config,
placeholder_tensor, input_tensors = \ placeholder_tensor, input_tensors = \
exporter.input_placeholder_fn_map[input_type]() exporter.input_placeholder_fn_map[input_type]()
inputs = tf.to_float(input_tensors) inputs = tf.cast(input_tensors, dtype=tf.float32)
preprocessed_inputs, true_image_shapes = detection_model.preprocess(inputs) preprocessed_inputs, true_image_shapes = detection_model.preprocess(inputs)
# Dimshuffle: (b, h, w, c) -> (b, c, h, w) # Dimshuffle: (b, h, w, c) -> (b, c, h, w)
......
This diff is collapsed.
This diff is collapsed.
...@@ -333,5 +333,79 @@ class AssertShapeEqualTest(tf.test.TestCase): ...@@ -333,5 +333,79 @@ class AssertShapeEqualTest(tf.test.TestCase):
tensor_b: np.zeros([5])}) tensor_b: np.zeros([5])})
class FlattenExpandDimensionTest(tf.test.TestCase):
def test_flatten_given_dims(self):
inputs = tf.random_uniform([5, 2, 10, 10, 3])
actual_flattened = shape_utils.flatten_dimensions(inputs, first=1, last=3)
expected_flattened = tf.reshape(inputs, [5, 20, 10, 3])
with self.test_session() as sess:
(actual_flattened_np,
expected_flattened_np) = sess.run([actual_flattened, expected_flattened])
self.assertAllClose(expected_flattened_np, actual_flattened_np)
def test_raises_value_error_incorrect_dimensions(self):
inputs = tf.random_uniform([5, 2, 10, 10, 3])
with self.assertRaises(ValueError):
shape_utils.flatten_dimensions(inputs, first=0, last=6)
def test_flatten_first_two_dimensions(self):
inputs = tf.constant(
[
[[1, 2], [3, 4]],
[[5, 6], [7, 8]],
[[9, 10], [11, 12]]
], dtype=tf.int32)
flattened_tensor = shape_utils.flatten_first_n_dimensions(
inputs, 2)
with self.test_session() as sess:
flattened_tensor_out = sess.run(flattened_tensor)
expected_output = [[1, 2],
[3, 4],
[5, 6],
[7, 8],
[9, 10],
[11, 12]]
self.assertAllEqual(expected_output, flattened_tensor_out)
def test_expand_first_dimension(self):
inputs = tf.constant(
[
[1, 2],
[3, 4],
[5, 6],
[7, 8],
[9, 10],
[11, 12]
], dtype=tf.int32)
dims = [3, 2]
expanded_tensor = shape_utils.expand_first_dimension(
inputs, dims)
with self.test_session() as sess:
expanded_tensor_out = sess.run(expanded_tensor)
expected_output = [
[[1, 2], [3, 4]],
[[5, 6], [7, 8]],
[[9, 10], [11, 12]]]
self.assertAllEqual(expected_output, expanded_tensor_out)
def test_expand_first_dimension_with_incompatible_dims(self):
inputs_default = tf.constant(
[
[[1, 2]],
[[3, 4]],
[[5, 6]],
], dtype=tf.int32)
inputs = tf.placeholder_with_default(inputs_default, [None, 1, 2])
dims = [3, 2]
expanded_tensor = shape_utils.expand_first_dimension(
inputs, dims)
with self.test_session() as sess:
with self.assertRaises(tf.errors.InvalidArgumentError):
sess.run(expanded_tensor)
if __name__ == '__main__': if __name__ == '__main__':
tf.test.main() tf.test.main()
This diff is collapsed.
This diff is collapsed.
...@@ -1005,6 +1005,10 @@ class EvalMetricOpsVisualization(object): ...@@ -1005,6 +1005,10 @@ class EvalMetricOpsVisualization(object):
lambda: tf.summary.image(summary_name, image), lambda: tf.summary.image(summary_name, image),
lambda: tf.constant('')) lambda: tf.constant(''))
if tf.executing_eagerly():
update_op = self.add_images([[images[0]]])
image_tensors = get_images()
else:
update_op = tf.py_func(self.add_images, [[images[0]]], []) update_op = tf.py_func(self.add_images, [[images[0]]], [])
image_tensors = tf.py_func( image_tensors = tf.py_func(
get_images, [], [tf.uint8] * self._max_examples_to_draw) get_images, [], [tf.uint8] * self._max_examples_to_draw)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment