Unverified Commit 451906e4 authored by pkulzc's avatar pkulzc Committed by GitHub
Browse files

Release MobileDet code and model, and require tf_slim installation for OD API. (#8562)



* Merged commit includes the following changes:
311933687  by Sergio Guadarrama:

    Removes spurios use of tf.compat.v2, which results in spurious tf.compat.v1.compat.v2. Adds basic test to nasnet_utils.
    Replaces all remaining import tensorflow as tf with import tensorflow.compat.v1 as tf

--
311766063  by Sergio Guadarrama:

    Removes explicit tf.compat.v1 in all call sites (we already import tf.compat.v1, so this code was  doing tf.compat.v1.compat.v1). The existing code worked in latest version of tensorflow, 2.2, (and 1.15) but not in 1.14 or in 2.0.0a, this CL fixes it.

--
311624958  by Sergio Guadarrama:

    Updates README that doesn't render properly in github documentation

--
310980959  by Sergio Guadarrama:

    Moves research_models/slim off tf.contrib.slim/layers/framework to tf_slim

--
310263156  by Sergio Guadarrama:

    Adds model breakdown for MobilenetV3

--
308640516  by Sergio Guadarrama:

    Internal change

308244396  by Sergio Guadarrama:

    GroupNormalization support for MobilenetV3.

--
307475800  by Sergio Guadarrama:

    Internal change

--
302077708  by Sergio Guadarrama:

    Remove `disable_tf2` behavior from slim py_library targets

--
301208453  by Sergio Guadarrama:

    Automated refactoring to make code Python 3 compatible.

--
300816672  by Sergio Guadarrama:

    Internal change

299433840  by Sergio Guadarrama:

    Internal change

299221609  by Sergio Guadarrama:

    Explicitly disable Tensorflow v2 behaviors for all TF1.x binaries and tests

--
299179617  by Sergio Guadarrama:

    Internal change

299040784  by Sergio Guadarrama:

    Internal change

299036699  by Sergio Guadarrama:

    Internal change

298736510  by Sergio Guadarrama:

    Internal change

298732599  by Sergio Guadarrama:

    Internal change

298729507  by Sergio Guadarrama:

    Internal change

298253328  by Sergio Guadarrama:

    Internal change

297788346  by Sergio Guadarrama:

    Internal change

297785278  by Sergio Guadarrama:

    Internal change

297783127  by Sergio Guadarrama:

    Internal change

297725870  by Sergio Guadarrama:

    Internal change

297721811  by Sergio Guadarrama:

    Internal change

297711347  by Sergio Guadarrama:

    Internal change

297708059  by Sergio Guadarrama:

    Internal change

297701831  by Sergio Guadarrama:

    Internal change

297700038  by Sergio Guadarrama:

    Internal change

297670468  by Sergio Guadarrama:

    Internal change.

--
297350326  by Sergio Guadarrama:

    Explicitly replace "import tensorflow" with "tensorflow.compat.v1" for TF2.x migration

--
297201668  by Sergio Guadarrama:

    Explicitly replace "import tensorflow" with "tensorflow.compat.v1" for TF2.x migration

--
294483372  by Sergio Guadarrama:

    Internal change

PiperOrigin-RevId: 311933687

* Merged commit includes the following changes:
312578615  by Menglong Zhu:

    Modify the LSTM feature extractors to be python 3 compatible.

--
311264357  by Menglong Zhu:

    Removes contrib.slim

--
308957207  by Menglong Zhu:

    Automated refactoring to make code Python 3 compatible.

--
306976470  by yongzhe:

    Internal change

306777559  by Menglong Zhu:

    Internal change

--
299232507  by lzyuan:

    Internal update.

--
299221735  by lzyuan:

    Add small epsilon on max_range for quantize_op to prevent range collapse.

--

PiperOrigin-RevId: 312578615

* Merged commit includes the following changes:
310447280  by lzc:

    Internal changes.

--

PiperOrigin-RevId: 310447280
Co-authored-by: default avatarSergio Guadarrama <sguada@google.com>
Co-authored-by: default avatarMenglong Zhu <menglong@google.com>
parent 73b5be67
......@@ -19,7 +19,7 @@ from __future__ import division
from __future__ import print_function
import os
import tensorflow as tf
import tensorflow.compat.v1 as tf
from google.protobuf import text_format
......
......@@ -21,7 +21,7 @@ from __future__ import print_function
import os
from six.moves import range
import tensorflow as tf
import tensorflow.compat.v1 as tf
from google.protobuf import text_format
......
......@@ -18,7 +18,7 @@ from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import tensorflow as tf
import tensorflow.compat.v1 as tf
from object_detection.utils import context_manager
......
......@@ -19,7 +19,7 @@ from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import tensorflow as tf
import tensorflow.compat.v1 as tf
def int64_feature(value):
......
......@@ -20,7 +20,7 @@ from __future__ import division
from __future__ import print_function
import os
import tensorflow as tf
import tensorflow.compat.v1 as tf
from object_detection.utils import dataset_util
......
......@@ -15,7 +15,7 @@
"""Tests for google3.image.understanding.object_detection.utils.json_utils."""
import os
import tensorflow as tf
import tensorflow.compat.v1 as tf
from object_detection.utils import json_utils
......
......@@ -18,14 +18,18 @@ from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import collections
import logging
import numpy as np
from six import string_types
from six.moves import range
import tensorflow as tf
import tensorflow.compat.v1 as tf
from google.protobuf import text_format
from object_detection.protos import string_int_label_map_pb2
_LABEL_OFFSET = 1
def _validate_label_map(label_map):
"""Checks if a label map is valid.
......@@ -216,6 +220,59 @@ def get_label_map_dict(label_map_path_or_proto,
return label_map_dict
def get_label_map_hierarchy_lut(label_map_path_or_proto,
include_identity=False):
"""Reads a label map and returns ancestors and descendants in the hierarchy.
The function returns the ancestors and descendants as separate look up tables
(LUT) numpy arrays of shape [max_id, max_id] where lut[i,j] = 1 when there is
a hierarchical relationship between class i and j.
Args:
label_map_path_or_proto: path to StringIntLabelMap proto text file or the
proto itself.
include_identity: Boolean to indicate whether to include a class element
among its ancestors and descendants. Setting this will result in the lut
diagonal being set to 1.
Returns:
ancestors_lut: Look up table with the ancestors.
descendants_lut: Look up table with the descendants.
"""
if isinstance(label_map_path_or_proto, string_types):
label_map = load_labelmap(label_map_path_or_proto)
else:
_validate_label_map(label_map_path_or_proto)
label_map = label_map_path_or_proto
hierarchy_dict = {
'ancestors': collections.defaultdict(list),
'descendants': collections.defaultdict(list)
}
max_id = -1
for item in label_map.item:
max_id = max(max_id, item.id)
for ancestor in item.ancestor_ids:
hierarchy_dict['ancestors'][item.id].append(ancestor)
for descendant in item.descendant_ids:
hierarchy_dict['descendants'][item.id].append(descendant)
def get_graph_relations_tensor(graph_relations):
graph_relations_tensor = np.zeros([max_id, max_id])
for id_val, ids_related in graph_relations.items():
id_val = int(id_val) - _LABEL_OFFSET
for id_related in ids_related:
id_related -= _LABEL_OFFSET
graph_relations_tensor[id_val, id_related] = 1
if include_identity:
graph_relations_tensor += np.eye(max_id)
return graph_relations_tensor
ancestors_lut = get_graph_relations_tensor(hierarchy_dict['ancestors'])
descendants_lut = get_graph_relations_tensor(hierarchy_dict['descendants'])
return ancestors_lut, descendants_lut
def create_categories_from_labelmap(label_map_path, use_display_name=True):
"""Reads a label map and returns categories list compatible with eval.
......
......@@ -19,8 +19,9 @@ from __future__ import division
from __future__ import print_function
import os
import numpy as np
from six.moves import range
import tensorflow as tf
import tensorflow.compat.v1 as tf
from google.protobuf import text_format
from object_detection.protos import string_int_label_map_pb2
......@@ -38,6 +39,22 @@ class LabelMapUtilTest(tf.test.TestCase):
item.display_name = str(i)
return label_map_proto
def _generate_label_map_with_hierarchy(self, num_classes, ancestors_dict,
descendants_dict):
label_map_proto = string_int_label_map_pb2.StringIntLabelMap()
for i in range(1, num_classes + 1):
item = label_map_proto.item.add()
item.id = i
item.name = 'label_' + str(i)
item.display_name = str(i)
if i in ancestors_dict:
for anc_i in ancestors_dict[i]:
item.ancestor_ids.append(anc_i)
if i in descendants_dict:
for desc_i in descendants_dict[i]:
item.descendant_ids.append(desc_i)
return label_map_proto
def test_get_label_map_dict(self):
label_map_string = """
item {
......@@ -404,6 +421,37 @@ class LabelMapUtilTest(tf.test.TestCase):
}
}, label_map_util.create_category_index_from_labelmap(label_map_path))
def test_get_label_map_hierarchy_lut(self):
num_classes = 5
ancestors = {2: [1, 3], 5: [1]}
descendants = {1: [2], 5: [1, 2]}
label_map = self._generate_label_map_with_hierarchy(num_classes, ancestors,
descendants)
gt_hierarchy_dict_lut = {
'ancestors':
np.array([
[1, 0, 0, 0, 0],
[1, 1, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 1, 0],
[1, 0, 0, 0, 1],
]),
'descendants':
np.array([
[1, 1, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 1, 0],
[1, 1, 0, 0, 1],
]),
}
ancestors_lut, descendants_lut = (
label_map_util.get_label_map_hierarchy_lut(label_map, True))
np.testing.assert_array_equal(gt_hierarchy_dict_lut['ancestors'],
ancestors_lut)
np.testing.assert_array_equal(gt_hierarchy_dict_lut['descendants'],
descendants_lut)
if __name__ == '__main__':
tf.test.main()
......@@ -20,7 +20,7 @@ from __future__ import print_function
import numpy as np
from six.moves import range
from six.moves import zip
import tensorflow as tf
import tensorflow.compat.v1 as tf
def exponential_decay_with_burnin(global_step,
......
......@@ -20,7 +20,7 @@ from __future__ import print_function
import numpy as np
from six.moves import range
import tensorflow as tf
import tensorflow.compat.v1 as tf
from object_detection.utils import learning_schedules
from object_detection.utils import test_case
......
......@@ -19,7 +19,7 @@ from __future__ import division
from __future__ import print_function
import numpy as np
import tensorflow as tf
import tensorflow.compat.v1 as tf
from object_detection.utils import metrics
......
......@@ -19,7 +19,7 @@ from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import tensorflow as tf
import tensorflow.compat.v1 as tf
def extract_submodel(model, inputs, outputs, name=None):
......
......@@ -19,7 +19,7 @@ from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import tensorflow as tf
import tensorflow.compat.v1 as tf
from object_detection.utils import model_util
......
......@@ -20,7 +20,7 @@ from __future__ import division
from __future__ import print_function
import numpy as np
import tensorflow as tf
import tensorflow.compat.v1 as tf
from object_detection.utils import np_box_list
from object_detection.utils import np_box_list_ops
......
......@@ -20,7 +20,7 @@ from __future__ import division
from __future__ import print_function
import numpy as np
import tensorflow as tf
import tensorflow.compat.v1 as tf
from object_detection.utils import np_box_list
......
......@@ -20,7 +20,7 @@ from __future__ import division
from __future__ import print_function
import numpy as np
import tensorflow as tf
import tensorflow.compat.v1 as tf
from object_detection.utils import np_box_mask_list
from object_detection.utils import np_box_mask_list_ops
......
......@@ -20,7 +20,7 @@ from __future__ import division
from __future__ import print_function
import numpy as np
import tensorflow as tf
import tensorflow.compat.v1 as tf
from object_detection.utils import np_box_mask_list
......
......@@ -20,7 +20,7 @@ from __future__ import division
from __future__ import print_function
import numpy as np
import tensorflow as tf
import tensorflow.compat.v1 as tf
from object_detection.utils import np_box_ops
......
......@@ -20,7 +20,7 @@ from __future__ import division
from __future__ import print_function
import numpy as np
import tensorflow as tf
import tensorflow.compat.v1 as tf
from object_detection.utils import np_mask_ops
......
......@@ -40,7 +40,7 @@ import numpy as np
import six
from six.moves import range
from six.moves import zip
import tensorflow as tf
import tensorflow.compat.v1 as tf
from object_detection.core import standard_fields
from object_detection.utils import label_map_util
......@@ -815,8 +815,11 @@ class OpenImagesChallengeEvaluator(OpenImagesDetectionEvaluator):
metric_prefix=metrics_prefix)
self._evaluatable_labels = {}
self._expected_keys.add(
standard_fields.InputDataFields.groundtruth_image_classes)
# Only one of the two has to be provided, but both options are given
# for compatibility with previous codebase.
self._expected_keys.update([
standard_fields.InputDataFields.groundtruth_image_classes,
standard_fields.InputDataFields.groundtruth_labeled_classes])
def add_single_ground_truth_image_info(self, image_id, groundtruth_dict):
"""Adds groundtruth for a single image to be used for evaluation.
......@@ -841,14 +844,18 @@ class OpenImagesChallengeEvaluator(OpenImagesDetectionEvaluator):
"""
super(OpenImagesChallengeEvaluator,
self).add_single_ground_truth_image_info(image_id, groundtruth_dict)
input_fields = standard_fields.InputDataFields
groundtruth_classes = (
groundtruth_dict[standard_fields.InputDataFields.groundtruth_classes] -
groundtruth_dict[input_fields.groundtruth_classes] -
self._label_id_offset)
image_classes = np.array([], dtype=int)
if input_fields.groundtruth_image_classes in groundtruth_dict:
image_classes = groundtruth_dict[input_fields.groundtruth_image_classes]
elif input_fields.groundtruth_labeled_classes in groundtruth_dict:
image_classes = groundtruth_dict[input_fields.groundtruth_labeled_classes]
image_classes -= self._label_id_offset
self._evaluatable_labels[image_id] = np.unique(
np.concatenate(((groundtruth_dict.get(
standard_fields.InputDataFields.groundtruth_image_classes,
np.array([], dtype=int)) - self._label_id_offset),
groundtruth_classes)))
np.concatenate((image_classes, groundtruth_classes)))
def add_single_detected_image_info(self, image_id, detections_dict):
"""Adds detections for a single image to be used for evaluation.
......
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