Skip to content

Commit a1337e0

Browse files
committed
Merged commit includes the following changes:
223075771 by lzc: Bring in external fixes. -- 222919755 by ronnyvotel: Bug fix in faster r-cnn model builder. Was previously using `inplace_batchnorm_update` for `reuse_weights`. -- 222885680 by Zhichao Lu: Use the result_dict_for_batched_example in models_lib Also fixes the visualization size on when eval is on GPU -- 222883648 by Zhichao Lu: Fix _unmatched_class_label for the _add_background_class == False case in ssd_meta_arch.py. -- 222836663 by Zhichao Lu: Adding support for visualizing grayscale images. Without this change, the images are black-red instead of grayscale. -- 222501978 by Zhichao Lu: Fix a bug that caused convert_to_grayscale flag not to be respected. -- 222432846 by richardmunoz: Fix mapping of groundtruth_confidences from shape [num_boxes] to [num_boxes, num_classes] when the input contains the groundtruth_confidences field. -- 221725755 by richardmunoz: Internal change. -- 221458536 by Zhichao Lu: Fix saver defer build bug in object detection train codepath. -- 221391590 by Zhichao Lu: Add support for group normalization in the object detection API. Just adding MobileNet-v1 SSD currently. This may serve as a road map for other models that wish to support group normalization as an option. -- 221367993 by Zhichao Lu: Bug fixes (1) Make RandomPadImage work, (2) Fix keep_checkpoint_every_n_hours. -- 221266403 by rathodv: Use detection boxes as proposals to compute correct mask loss in eval jobs. -- 220845934 by lzc: Internal change. -- 220778850 by Zhichao Lu: Incorporating existing metrics into Estimator framework. Should restore: -oid_challenge_detection_metrics -pascal_voc_detection_metrics -weighted_pascal_voc_detection_metrics -pascal_voc_instance_segmentation_metrics -weighted_pascal_voc_instance_segmentation_metrics -oid_V2_detection_metrics -- 220370391 by alirezafathi: Adding precision and recall to the metrics. -- 220321268 by Zhichao Lu: Allow the option of setting max_examples_to_draw to zero. -- 220193337 by Zhichao Lu: This CL fixes a bug where the Keras convolutional box predictor was applying heads in the non-deterministic dict order. The consequence of this bug was that variables were created in non-deterministic orders. This in turn led different workers in a multi-gpu training setup to have slightly different graphs which had variables assigned to mismatched parameter servers. As a result, roughly half of all workers were unable to initialize and did no work, and training time was slowed down approximately 2x. -- 220136508 by huizhongc: Add weight equalization loss to SSD meta arch. -- 220125875 by pengchong: Rename label_scores to label_weights -- 219730108 by Zhichao Lu: Add description of detection_keypoints in postprocessed_tensors to docstring. -- 219577519 by pengchong: Support parsing the class confidences and training using them. -- 219547611 by lzc: Stop using static shapes in GPU eval jobs. -- 219536476 by Zhichao Lu: Migrate TensorFlow Lite out of tensorflow/contrib This change moves //tensorflow/contrib/lite to //tensorflow/lite in preparation for TensorFlow 2.0's deprecation of contrib/. If you refer to TF Lite build targets or headers, you will need to update them manually. If you use TF Lite from the TensorFlow python package, "tf.contrib.lite" now points to "tf.lite". Please update your imports as soon as possible. For more details, see https://groups.google.com/a/tensorflow.org/forum/#!topic/tflite/iIIXOTOFvwQ @angersson and @aselle are conducting this migration. Please contact them if you have any further questions. -- 219190083 by Zhichao Lu: Add a second expected_loss_weights function using an alternative expectation calculation compared to previous. Integrate this op into ssd_meta_arch and losses builder. Affects files that use losses_builder.build to handle the returning of an additional element. -- 218924451 by pengchong: Add a new way to assign training targets using groundtruth confidences. -- 218760524 by chowdhery: Modify export script to add option for regular NMS in TFLite post-processing op. -- PiperOrigin-RevId: 223075771
1 parent 2c680af commit a1337e0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+2479
-1168
lines changed

research/object_detection/builders/box_predictor_builder.py

+3-79
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
"""Function to build box predictor from configuration."""
1717

1818
import collections
19-
from absl import logging
2019
import tensorflow as tf
2120
from object_detection.predictors import convolutional_box_predictor
2221
from object_detection.predictors import convolutional_keras_box_predictor
@@ -26,7 +25,6 @@
2625
from object_detection.predictors.heads import class_head
2726
from object_detection.predictors.heads import keras_box_head
2827
from object_detection.predictors.heads import keras_class_head
29-
from object_detection.predictors.heads import keras_mask_head
3028
from object_detection.predictors.heads import mask_head
3129
from object_detection.protos import box_predictor_pb2
3230

@@ -44,8 +42,7 @@ def build_convolutional_box_predictor(is_training,
4442
apply_sigmoid_to_scores=False,
4543
add_background_class=True,
4644
class_prediction_bias_init=0.0,
47-
use_depthwise=False,
48-
mask_head_config=None):
45+
use_depthwise=False,):
4946
"""Builds the ConvolutionalBoxPredictor from the arguments.
5047
5148
Args:
@@ -80,8 +77,6 @@ def build_convolutional_box_predictor(is_training,
8077
conv2d layer before class prediction.
8178
use_depthwise: Whether to use depthwise convolutions for prediction
8279
steps. Default is False.
83-
mask_head_config: An optional MaskHead object containing configs for mask
84-
head construction.
8580
8681
Returns:
8782
A ConvolutionalBoxPredictor class.
@@ -101,21 +96,6 @@ def build_convolutional_box_predictor(is_training,
10196
class_prediction_bias_init=class_prediction_bias_init,
10297
use_depthwise=use_depthwise)
10398
other_heads = {}
104-
if mask_head_config is not None:
105-
if not mask_head_config.masks_are_class_agnostic:
106-
logging.warning('Note that class specific mask prediction for SSD '
107-
'models is memory consuming.')
108-
other_heads[convolutional_box_predictor.MASK_PREDICTIONS] = (
109-
mask_head.ConvolutionalMaskHead(
110-
is_training=is_training,
111-
num_classes=num_classes,
112-
use_dropout=use_dropout,
113-
dropout_keep_prob=dropout_keep_prob,
114-
kernel_size=kernel_size,
115-
use_depthwise=use_depthwise,
116-
mask_height=mask_head_config.mask_height,
117-
mask_width=mask_head_config.mask_width,
118-
masks_are_class_agnostic=mask_head_config.masks_are_class_agnostic))
11999
return convolutional_box_predictor.ConvolutionalBoxPredictor(
120100
is_training=is_training,
121101
num_classes=num_classes,
@@ -144,7 +124,6 @@ def build_convolutional_keras_box_predictor(is_training,
144124
add_background_class=True,
145125
class_prediction_bias_init=0.0,
146126
use_depthwise=False,
147-
mask_head_config=None,
148127
name='BoxPredictor'):
149128
"""Builds the Keras ConvolutionalBoxPredictor from the arguments.
150129
@@ -189,8 +168,6 @@ def build_convolutional_keras_box_predictor(is_training,
189168
conv2d layer before class prediction.
190169
use_depthwise: Whether to use depthwise convolutions for prediction
191170
steps. Default is False.
192-
mask_head_config: An optional MaskHead object containing configs for mask
193-
head construction.
194171
name: A string name scope to assign to the box predictor. If `None`, Keras
195172
will auto-generate one from the class name.
196173
@@ -199,11 +176,7 @@ def build_convolutional_keras_box_predictor(is_training,
199176
"""
200177
box_prediction_heads = []
201178
class_prediction_heads = []
202-
mask_prediction_heads = []
203179
other_heads = {}
204-
if mask_head_config is not None:
205-
other_heads[convolutional_box_predictor.MASK_PREDICTIONS] = \
206-
mask_prediction_heads
207180

208181
for stack_index, num_predictions_per_location in enumerate(
209182
num_predictions_per_location_list):
@@ -231,26 +204,6 @@ def build_convolutional_keras_box_predictor(is_training,
231204
class_prediction_bias_init=class_prediction_bias_init,
232205
use_depthwise=use_depthwise,
233206
name='ConvolutionalClassHead_%d' % stack_index))
234-
if mask_head_config is not None:
235-
if not mask_head_config.masks_are_class_agnostic:
236-
logging.warning('Note that class specific mask prediction for SSD '
237-
'models is memory consuming.')
238-
mask_prediction_heads.append(
239-
keras_mask_head.ConvolutionalMaskHead(
240-
is_training=is_training,
241-
num_classes=num_classes,
242-
use_dropout=use_dropout,
243-
dropout_keep_prob=dropout_keep_prob,
244-
kernel_size=kernel_size,
245-
conv_hyperparams=conv_hyperparams,
246-
freeze_batchnorm=freeze_batchnorm,
247-
num_predictions_per_location=num_predictions_per_location,
248-
use_depthwise=use_depthwise,
249-
mask_height=mask_head_config.mask_height,
250-
mask_width=mask_head_config.mask_width,
251-
masks_are_class_agnostic=mask_head_config.
252-
masks_are_class_agnostic,
253-
name='ConvolutionalMaskHead_%d' % stack_index))
254207

255208
return convolutional_keras_box_predictor.ConvolutionalBoxPredictor(
256209
is_training=is_training,
@@ -282,7 +235,6 @@ def build_weight_shared_convolutional_box_predictor(
282235
share_prediction_tower=False,
283236
apply_batch_norm=True,
284237
use_depthwise=False,
285-
mask_head_config=None,
286238
score_converter_fn=tf.identity,
287239
box_encodings_clip_range=None):
288240
"""Builds and returns a WeightSharedConvolutionalBoxPredictor class.
@@ -310,8 +262,6 @@ def build_weight_shared_convolutional_box_predictor(
310262
apply_batch_norm: Whether to apply batch normalization to conv layers in
311263
this predictor.
312264
use_depthwise: Whether to use depthwise separable conv2d instead of conv2d.
313-
mask_head_config: An optional MaskHead object containing configs for mask
314-
head construction.
315265
score_converter_fn: Callable score converter to perform elementwise op on
316266
class scores.
317267
box_encodings_clip_range: Min and max values for clipping the box_encodings.
@@ -335,19 +285,6 @@ class scores.
335285
use_depthwise=use_depthwise,
336286
score_converter_fn=score_converter_fn))
337287
other_heads = {}
338-
if mask_head_config is not None:
339-
if not mask_head_config.masks_are_class_agnostic:
340-
logging.warning('Note that class specific mask prediction for SSD '
341-
'models is memory consuming.')
342-
other_heads[convolutional_box_predictor.MASK_PREDICTIONS] = (
343-
mask_head.WeightSharedConvolutionalMaskHead(
344-
num_classes=num_classes,
345-
kernel_size=kernel_size,
346-
use_dropout=use_dropout,
347-
dropout_keep_prob=dropout_keep_prob,
348-
mask_height=mask_head_config.mask_height,
349-
mask_width=mask_head_config.mask_width,
350-
masks_are_class_agnostic=mask_head_config.masks_are_class_agnostic))
351288
return convolutional_box_predictor.WeightSharedConvolutionalBoxPredictor(
352289
is_training=is_training,
353290
num_classes=num_classes,
@@ -520,9 +457,6 @@ def build(argscope_fn, box_predictor_config, is_training, num_classes,
520457
config_box_predictor = box_predictor_config.convolutional_box_predictor
521458
conv_hyperparams_fn = argscope_fn(config_box_predictor.conv_hyperparams,
522459
is_training)
523-
mask_head_config = (
524-
config_box_predictor.mask_head
525-
if config_box_predictor.HasField('mask_head') else None)
526460
return build_convolutional_box_predictor(
527461
is_training=is_training,
528462
num_classes=num_classes,
@@ -539,8 +473,7 @@ def build(argscope_fn, box_predictor_config, is_training, num_classes,
539473
apply_sigmoid_to_scores=config_box_predictor.apply_sigmoid_to_scores,
540474
class_prediction_bias_init=(
541475
config_box_predictor.class_prediction_bias_init),
542-
use_depthwise=config_box_predictor.use_depthwise,
543-
mask_head_config=mask_head_config)
476+
use_depthwise=config_box_predictor.use_depthwise)
544477

545478
if box_predictor_oneof == 'weight_shared_convolutional_box_predictor':
546479
config_box_predictor = (
@@ -549,9 +482,6 @@ def build(argscope_fn, box_predictor_config, is_training, num_classes,
549482
is_training)
550483
apply_batch_norm = config_box_predictor.conv_hyperparams.HasField(
551484
'batch_norm')
552-
mask_head_config = (
553-
config_box_predictor.mask_head
554-
if config_box_predictor.HasField('mask_head') else None)
555485
# During training phase, logits are used to compute the loss. Only apply
556486
# sigmoid at inference to make the inference graph TPU friendly.
557487
score_converter_fn = build_score_converter(
@@ -581,7 +511,6 @@ def build(argscope_fn, box_predictor_config, is_training, num_classes,
581511
share_prediction_tower=config_box_predictor.share_prediction_tower,
582512
apply_batch_norm=apply_batch_norm,
583513
use_depthwise=config_box_predictor.use_depthwise,
584-
mask_head_config=mask_head_config,
585514
score_converter_fn=score_converter_fn,
586515
box_encodings_clip_range=box_encodings_clip_range)
587516

@@ -680,10 +609,6 @@ def build_keras(conv_hyperparams_fn, freeze_batchnorm, inplace_batchnorm_update,
680609
config_box_predictor = box_predictor_config.convolutional_box_predictor
681610
conv_hyperparams = conv_hyperparams_fn(
682611
config_box_predictor.conv_hyperparams)
683-
684-
mask_head_config = (
685-
config_box_predictor.mask_head
686-
if config_box_predictor.HasField('mask_head') else None)
687612
return build_convolutional_keras_box_predictor(
688613
is_training=is_training,
689614
num_classes=num_classes,
@@ -702,8 +627,7 @@ def build_keras(conv_hyperparams_fn, freeze_batchnorm, inplace_batchnorm_update,
702627
max_depth=config_box_predictor.max_depth,
703628
class_prediction_bias_init=(
704629
config_box_predictor.class_prediction_bias_init),
705-
use_depthwise=config_box_predictor.use_depthwise,
706-
mask_head_config=mask_head_config)
630+
use_depthwise=config_box_predictor.use_depthwise)
707631

708632
raise ValueError(
709633
'Unknown box predictor for Keras: {}'.format(box_predictor_oneof))

research/object_detection/builders/box_predictor_builder_test.py

-142
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@
2121
from google.protobuf import text_format
2222
from object_detection.builders import box_predictor_builder
2323
from object_detection.builders import hyperparams_builder
24-
from object_detection.predictors import convolutional_box_predictor
2524
from object_detection.predictors import mask_rcnn_box_predictor
26-
from object_detection.predictors.heads import mask_head
2725
from object_detection.protos import box_predictor_pb2
2826
from object_detection.protos import hyperparams_pb2
2927

@@ -161,73 +159,6 @@ def test_construct_default_conv_box_predictor(self):
161159
self.assertTrue(box_predictor._is_training)
162160
self.assertFalse(class_head._use_depthwise)
163161

164-
def test_construct_default_conv_box_predictor_with_default_mask_head(self):
165-
box_predictor_text_proto = """
166-
convolutional_box_predictor {
167-
mask_head {
168-
}
169-
conv_hyperparams {
170-
regularizer {
171-
l1_regularizer {
172-
}
173-
}
174-
initializer {
175-
truncated_normal_initializer {
176-
}
177-
}
178-
}
179-
}"""
180-
box_predictor_proto = box_predictor_pb2.BoxPredictor()
181-
text_format.Merge(box_predictor_text_proto, box_predictor_proto)
182-
box_predictor = box_predictor_builder.build(
183-
argscope_fn=hyperparams_builder.build,
184-
box_predictor_config=box_predictor_proto,
185-
is_training=True,
186-
num_classes=90)
187-
self.assertTrue(convolutional_box_predictor.MASK_PREDICTIONS in
188-
box_predictor._other_heads)
189-
mask_prediction_head = (
190-
box_predictor._other_heads[convolutional_box_predictor.MASK_PREDICTIONS]
191-
)
192-
self.assertEqual(mask_prediction_head._mask_height, 15)
193-
self.assertEqual(mask_prediction_head._mask_width, 15)
194-
self.assertTrue(mask_prediction_head._masks_are_class_agnostic)
195-
196-
def test_construct_default_conv_box_predictor_with_custom_mask_head(self):
197-
box_predictor_text_proto = """
198-
convolutional_box_predictor {
199-
mask_head {
200-
mask_height: 7
201-
mask_width: 7
202-
masks_are_class_agnostic: false
203-
}
204-
conv_hyperparams {
205-
regularizer {
206-
l1_regularizer {
207-
}
208-
}
209-
initializer {
210-
truncated_normal_initializer {
211-
}
212-
}
213-
}
214-
}"""
215-
box_predictor_proto = box_predictor_pb2.BoxPredictor()
216-
text_format.Merge(box_predictor_text_proto, box_predictor_proto)
217-
box_predictor = box_predictor_builder.build(
218-
argscope_fn=hyperparams_builder.build,
219-
box_predictor_config=box_predictor_proto,
220-
is_training=True,
221-
num_classes=90)
222-
self.assertTrue(convolutional_box_predictor.MASK_PREDICTIONS in
223-
box_predictor._other_heads)
224-
mask_prediction_head = (
225-
box_predictor._other_heads[convolutional_box_predictor.MASK_PREDICTIONS]
226-
)
227-
self.assertEqual(mask_prediction_head._mask_height, 7)
228-
self.assertEqual(mask_prediction_head._mask_width, 7)
229-
self.assertFalse(mask_prediction_head._masks_are_class_agnostic)
230-
231162

232163
class WeightSharedConvolutionalBoxPredictorBuilderTest(tf.test.TestCase):
233164

@@ -421,79 +352,6 @@ def test_construct_default_conv_box_predictor_with_batch_norm(self):
421352
self.assertTrue(box_predictor._is_training)
422353
self.assertEqual(box_predictor._apply_batch_norm, True)
423354

424-
def test_construct_weight_shared_predictor_with_default_mask_head(self):
425-
box_predictor_text_proto = """
426-
weight_shared_convolutional_box_predictor {
427-
mask_head {
428-
}
429-
conv_hyperparams {
430-
regularizer {
431-
l1_regularizer {
432-
}
433-
}
434-
initializer {
435-
truncated_normal_initializer {
436-
}
437-
}
438-
}
439-
}"""
440-
box_predictor_proto = box_predictor_pb2.BoxPredictor()
441-
text_format.Merge(box_predictor_text_proto, box_predictor_proto)
442-
box_predictor = box_predictor_builder.build(
443-
argscope_fn=hyperparams_builder.build,
444-
box_predictor_config=box_predictor_proto,
445-
is_training=True,
446-
num_classes=90)
447-
self.assertTrue(convolutional_box_predictor.MASK_PREDICTIONS in
448-
box_predictor._other_heads)
449-
weight_shared_convolutional_mask_head = (
450-
box_predictor._other_heads[convolutional_box_predictor.MASK_PREDICTIONS]
451-
)
452-
self.assertIsInstance(weight_shared_convolutional_mask_head,
453-
mask_head.WeightSharedConvolutionalMaskHead)
454-
self.assertEqual(weight_shared_convolutional_mask_head._mask_height, 15)
455-
self.assertEqual(weight_shared_convolutional_mask_head._mask_width, 15)
456-
self.assertTrue(
457-
weight_shared_convolutional_mask_head._masks_are_class_agnostic)
458-
459-
def test_construct_weight_shared_predictor_with_custom_mask_head(self):
460-
box_predictor_text_proto = """
461-
weight_shared_convolutional_box_predictor {
462-
mask_head {
463-
mask_height: 7
464-
mask_width: 7
465-
masks_are_class_agnostic: false
466-
}
467-
conv_hyperparams {
468-
regularizer {
469-
l1_regularizer {
470-
}
471-
}
472-
initializer {
473-
truncated_normal_initializer {
474-
}
475-
}
476-
}
477-
}"""
478-
box_predictor_proto = box_predictor_pb2.BoxPredictor()
479-
text_format.Merge(box_predictor_text_proto, box_predictor_proto)
480-
box_predictor = box_predictor_builder.build(
481-
argscope_fn=hyperparams_builder.build,
482-
box_predictor_config=box_predictor_proto,
483-
is_training=True,
484-
num_classes=90)
485-
self.assertTrue(convolutional_box_predictor.MASK_PREDICTIONS in
486-
box_predictor._other_heads)
487-
weight_shared_convolutional_mask_head = (
488-
box_predictor._other_heads[convolutional_box_predictor.MASK_PREDICTIONS]
489-
)
490-
self.assertIsInstance(weight_shared_convolutional_mask_head,
491-
mask_head.WeightSharedConvolutionalMaskHead)
492-
self.assertEqual(weight_shared_convolutional_mask_head._mask_height, 7)
493-
self.assertEqual(weight_shared_convolutional_mask_head._mask_width, 7)
494-
self.assertFalse(
495-
weight_shared_convolutional_mask_head._masks_are_class_agnostic)
496-
497355

498356
class MaskRCNNBoxPredictorBuilderTest(tf.test.TestCase):
499357

0 commit comments

Comments
 (0)