def test_get_expected_feature_map_shapes_with_inception_v2(self): with test_utils.GraphContextOrNone() as g: image_features = { 'Mixed_3c': tf.random_uniform([4, 28, 28, 256], dtype=tf.float32), 'Mixed_4c': tf.random_uniform([4, 14, 14, 576], dtype=tf.float32), 'Mixed_5c': tf.random_uniform([4, 7, 7, 1024], dtype=tf.float32) } feature_map_generator = self._build_feature_map_generator( feature_map_layout=INCEPTION_V2_LAYOUT) def graph_fn(): feature_maps = feature_map_generator(image_features) return feature_maps expected_feature_map_shapes = { 'Mixed_3c': (4, 28, 28, 256), 'Mixed_4c': (4, 14, 14, 576), 'Mixed_5c': (4, 7, 7, 1024), 'Mixed_5c_2_Conv2d_3_3x3_s2_512': (4, 4, 4, 512), 'Mixed_5c_2_Conv2d_4_3x3_s2_256': (4, 2, 2, 256), 'Mixed_5c_2_Conv2d_5_3x3_s2_256': (4, 1, 1, 256) } out_feature_maps = self.execute(graph_fn, [], g) out_feature_map_shapes = dict( (key, value.shape) for key, value in out_feature_maps.items()) self.assertDictEqual(expected_feature_map_shapes, out_feature_map_shapes)
def test_get_expected_feature_map_shapes_with_depthwise( self, use_native_resize_op): with test_utils.GraphContextOrNone() as g: image_features = [ ('block2', tf.random_uniform([4, 8, 8, 256], dtype=tf.float32)), ('block3', tf.random_uniform([4, 4, 4, 256], dtype=tf.float32)), ('block4', tf.random_uniform([4, 2, 2, 256], dtype=tf.float32)), ('block5', tf.random_uniform([4, 1, 1, 256], dtype=tf.float32)) ] feature_map_generator = self._build_feature_map_generator( image_features=image_features, depth=128, use_depthwise=True, use_native_resize_op=use_native_resize_op) def graph_fn(): return feature_map_generator(image_features) expected_feature_map_shapes = { 'top_down_block2': (4, 8, 8, 128), 'top_down_block3': (4, 4, 4, 128), 'top_down_block4': (4, 2, 2, 128), 'top_down_block5': (4, 1, 1, 128) } out_feature_maps = self.execute(graph_fn, [], g) out_feature_map_shapes = dict( (key, value.shape) for key, value in out_feature_maps.items()) self.assertDictEqual(expected_feature_map_shapes, out_feature_map_shapes)
def test_loss_results_are_correct_with_normalize_by_codesize_true(self): with test_utils.GraphContextOrNone() as g: model, _, _, _ = self._create_model( apply_hard_mining=False, normalize_loc_loss_by_codesize=True) def graph_fn(preprocessed_tensor, groundtruth_boxes1, groundtruth_boxes2, groundtruth_classes1, groundtruth_classes2): groundtruth_boxes_list = [groundtruth_boxes1, groundtruth_boxes2] groundtruth_classes_list = [ groundtruth_classes1, groundtruth_classes2 ] model.provide_groundtruth(groundtruth_boxes_list, groundtruth_classes_list) prediction_dict = model.predict(preprocessed_tensor, true_image_shapes=None) loss_dict = model.loss(prediction_dict, true_image_shapes=None) return (self._get_value_for_matching_key( loss_dict, 'Loss/localization_loss'), ) batch_size = 2 preprocessed_input = np.random.rand(batch_size, 2, 2, 3).astype(np.float32) groundtruth_boxes1 = np.array([[0, 0, 1, 1]], dtype=np.float32) groundtruth_boxes2 = np.array([[0, 0, 1, 1]], dtype=np.float32) groundtruth_classes1 = np.array([[1]], dtype=np.float32) groundtruth_classes2 = np.array([[1]], dtype=np.float32) expected_localization_loss = 0.5 / 4 localization_loss = self.execute(graph_fn, [ preprocessed_input, groundtruth_boxes1, groundtruth_boxes2, groundtruth_classes1, groundtruth_classes2 ], graph=g) self.assertAllClose(localization_loss, expected_localization_loss)
def test_predict_result_shapes_on_image_with_static_shape(self): with test_utils.GraphContextOrNone() as g: model, num_classes, num_anchors, code_size = self._create_model() def graph_fn(input_image): predictions = model.predict(input_image, true_image_shapes=None) return (predictions['box_encodings'], predictions['class_predictions_with_background'], predictions['final_anchors']) batch_size = 3 image_size = 2 channels = 3 input_image = np.random.rand(batch_size, image_size, image_size, channels).astype(np.float32) expected_box_encodings_shape = (batch_size, num_anchors, code_size) expected_class_predictions_shape = (batch_size, num_anchors, num_classes + 1) final_anchors_shape = (batch_size, num_anchors, 4) (box_encodings, class_predictions, final_anchors) = self.execute(graph_fn, [input_image], graph=g) self.assertAllEqual(box_encodings.shape, expected_box_encodings_shape) self.assertAllEqual(class_predictions.shape, expected_class_predictions_shape) self.assertAllEqual(final_anchors.shape, final_anchors_shape)
def test_use_bounded_activations_add_operations(self, use_native_resize_op): with test_utils.GraphContextOrNone() as g: image_features = [ ('block2', tf.random_uniform([4, 8, 8, 256], dtype=tf.float32)), ('block3', tf.random_uniform([4, 4, 4, 256], dtype=tf.float32)), ('block4', tf.random_uniform([4, 2, 2, 256], dtype=tf.float32)), ('block5', tf.random_uniform([4, 1, 1, 256], dtype=tf.float32)) ] feature_map_generator = self._build_feature_map_generator( image_features=image_features, depth=128, use_bounded_activations=True, use_native_resize_op=use_native_resize_op) def graph_fn(): return feature_map_generator(image_features) self.execute(graph_fn, [], g) expected_added_operations = dict.fromkeys([ 'top_down/clip_by_value', 'top_down/clip_by_value_1', 'top_down/clip_by_value_2', 'top_down/clip_by_value_3', 'top_down/clip_by_value_4', 'top_down/clip_by_value_5', 'top_down/clip_by_value_6' ]) op_names = {op.name: None for op in g.get_operations()} self.assertDictContainsSubset(expected_added_operations, op_names)
def test_feature_map_shapes_with_pool_residual_ssd_mobilenet_v1(self): with test_utils.GraphContextOrNone() as g: image_features = { 'Conv2d_13_pointwise': tf.random_uniform([4, 8, 8, 1024], dtype=tf.float32), } feature_map_generator = self._build_feature_map_generator( feature_map_layout=SSD_MOBILENET_V1_WEIGHT_SHARED_LAYOUT, pool_residual=True) def graph_fn(): return feature_map_generator(image_features) expected_feature_map_shapes = { 'Conv2d_13_pointwise': (4, 8, 8, 1024), 'Conv2d_13_pointwise_2_Conv2d_1_3x3_s2_256': (4, 4, 4, 256), 'Conv2d_13_pointwise_2_Conv2d_2_3x3_s2_256': (4, 2, 2, 256), 'Conv2d_13_pointwise_2_Conv2d_3_3x3_s2_256': (4, 1, 1, 256) } out_feature_maps = self.execute(graph_fn, [], g) out_feature_map_shapes = dict( (key, value.shape) for key, value in out_feature_maps.items()) self.assertDictEqual(expected_feature_map_shapes, out_feature_map_shapes)
def test_predict_result_shapes_on_image_with_dynamic_shape(self): with test_utils.GraphContextOrNone() as g: model, num_classes, num_anchors, code_size = self._create_model() def graph_fn(): size = tf.random.uniform([], minval=2, maxval=3, dtype=tf.int32) batch = tf.random.uniform([], minval=2, maxval=3, dtype=tf.int32) shape = tf.stack([batch, size, size, 3]) image = tf.random.uniform(shape) prediction_dict = model.predict(image, true_image_shapes=None) self.assertIn('box_encodings', prediction_dict) self.assertIn('class_predictions_with_background', prediction_dict) self.assertIn('feature_maps', prediction_dict) self.assertIn('anchors', prediction_dict) self.assertIn('final_anchors', prediction_dict) return (prediction_dict['box_encodings'], prediction_dict['final_anchors'], prediction_dict['class_predictions_with_background'], tf.constant(num_anchors), batch) (box_encodings_out, final_anchors, class_predictions_with_background, num_anchors, batch_size) = self.execute_cpu(graph_fn, [], graph=g) self.assertAllEqual(box_encodings_out.shape, (batch_size, num_anchors, code_size)) self.assertAllEqual(final_anchors.shape, (batch_size, num_anchors, code_size)) self.assertAllEqual(class_predictions_with_background.shape, (batch_size, num_anchors, num_classes + 1))
def test_predict_with_raw_output_fields(self): with test_utils.GraphContextOrNone() as g: model, num_classes, num_anchors, code_size = self._create_model( return_raw_detections_during_predict=True) def graph_fn(input_image): predictions = model.predict(input_image, true_image_shapes=None) return (predictions['box_encodings'], predictions['class_predictions_with_background'], predictions['final_anchors'], predictions['raw_detection_boxes'], predictions['raw_detection_feature_map_indices']) batch_size = 3 image_size = 2 channels = 3 input_image = np.random.rand(batch_size, image_size, image_size, channels).astype(np.float32) expected_box_encodings_shape = (batch_size, num_anchors, code_size) expected_class_predictions_shape = (batch_size, num_anchors, num_classes + 1) final_anchors_shape = (batch_size, num_anchors, 4) expected_raw_detection_boxes_shape = (batch_size, num_anchors, 4) (box_encodings, class_predictions, final_anchors, raw_detection_boxes, raw_detection_feature_map_indices) = self.execute(graph_fn, [input_image], graph=g) self.assertAllEqual(box_encodings.shape, expected_box_encodings_shape) self.assertAllEqual(class_predictions.shape, expected_class_predictions_shape) self.assertAllEqual(final_anchors.shape, final_anchors_shape) self.assertAllEqual(raw_detection_boxes.shape, expected_raw_detection_boxes_shape) self.assertAllEqual(raw_detection_feature_map_indices, np.zeros((batch_size, num_anchors)))
def test_get_expected_feature_map_shapes(self, bifpn_num_iterations): with test_utils.GraphContextOrNone() as g: image_features = [ ('block3', tf.random_uniform([4, 16, 16, 256], dtype=tf.float32)), ('block4', tf.random_uniform([4, 8, 8, 256], dtype=tf.float32)), ('block5', tf.random_uniform([4, 4, 4, 256], dtype=tf.float32)) ] bifpn_generator = bifpn_generators.KerasBiFpnFeatureMaps( bifpn_num_iterations=bifpn_num_iterations, bifpn_num_filters=128, fpn_min_level=3, fpn_max_level=7, input_max_level=5, is_training=True, conv_hyperparams=self._build_conv_hyperparams(), freeze_batchnorm=False) def graph_fn(): feature_maps = bifpn_generator(image_features) return feature_maps expected_feature_map_shapes = { '{}_dn_lvl_3'.format(bifpn_num_iterations): (4, 16, 16, 128), '{}_up_lvl_4'.format(bifpn_num_iterations): (4, 8, 8, 128), '{}_up_lvl_5'.format(bifpn_num_iterations): (4, 4, 4, 128), '{}_up_lvl_6'.format(bifpn_num_iterations): (4, 2, 2, 128), '{}_up_lvl_7'.format(bifpn_num_iterations): (4, 1, 1, 128)} out_feature_maps = self.execute(graph_fn, [], g) out_feature_map_shapes = dict( (key, value.shape) for key, value in out_feature_maps.items()) self.assertDictEqual(expected_feature_map_shapes, out_feature_map_shapes)
def check_extract_features_returns_correct_shape( self, batch_size, image_height, image_width, depth_multiplier, pad_to_multiple, expected_feature_map_shapes, use_explicit_padding=False, num_layers=6, use_keras=False, use_depthwise=False): with test_utils.GraphContextOrNone() as g: feature_extractor = self._create_features( depth_multiplier, pad_to_multiple, use_explicit_padding=use_explicit_padding, num_layers=num_layers, use_keras=use_keras, use_depthwise=use_depthwise) def graph_fn(image_tensor): return self._extract_features(image_tensor, feature_extractor, use_keras=use_keras) image_tensor = np.random.rand(batch_size, image_height, image_width, 3).astype(np.float32) feature_maps = self.execute(graph_fn, [image_tensor], graph=g) for feature_map, expected_shape in zip(feature_maps, expected_feature_map_shapes): self.assertAllEqual(feature_map.shape, expected_shape)
def test_extract_features_returns_correct_shapes_with_min_depth(self): image_height = 256 image_width = 256 depth_multiplier = 1.0 pad_to_multiple = 1 min_depth = 320 expected_feature_map_shape = [(2, 32, 32, min_depth), (2, 16, 16, min_depth), (2, 8, 8, min_depth), (2, 4, 4, min_depth), (2, 2, 2, min_depth)] with test_utils.GraphContextOrNone() as g: image_tensor = tf.random.uniform([2, image_height, image_width, 3]) feature_extractor = self._create_feature_extractor( depth_multiplier, pad_to_multiple, min_depth=min_depth, use_keras=self.is_tf2()) def graph_fn(): if self.is_tf2(): return feature_extractor(image_tensor) return feature_extractor.extract_features(image_tensor) feature_maps = self.execute(graph_fn, [], graph=g) for feature_map, expected_shape in zip(feature_maps, expected_feature_map_shape): self.assertAllEqual(feature_map.shape, expected_shape)
def test_postprocess_results_are_correct_with_calibration(self): with test_utils.GraphContextOrNone() as g: model, _, _, _ = self._create_model(calibration_mapping_value=0.5) def graph_fn(): size = tf.random.uniform([], minval=2, maxval=3, dtype=tf.int32) batch = tf.random.uniform([], minval=2, maxval=3, dtype=tf.int32) shape = tf.stack([batch, size, size, 3]) image = tf.random.uniform(shape) preprocessed_inputs, true_image_shapes = model.preprocess(image) prediction_dict = model.predict(preprocessed_inputs, true_image_shapes) detections = model.postprocess(prediction_dict, true_image_shapes) return detections['detection_scores'], detections[ 'raw_detection_scores'] # Calibration mapping value below is set to map all scores to 0.5, except # for the last two detections in each batch (see expected number of # detections below. expected_scores = [[0.5, 0.5, 0.5, 0., 0.], [0.5, 0.5, 0.5, 0., 0.]] expected_raw_detection_scores = [[[0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5]], [[0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5]]] detection_scores, raw_detection_scores = self.execute_cpu(graph_fn, [], graph=g) self.assertAllClose(detection_scores, expected_scores) self.assertAllEqual(raw_detection_scores, expected_raw_detection_scores)
def test_raw_detection_boxes_and_anchor_indices_correct(self): batch_size = 2 image_size = 10 with test_utils.GraphContextOrNone() as g: model = self._build_model( is_training=False, number_of_stages=2, second_stage_batch_size=2, share_box_across_classes=True, return_raw_detections_during_predict=True) def graph_fn(): shape = [ tf.random_uniform([], minval=batch_size, maxval=batch_size + 1, dtype=tf.int32), tf.random_uniform([], minval=image_size, maxval=image_size + 1, dtype=tf.int32), tf.random_uniform([], minval=image_size, maxval=image_size + 1, dtype=tf.int32), 3 ] image = tf.zeros(shape) _, true_image_shapes = model.preprocess(image) predict_tensor_dict = model.predict(image, true_image_shapes) detections = model.postprocess(predict_tensor_dict, true_image_shapes) return (detections['detection_boxes'], detections['num_detections'], detections['detection_anchor_indices'], detections['raw_detection_boxes'], predict_tensor_dict['raw_detection_boxes']) (detection_boxes, num_detections, detection_anchor_indices, raw_detection_boxes, predict_raw_detection_boxes) = self.execute_cpu(graph_fn, [], graph=g) # Verify that the raw detections from predict and postprocess are the # same. self.assertAllClose(np.squeeze(predict_raw_detection_boxes), raw_detection_boxes) # Verify that the raw detection boxes at detection anchor indices are the # same as the postprocessed detections. for i in range(batch_size): num_detections_per_image = int(num_detections[i]) detection_boxes_per_image = detection_boxes[ i][:num_detections_per_image] detection_anchor_indices_per_image = detection_anchor_indices[ i][:num_detections_per_image] raw_detections_per_image = np.squeeze(raw_detection_boxes[i]) raw_detections_at_anchor_indices = raw_detections_per_image[ detection_anchor_indices_per_image] self.assertAllClose(detection_boxes_per_image, raw_detections_at_anchor_indices)
def test_postprocess_results_are_correct_static(self): with test_utils.GraphContextOrNone() as g: model, _, _, _ = self._create_model(use_static_shapes=True, nms_max_size_per_class=4) def graph_fn(input_image): preprocessed_inputs, true_image_shapes = model.preprocess( input_image) prediction_dict = model.predict(preprocessed_inputs, true_image_shapes) detections = model.postprocess(prediction_dict, true_image_shapes) return (detections['detection_boxes'], detections['detection_scores'], detections['detection_classes'], detections['num_detections'], detections['detection_multiclass_scores']) expected_boxes = [ [[0, 0, .5, .5], [0, .5, .5, 1], [.5, 0, 1, .5], [0, 0, 0, 0]], # padding [[0, 0, .5, .5], [0, .5, .5, 1], [.5, 0, 1, .5], [0, 0, 0, 0]] ] # padding expected_scores = [[0, 0, 0, 0], [0, 0, 0, 0]] expected_multiclass_scores = [[[0, 0], [0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0], [0, 0]]] expected_classes = [[0, 0, 0, 0], [0, 0, 0, 0]] expected_num_detections = np.array([3, 3]) batch_size = 2 image_size = 2 channels = 3 input_image = np.random.rand(batch_size, image_size, image_size, channels).astype(np.float32) (detection_boxes, detection_scores, detection_classes, num_detections, detection_multiclass_scores) = self.execute(graph_fn, [input_image], graph=g) for image_idx in range(batch_size): self.assertTrue( test_utils.first_rows_close_as_set( detection_boxes[image_idx] [0:expected_num_detections[image_idx]].tolist(), expected_boxes[image_idx] [0:expected_num_detections[image_idx]])) self.assertAllClose( detection_scores[image_idx] [0:expected_num_detections[image_idx]], expected_scores[image_idx] [0:expected_num_detections[image_idx]]) self.assertAllClose( detection_multiclass_scores[image_idx] [0:expected_num_detections[image_idx]], expected_multiclass_scores[image_idx] [0:expected_num_detections[image_idx]]) self.assertAllClose( detection_classes[image_idx] [0:expected_num_detections[image_idx]], expected_classes[image_idx] [0:expected_num_detections[image_idx]]) self.assertAllClose(num_detections, expected_num_detections)
def test_get_expected_variable_names_with_inception_v2(self): with test_utils.GraphContextOrNone() as g: image_features = { 'Mixed_3c': tf.random_uniform([4, 28, 28, 256], dtype=tf.float32), 'Mixed_4c': tf.random_uniform([4, 14, 14, 576], dtype=tf.float32), 'Mixed_5c': tf.random_uniform([4, 7, 7, 1024], dtype=tf.float32) } feature_map_generator = self._build_feature_map_generator( feature_map_layout=INCEPTION_V2_LAYOUT, ) def graph_fn(): return feature_map_generator(image_features) self.execute(graph_fn, [], g) expected_slim_variables = set([ 'Mixed_5c_1_Conv2d_3_1x1_256/weights', 'Mixed_5c_1_Conv2d_3_1x1_256/biases', 'Mixed_5c_2_Conv2d_3_3x3_s2_512/weights', 'Mixed_5c_2_Conv2d_3_3x3_s2_512/biases', 'Mixed_5c_1_Conv2d_4_1x1_128/weights', 'Mixed_5c_1_Conv2d_4_1x1_128/biases', 'Mixed_5c_2_Conv2d_4_3x3_s2_256/weights', 'Mixed_5c_2_Conv2d_4_3x3_s2_256/biases', 'Mixed_5c_1_Conv2d_5_1x1_128/weights', 'Mixed_5c_1_Conv2d_5_1x1_128/biases', 'Mixed_5c_2_Conv2d_5_3x3_s2_256/weights', 'Mixed_5c_2_Conv2d_5_3x3_s2_256/biases', ]) expected_keras_variables = set([ 'FeatureMaps/Mixed_5c_1_Conv2d_3_1x1_256_conv/kernel', 'FeatureMaps/Mixed_5c_1_Conv2d_3_1x1_256_conv/bias', 'FeatureMaps/Mixed_5c_2_Conv2d_3_3x3_s2_512_conv/kernel', 'FeatureMaps/Mixed_5c_2_Conv2d_3_3x3_s2_512_conv/bias', 'FeatureMaps/Mixed_5c_1_Conv2d_4_1x1_128_conv/kernel', 'FeatureMaps/Mixed_5c_1_Conv2d_4_1x1_128_conv/bias', 'FeatureMaps/Mixed_5c_2_Conv2d_4_3x3_s2_256_conv/kernel', 'FeatureMaps/Mixed_5c_2_Conv2d_4_3x3_s2_256_conv/bias', 'FeatureMaps/Mixed_5c_1_Conv2d_5_1x1_128_conv/kernel', 'FeatureMaps/Mixed_5c_1_Conv2d_5_1x1_128_conv/bias', 'FeatureMaps/Mixed_5c_2_Conv2d_5_3x3_s2_256_conv/kernel', 'FeatureMaps/Mixed_5c_2_Conv2d_5_3x3_s2_256_conv/bias', ]) if tf_version.is_tf2(): actual_variable_set = set([ var.name.split(':')[0] for var in feature_map_generator.variables ]) self.assertSetEqual(expected_keras_variables, actual_variable_set) else: with g.as_default(): actual_variable_set = set( [var.op.name for var in tf.trainable_variables()]) self.assertSetEqual(expected_slim_variables, actual_variable_set)
def test_prediction_end_to_end(self, static_shapes): """Runs prediction end to end and test the shape of the results.""" with test_utils.GraphContextOrNone() as g: model = self._build_model( is_training=False, number_of_stages=2, second_stage_batch_size=6, use_matmul_crop_and_resize=static_shapes, clip_anchors_to_image=static_shapes, use_matmul_gather_in_matcher=static_shapes, use_static_shapes=static_shapes, num_classes=42) def graph_fn(): inputs_shape = (2, 20, 20, 3) inputs = tf.cast(tf.random_uniform(inputs_shape, minval=0, maxval=255, dtype=tf.int32), dtype=tf.float32) preprocessed_inputs, true_image_shapes = model.preprocess(inputs) context_features = tf.random_uniform((2, 20, 10), minval=0, maxval=255, dtype=tf.float32) valid_context_size = tf.random_uniform((2, ), minval=0, maxval=10, dtype=tf.int32) features = { fields.InputDataFields.context_features: context_features, fields.InputDataFields.valid_context_size: valid_context_size } side_inputs = model.get_side_inputs(features) prediction_dict = model.predict(preprocessed_inputs, true_image_shapes, **side_inputs) return (prediction_dict['rpn_box_predictor_features'], prediction_dict['rpn_box_encodings'], prediction_dict['refined_box_encodings'], prediction_dict['proposal_boxes_normalized'], prediction_dict['proposal_boxes']) execute_fn = self.execute if static_shapes else self.execute_cpu (rpn_box_predictor_features, rpn_box_encodings, refined_box_encodings, proposal_boxes_normalized, proposal_boxes) = execute_fn(graph_fn, [], graph=g) self.assertAllEqual(len(rpn_box_predictor_features), 1) self.assertAllEqual(rpn_box_predictor_features[0].shape, [2, 20, 20, 512]) self.assertAllEqual(rpn_box_encodings.shape, [2, 3600, 4]) self.assertAllEqual(refined_box_encodings.shape, [16, 42, 4]) self.assertAllEqual(proposal_boxes_normalized.shape, [2, 8, 4]) self.assertAllEqual(proposal_boxes.shape, [2, 8, 4])
def test_loss_results_are_correct_with_losses_mask(self): with test_utils.GraphContextOrNone() as g: model, num_classes, num_anchors, _ = self._create_model( apply_hard_mining=False) def graph_fn(preprocessed_tensor, groundtruth_boxes1, groundtruth_boxes2, groundtruth_boxes3, groundtruth_classes1, groundtruth_classes2, groundtruth_classes3): groundtruth_boxes_list = [ groundtruth_boxes1, groundtruth_boxes2, groundtruth_boxes3 ] groundtruth_classes_list = [ groundtruth_classes1, groundtruth_classes2, groundtruth_classes3 ] is_annotated_list = [ tf.constant(True), tf.constant(True), tf.constant(False) ] model.provide_groundtruth(groundtruth_boxes_list, groundtruth_classes_list, is_annotated_list=is_annotated_list) prediction_dict = model.predict(preprocessed_tensor, true_image_shapes=None) loss_dict = model.loss(prediction_dict, true_image_shapes=None) return (self._get_value_for_matching_key(loss_dict, 'Loss/localization_loss'), self._get_value_for_matching_key( loss_dict, 'Loss/classification_loss')) batch_size = 3 preprocessed_input = np.random.rand(batch_size, 2, 2, 3).astype(np.float32) groundtruth_boxes1 = np.array([[0, 0, .5, .5]], dtype=np.float32) groundtruth_boxes2 = np.array([[0, 0, .5, .5]], dtype=np.float32) groundtruth_boxes3 = np.array([[0, 0, .5, .5]], dtype=np.float32) groundtruth_classes1 = np.array([[1]], dtype=np.float32) groundtruth_classes2 = np.array([[1]], dtype=np.float32) groundtruth_classes3 = np.array([[1]], dtype=np.float32) expected_localization_loss = 0.0 # Note that we are subtracting 1 from batch_size, since the final image is # not annotated. expected_classification_loss = ((batch_size - 1) * num_anchors * (num_classes + 1) * np.log(2.0)) (localization_loss, classification_loss) = self.execute(graph_fn, [ preprocessed_input, groundtruth_boxes1, groundtruth_boxes2, groundtruth_boxes3, groundtruth_classes1, groundtruth_classes2, groundtruth_classes3 ], graph=g) self.assertAllClose(localization_loss, expected_localization_loss) self.assertAllClose(classification_loss, expected_classification_loss)
def test_postprocess_second_stage_only_inference_mode_with_shared_boxes( self): with test_utils.GraphContextOrNone() as g: model = self._build_model(is_training=False, number_of_stages=2, second_stage_batch_size=6) batch_size = 2 total_num_padded_proposals = batch_size * model.max_num_proposals def graph_fn(): proposal_boxes = tf.constant( [[[1, 1, 2, 3], [0, 0, 1, 1], [.5, .5, .6, .6], 4 * [0], 4 * [0], 4 * [0], 4 * [0], 4 * [0]], [[2, 3, 6, 8], [1, 2, 5, 3], 4 * [0], 4 * [0], 4 * [0], 4 * [0], 4 * [0], 4 * [0]]], dtype=tf.float32) num_proposals = tf.constant([3, 2], dtype=tf.int32) # This has 1 box instead of one for each class. refined_box_encodings = tf.zeros( [total_num_padded_proposals, 1, 4], dtype=tf.float32) class_predictions_with_background = tf.ones( [total_num_padded_proposals, model.num_classes + 1], dtype=tf.float32) image_shape = tf.constant([batch_size, 36, 48, 3], dtype=tf.int32) _, true_image_shapes = model.preprocess(tf.zeros(image_shape)) detections = model.postprocess( { 'refined_box_encodings': refined_box_encodings, 'class_predictions_with_background': class_predictions_with_background, 'num_proposals': num_proposals, 'proposal_boxes': proposal_boxes, 'image_shape': image_shape, }, true_image_shapes) return (detections['detection_boxes'], detections['detection_scores'], detections['detection_classes'], detections['num_detections']) (detection_boxes, detection_scores, detection_classes, num_detections) = self.execute_cpu(graph_fn, [], graph=g) self.assertAllEqual(detection_boxes.shape, [2, 5, 4]) self.assertAllClose(detection_scores, [[1, 1, 1, 1, 1], [1, 1, 1, 1, 0]]) self.assertAllClose(detection_classes, [[0, 0, 0, 1, 1], [0, 0, 1, 1, 0]]) self.assertAllClose(num_detections, [5, 4])
def test_predict_correct_shapes_in_inference_mode_three_stages_with_masks( self, masks_are_class_agnostic): batch_size = 2 image_size = 10 with test_utils.GraphContextOrNone() as g: model = self._build_model( is_training=False, number_of_stages=3, second_stage_batch_size=2, predict_masks=True, masks_are_class_agnostic=masks_are_class_agnostic) def graph_fn(): shape = [ tf.random_uniform([], minval=batch_size, maxval=batch_size + 1, dtype=tf.int32), tf.random_uniform([], minval=image_size, maxval=image_size + 1, dtype=tf.int32), tf.random_uniform([], minval=image_size, maxval=image_size + 1, dtype=tf.int32), 3 ] image = tf.zeros(shape) _, true_image_shapes = model.preprocess(image) detections = model.predict(image, true_image_shapes) return (detections['detection_boxes'], detections['detection_classes'], detections['detection_scores'], detections['num_detections'], detections['detection_masks'], detections['mask_predictions']) (detection_boxes, detection_scores, detection_classes, num_detections, detection_masks, mask_predictions) = self.execute_cpu(graph_fn, [], graph=g) self.assertAllEqual(detection_boxes.shape, [2, 5, 4]) self.assertAllEqual(detection_masks.shape, [2, 5, 14, 14]) self.assertAllEqual(detection_classes.shape, [2, 5]) self.assertAllEqual(detection_scores.shape, [2, 5]) self.assertAllEqual(num_detections.shape, [2]) num_classes = 1 if masks_are_class_agnostic else 2 self.assertAllEqual(mask_predictions.shape, [10, num_classes, 14, 14])
def test_preprocess_returns_correct_value_range(self): image_height = 128 image_width = 128 depth_multiplier = 1 pad_to_multiple = 1 test_image_np = np.random.rand(4, image_height, image_width, 3) with test_utils.GraphContextOrNone() as g: test_image = tf.constant(test_image_np) feature_extractor = self._create_feature_extractor( depth_multiplier, pad_to_multiple, use_keras=self.is_tf2()) def graph_fn(): preprocessed_image = feature_extractor.preprocess(test_image) return preprocessed_image preprocessed_image_out = self.execute(graph_fn, [], graph=g) self.assertAllClose(preprocessed_image_out, test_image_np - [[123.68, 116.779, 103.939]])
def test_predict_gives_correct_shapes_in_train_mode_both_stages_with_masks( self, masks_are_class_agnostic): with test_utils.GraphContextOrNone() as g: model = self._build_model( is_training=True, number_of_stages=3, second_stage_batch_size=7, predict_masks=True, masks_are_class_agnostic=masks_are_class_agnostic) batch_size = 2 image_size = 10 max_num_proposals = 7 def graph_fn(): image_shape = (batch_size, image_size, image_size, 3) preprocessed_inputs = tf.zeros(image_shape, dtype=tf.float32) groundtruth_boxes_list = [ tf.constant([[0, 0, .5, .5], [.5, .5, 1, 1]], dtype=tf.float32), tf.constant([[0, .5, .5, 1], [.5, 0, 1, .5]], dtype=tf.float32) ] groundtruth_classes_list = [ tf.constant([[1, 0], [0, 1]], dtype=tf.float32), tf.constant([[1, 0], [1, 0]], dtype=tf.float32) ] groundtruth_weights_list = [ tf.constant([1, 1], dtype=tf.float32), tf.constant([1, 1], dtype=tf.float32) ] _, true_image_shapes = model.preprocess(tf.zeros(image_shape)) model.provide_groundtruth( groundtruth_boxes_list, groundtruth_classes_list, groundtruth_weights_list=groundtruth_weights_list) result_tensor_dict = model.predict(preprocessed_inputs, true_image_shapes) return result_tensor_dict['mask_predictions'] mask_shape_1 = 1 if masks_are_class_agnostic else model._num_classes mask_out = self.execute_cpu(graph_fn, [], graph=g) self.assertAllEqual(mask_out.shape, (2 * max_num_proposals, mask_shape_1, 14, 14))
def test_loss_results_are_correct_with_random_example_sampling(self): with test_utils.GraphContextOrNone() as g: model, num_classes, _, _ = self._create_model( random_example_sampling=True) def graph_fn(preprocessed_tensor, groundtruth_boxes1, groundtruth_boxes2, groundtruth_classes1, groundtruth_classes2): groundtruth_boxes_list = [groundtruth_boxes1, groundtruth_boxes2] groundtruth_classes_list = [ groundtruth_classes1, groundtruth_classes2 ] model.provide_groundtruth(groundtruth_boxes_list, groundtruth_classes_list) prediction_dict = model.predict(preprocessed_tensor, true_image_shapes=None) loss_dict = model.loss(prediction_dict, true_image_shapes=None) return (self._get_value_for_matching_key(loss_dict, 'Loss/localization_loss'), self._get_value_for_matching_key( loss_dict, 'Loss/classification_loss')) batch_size = 2 preprocessed_input = np.random.rand(batch_size, 2, 2, 3).astype(np.float32) groundtruth_boxes1 = np.array([[0, 0, .5, .5]], dtype=np.float32) groundtruth_boxes2 = np.array([[0, 0, .5, .5]], dtype=np.float32) groundtruth_classes1 = np.array([[1]], dtype=np.float32) groundtruth_classes2 = np.array([[1]], dtype=np.float32) expected_localization_loss = 0.0 # Among 4 anchors (1 positive, 3 negative) in this test, only 2 anchors are # selected (1 positive, 1 negative) since random sampler will adjust number # of negative examples to make sure positive example fraction in the batch # is 0.5. expected_classification_loss = (batch_size * 2 * (num_classes + 1) * np.log(2.0)) (localization_loss, classification_loss) = self.execute_cpu(graph_fn, [ preprocessed_input, groundtruth_boxes1, groundtruth_boxes2, groundtruth_classes1, groundtruth_classes2 ], graph=g) self.assertAllClose(localization_loss, expected_localization_loss) self.assertAllClose(classification_loss, expected_classification_loss)
def test_loss_results_are_correct(self): with test_utils.GraphContextOrNone() as g: model, num_classes, num_anchors, _ = self._create_model( apply_hard_mining=False) def graph_fn(preprocessed_tensor, groundtruth_boxes1, groundtruth_boxes2, groundtruth_classes1, groundtruth_classes2): groundtruth_boxes_list = [groundtruth_boxes1, groundtruth_boxes2] groundtruth_classes_list = [ groundtruth_classes1, groundtruth_classes2 ] model.provide_groundtruth(groundtruth_boxes_list, groundtruth_classes_list) prediction_dict = model.predict(preprocessed_tensor, true_image_shapes=None) loss_dict = model.loss(prediction_dict, true_image_shapes=None) return (self._get_value_for_matching_key(loss_dict, 'Loss/localization_loss'), self._get_value_for_matching_key( loss_dict, 'Loss/classification_loss')) batch_size = 2 preprocessed_input = np.random.rand(batch_size, 2, 2, 3).astype(np.float32) groundtruth_boxes1 = np.array([[0, 0, .5, .5]], dtype=np.float32) groundtruth_boxes2 = np.array([[0, 0, .5, .5]], dtype=np.float32) groundtruth_classes1 = np.array([[1]], dtype=np.float32) groundtruth_classes2 = np.array([[1]], dtype=np.float32) (localization_loss, classification_loss) = self.execute(graph_fn, [ preprocessed_input, groundtruth_boxes1, groundtruth_boxes2, groundtruth_classes1, groundtruth_classes2 ], graph=g) expected_localization_loss = 0.0 expected_classification_loss = (batch_size * num_anchors * (num_classes + 1) * np.log(2.0)) self.assertAllClose(localization_loss, expected_localization_loss) self.assertAllClose(classification_loss, expected_classification_loss)
def check_extract_features_raises_error_with_invalid_image_size( self, image_height, image_width, depth_multiplier, pad_to_multiple, use_keras=False, use_depthwise=False): with test_utils.GraphContextOrNone() as g: batch = 4 width = tf.random.uniform([], minval=image_width, maxval=image_width + 1, dtype=tf.int32) height = tf.random.uniform([], minval=image_height, maxval=image_height + 1, dtype=tf.int32) shape = tf.stack([batch, height, width, 3]) preprocessed_inputs = tf.random.uniform(shape) feature_extractor = self._create_features( depth_multiplier, pad_to_multiple, use_keras=use_keras, use_depthwise=use_depthwise) def graph_fn(): feature_maps = self._extract_features(preprocessed_inputs, feature_extractor, use_keras=use_keras) return feature_maps if self.is_tf2(): with self.assertRaises(ValueError): self.execute_cpu(graph_fn, [], graph=g) else: with self.assertRaises(tf.errors.InvalidArgumentError): self.execute_cpu(graph_fn, [], graph=g)
def check_extract_features_returns_correct_shapes_with_dynamic_inputs( self, batch_size, image_height, image_width, depth_multiplier, pad_to_multiple, expected_feature_map_shapes, use_explicit_padding=False, num_layers=6, use_keras=False, use_depthwise=False): with test_utils.GraphContextOrNone() as g: feature_extractor = self._create_features( depth_multiplier, pad_to_multiple, use_explicit_padding=use_explicit_padding, num_layers=num_layers, use_keras=use_keras, use_depthwise=use_depthwise) def graph_fn(image_height, image_width): image_tensor = tf.random_uniform( [batch_size, image_height, image_width, 3], dtype=tf.float32) return self._extract_features(image_tensor, feature_extractor, use_keras=use_keras) feature_maps = self.execute_cpu(graph_fn, [ np.array(image_height, dtype=np.int32), np.array(image_width, dtype=np.int32) ], graph=g) for feature_map, expected_shape in zip(feature_maps, expected_feature_map_shapes): self.assertAllEqual(feature_map.shape, expected_shape)
def test_raw_detection_boxes_agree_predict_postprocess(self): with test_utils.GraphContextOrNone() as g: model, _, _, _ = self._create_model( return_raw_detections_during_predict=True) def graph_fn(): size = tf.random.uniform([], minval=2, maxval=3, dtype=tf.int32) batch = tf.random.uniform([], minval=2, maxval=3, dtype=tf.int32) shape = tf.stack([batch, size, size, 3]) image = tf.random.uniform(shape) preprocessed_inputs, true_image_shapes = model.preprocess(image) prediction_dict = model.predict(preprocessed_inputs, true_image_shapes) raw_detection_boxes_predict = prediction_dict[ 'raw_detection_boxes'] detections = model.postprocess(prediction_dict, true_image_shapes) raw_detection_boxes_postprocess = detections['raw_detection_boxes'] return raw_detection_boxes_predict, raw_detection_boxes_postprocess (raw_detection_boxes_predict_out, raw_detection_boxes_postprocess_out) = self.execute_cpu(graph_fn, [], graph=g) self.assertAllEqual(raw_detection_boxes_predict_out, raw_detection_boxes_postprocess_out)
def test_postprocess_third_stage_only_inference_mode(self): batch_size = 2 initial_crop_size = 3 maxpool_stride = 1 height = initial_crop_size // maxpool_stride width = initial_crop_size // maxpool_stride depth = 3 with test_utils.GraphContextOrNone() as g: model = self._build_model( is_training=False, number_of_stages=3, second_stage_batch_size=6, predict_masks=True) total_num_padded_proposals = batch_size * model.max_num_proposals def graph_fn(images_shape, num_proposals, proposal_boxes, refined_box_encodings, class_predictions_with_background): _, true_image_shapes = model.preprocess( tf.zeros(images_shape)) detections = model.postprocess({ 'refined_box_encodings': refined_box_encodings, 'class_predictions_with_background': class_predictions_with_background, 'num_proposals': num_proposals, 'proposal_boxes': proposal_boxes, 'image_shape': images_shape, 'detection_boxes': tf.zeros([2, 5, 4]), 'detection_masks': tf.zeros([2, 5, 14, 14]), 'detection_scores': tf.zeros([2, 5]), 'detection_classes': tf.zeros([2, 5]), 'num_detections': tf.zeros([2]), 'detection_features': tf.zeros([2, 5, width, height, depth]) }, true_image_shapes) return (detections['detection_boxes'], detections['detection_masks'], detections['detection_scores'], detections['detection_classes'], detections['num_detections'], detections['detection_features']) images_shape = np.array((2, 36, 48, 3), dtype=np.int32) proposal_boxes = np.array( [[[1, 1, 2, 3], [0, 0, 1, 1], [.5, .5, .6, .6], 4*[0], 4*[0], 4*[0], 4*[0], 4*[0]], [[2, 3, 6, 8], [1, 2, 5, 3], 4*[0], 4*[0], 4*[0], 4*[0], 4*[0], 4*[0]]]) num_proposals = np.array([3, 2], dtype=np.int32) refined_box_encodings = np.zeros( [total_num_padded_proposals, model.num_classes, 4]) class_predictions_with_background = np.ones( [total_num_padded_proposals, model.num_classes+1]) (detection_boxes, detection_masks, detection_scores, detection_classes, num_detections, detection_features) = self.execute_cpu(graph_fn, [images_shape, num_proposals, proposal_boxes, refined_box_encodings, class_predictions_with_background], graph=g) self.assertAllEqual(detection_boxes.shape, [2, 5, 4]) self.assertAllEqual(detection_masks.shape, [2, 5, 14, 14]) self.assertAllClose(detection_scores.shape, [2, 5]) self.assertAllClose(detection_classes.shape, [2, 5]) self.assertAllClose(num_detections.shape, [2]) self.assertTrue(np.amax(detection_masks <= 1.0)) self.assertTrue(np.amin(detection_masks >= 0.0)) self.assertAllEqual(detection_features.shape, [2, 5, width, height, depth]) self.assertGreaterEqual(np.amax(detection_features), 0)
def test_output_final_box_features(self): with test_utils.GraphContextOrNone() as g: model = self._build_model( is_training=False, number_of_stages=2, second_stage_batch_size=6, output_final_box_features=True) batch_size = 2 total_num_padded_proposals = batch_size * model.max_num_proposals def graph_fn(): proposal_boxes = tf.constant([[[1, 1, 2, 3], [0, 0, 1, 1], [.5, .5, .6, .6], 4 * [0], 4 * [0], 4 * [0], 4 * [0], 4 * [0]], [[2, 3, 6, 8], [1, 2, 5, 3], 4 * [0], 4 * [0], 4 * [0], 4 * [0], 4 * [0], 4 * [0]]], dtype=tf.float32) num_proposals = tf.constant([3, 2], dtype=tf.int32) refined_box_encodings = tf.zeros( [total_num_padded_proposals, model.num_classes, 4], dtype=tf.float32) class_predictions_with_background = tf.ones( [total_num_padded_proposals, model.num_classes + 1], dtype=tf.float32) image_shape = tf.constant([batch_size, 36, 48, 3], dtype=tf.int32) mask_height = 2 mask_width = 2 mask_predictions = 30. * tf.ones([ total_num_padded_proposals, model.num_classes, mask_height, mask_width ], dtype=tf.float32) _, true_image_shapes = model.preprocess(tf.zeros(image_shape)) rpn_features_to_crop = tf.ones((batch_size, mask_height, mask_width, 3), tf.float32) detections = model.postprocess( { 'refined_box_encodings': refined_box_encodings, 'class_predictions_with_background': class_predictions_with_background, 'num_proposals': num_proposals, 'proposal_boxes': proposal_boxes, 'image_shape': image_shape, 'mask_predictions': mask_predictions, 'rpn_features_to_crop': [rpn_features_to_crop] }, true_image_shapes) self.assertIn('detection_features', detections) return (detections['detection_boxes'], detections['detection_scores'], detections['detection_classes'], detections['num_detections'], detections['detection_masks']) (detection_boxes, detection_scores, detection_classes, num_detections, detection_masks) = self.execute_cpu(graph_fn, [], graph=g) exp_detection_masks = np.array([[[[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]]], [[[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [[0, 0], [0, 0]]]]) self.assertAllEqual(detection_boxes.shape, [2, 5, 4]) self.assertAllClose(detection_scores, [[1, 1, 1, 1, 1], [1, 1, 1, 1, 0]]) self.assertAllClose(detection_classes, [[0, 0, 0, 1, 1], [0, 0, 1, 1, 0]]) self.assertAllClose(num_detections, [5, 4]) self.assertAllClose(detection_masks, exp_detection_masks)
def test_get_expected_variable_names_with_depthwise( self, use_native_resize_op): with test_utils.GraphContextOrNone() as g: image_features = [ ('block2', tf.random_uniform([4, 8, 8, 256], dtype=tf.float32)), ('block3', tf.random_uniform([4, 4, 4, 256], dtype=tf.float32)), ('block4', tf.random_uniform([4, 2, 2, 256], dtype=tf.float32)), ('block5', tf.random_uniform([4, 1, 1, 256], dtype=tf.float32)) ] feature_map_generator = self._build_feature_map_generator( image_features=image_features, depth=128, use_depthwise=True, use_native_resize_op=use_native_resize_op) def graph_fn(): return feature_map_generator(image_features) self.execute(graph_fn, [], g) expected_slim_variables = set([ 'projection_1/weights', 'projection_1/biases', 'projection_2/weights', 'projection_2/biases', 'projection_3/weights', 'projection_3/biases', 'projection_4/weights', 'projection_4/biases', 'smoothing_1/depthwise_weights', 'smoothing_1/pointwise_weights', 'smoothing_1/biases', 'smoothing_2/depthwise_weights', 'smoothing_2/pointwise_weights', 'smoothing_2/biases', 'smoothing_3/depthwise_weights', 'smoothing_3/pointwise_weights', 'smoothing_3/biases', ]) expected_keras_variables = set([ 'FeatureMaps/top_down/projection_1/kernel', 'FeatureMaps/top_down/projection_1/bias', 'FeatureMaps/top_down/projection_2/kernel', 'FeatureMaps/top_down/projection_2/bias', 'FeatureMaps/top_down/projection_3/kernel', 'FeatureMaps/top_down/projection_3/bias', 'FeatureMaps/top_down/projection_4/kernel', 'FeatureMaps/top_down/projection_4/bias', 'FeatureMaps/top_down/smoothing_1_depthwise_conv/depthwise_kernel', 'FeatureMaps/top_down/smoothing_1_depthwise_conv/pointwise_kernel', 'FeatureMaps/top_down/smoothing_1_depthwise_conv/bias', 'FeatureMaps/top_down/smoothing_2_depthwise_conv/depthwise_kernel', 'FeatureMaps/top_down/smoothing_2_depthwise_conv/pointwise_kernel', 'FeatureMaps/top_down/smoothing_2_depthwise_conv/bias', 'FeatureMaps/top_down/smoothing_3_depthwise_conv/depthwise_kernel', 'FeatureMaps/top_down/smoothing_3_depthwise_conv/pointwise_kernel', 'FeatureMaps/top_down/smoothing_3_depthwise_conv/bias' ]) if tf_version.is_tf2(): actual_variable_set = set([ var.name.split(':')[0] for var in feature_map_generator.variables ]) self.assertSetEqual(expected_keras_variables, actual_variable_set) else: with g.as_default(): actual_variable_set = set( [var.op.name for var in tf.trainable_variables()]) self.assertSetEqual(expected_slim_variables, actual_variable_set)
def test_postprocess_results_are_correct(self): with test_utils.GraphContextOrNone() as g: model, _, _, _ = self._create_model() def graph_fn(): size = tf.random.uniform([], minval=2, maxval=3, dtype=tf.int32) batch = tf.random.uniform([], minval=2, maxval=3, dtype=tf.int32) shape = tf.stack([batch, size, size, 3]) image = tf.random.uniform(shape) preprocessed_inputs, true_image_shapes = model.preprocess(image) prediction_dict = model.predict(preprocessed_inputs, true_image_shapes) detections = model.postprocess(prediction_dict, true_image_shapes) return [ batch, detections['detection_boxes'], detections['detection_scores'], detections['detection_classes'], detections['detection_multiclass_scores'], detections['num_detections'], detections['raw_detection_boxes'], detections['raw_detection_scores'], detections['detection_anchor_indices'] ] expected_boxes = [ [ [0, 0, .5, .5], [0, .5, .5, 1], [.5, 0, 1, .5], [0, 0, 0, 0], # pruned prediction [0, 0, 0, 0] ], # padding [ [0, 0, .5, .5], [0, .5, .5, 1], [.5, 0, 1, .5], [0, 0, 0, 0], # pruned prediction [0, 0, 0, 0] ] ] # padding expected_scores = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]] expected_multiclass_scores = [[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]]] expected_classes = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]] expected_num_detections = np.array([3, 3]) expected_raw_detection_boxes = [[[0., 0., 0.5, 0.5], [0., 0.5, 0.5, 1.], [0.5, 0., 1., 0.5], [1., 1., 1.5, 1.5]], [[0., 0., 0.5, 0.5], [0., 0.5, 0.5, 1.], [0.5, 0., 1., 0.5], [1., 1., 1.5, 1.5]]] expected_raw_detection_scores = [[[0, 0], [0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0], [0, 0]]] expected_detection_anchor_indices = [[0, 1, 2], [0, 1, 2]] (batch, detection_boxes, detection_scores, detection_classes, detection_multiclass_scores, num_detections, raw_detection_boxes, raw_detection_scores, detection_anchor_indices) = self.execute_cpu(graph_fn, [], graph=g) for image_idx in range(batch): self.assertTrue( test_utils.first_rows_close_as_set( detection_boxes[image_idx].tolist(), expected_boxes[image_idx])) self.assertSameElements( detection_anchor_indices[image_idx], expected_detection_anchor_indices[image_idx]) self.assertAllClose(detection_scores, expected_scores) self.assertAllClose(detection_classes, expected_classes) self.assertAllClose(detection_multiclass_scores, expected_multiclass_scores) self.assertAllClose(num_detections, expected_num_detections) self.assertAllEqual(raw_detection_boxes, expected_raw_detection_boxes) self.assertAllEqual(raw_detection_scores, expected_raw_detection_scores)