def test_raises_error_on_incompatible_groundtruth_boxes_and_labels(self): similarity_calc = region_similarity_calculator.NegSqDistSimilarity() matcher = bipartite_matcher.GreedyBipartiteMatcher() box_coder = mean_stddev_box_coder.MeanStddevBoxCoder() unmatched_cls_target = tf.constant([1, 0, 0, 0, 0, 0, 0], tf.float32) target_assigner = targetassigner.TargetAssigner( similarity_calc, matcher, box_coder, unmatched_cls_target=unmatched_cls_target) prior_means = tf.constant([[0.0, 0.0, 0.5, 0.5], [0.5, 0.5, 1.0, 0.8], [0, 0.5, .5, 1.0], [.75, 0, 1.0, .25]]) priors = box_list.BoxList(prior_means) box_corners = [[0.0, 0.0, 0.5, 0.5], [0.0, 0.0, 0.5, 0.8], [0.5, 0.5, 0.9, 0.9], [.75, 0, .95, .27]] boxes = box_list.BoxList(tf.constant(box_corners)) groundtruth_labels = tf.constant([[0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 1, 0, 0, 0]], tf.float32) with self.assertRaisesRegexp(ValueError, 'Unequal shapes'): target_assigner.assign(priors, boxes, groundtruth_labels, num_valid_rows=3)
def build(matcher_config): """Builds a matcher object based on the matcher config. Args: matcher_config: A matcher.proto object containing the config for the desired Matcher. Returns: Matcher based on the config. Raises: ValueError: On empty matcher proto. """ if not isinstance(matcher_config, matcher_pb2.Matcher): raise ValueError('matcher_config not of type matcher_pb2.Matcher.') if matcher_config.WhichOneof('matcher_oneof') == 'argmax_matcher': matcher = matcher_config.argmax_matcher matched_threshold = unmatched_threshold = None if not matcher.ignore_thresholds: matched_threshold = matcher.matched_threshold unmatched_threshold = matcher.unmatched_threshold return argmax_matcher.ArgMaxMatcher( matched_threshold=matched_threshold, unmatched_threshold=unmatched_threshold, negatives_lower_than_unmatched=matcher. negatives_lower_than_unmatched, force_match_for_each_row=matcher.force_match_for_each_row) if matcher_config.WhichOneof('matcher_oneof') == 'bipartite_matcher': return bipartite_matcher.GreedyBipartiteMatcher() raise ValueError('Empty matcher.')
def test_assign_multiclass_unequal_class_weights(self): similarity_calc = region_similarity_calculator.NegSqDistSimilarity() matcher = bipartite_matcher.GreedyBipartiteMatcher() box_coder = mean_stddev_box_coder.MeanStddevBoxCoder() unmatched_cls_target = tf.constant([1, 0, 0, 0, 0, 0, 0], tf.float32) target_assigner = targetassigner.TargetAssigner( similarity_calc, matcher, box_coder, positive_class_weight=1.0, negative_class_weight=0.5, unmatched_cls_target=unmatched_cls_target) prior_means = tf.constant([[0.0, 0.0, 0.5, 0.5], [0.5, 0.5, 1.0, 0.8], [0, 0.5, .5, 1.0], [.75, 0, 1.0, .25]]) prior_stddevs = tf.constant(4 * [4 * [.1]]) priors = box_list.BoxList(prior_means) priors.add_field('stddev', prior_stddevs) box_corners = [[0.0, 0.0, 0.5, 0.5], [0.5, 0.5, 0.9, 0.9], [.75, 0, .95, .27]] boxes = box_list.BoxList(tf.constant(box_corners)) groundtruth_labels = tf.constant([[0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 1, 0, 0, 0]], tf.float32) exp_cls_weights = [1, 1, .5, 1] result = target_assigner.assign(priors, boxes, groundtruth_labels, num_valid_rows=3) (_, cls_weights, _, _, _) = result with self.test_session() as sess: cls_weights_out = sess.run(cls_weights) self.assertAllClose(cls_weights_out, exp_cls_weights)
def test_raises_error_on_incompatible_groundtruth_boxes_and_labels(self): similarity_calc = region_similarity_calculator.NegSqDistSimilarity() matcher = bipartite_matcher.GreedyBipartiteMatcher() box_coder = mean_stddev_box_coder.MeanStddevBoxCoder() unmatched_cls_target = tf.constant([1, 0, 0, 0, 0, 0, 0], tf.float32) target_assigner = targetassigner.TargetAssigner( similarity_calc, matcher, box_coder, unmatched_cls_target=unmatched_cls_target) prior_means = tf.constant([[0.0, 0.0, 0.5, 0.5], [0.5, 0.5, 1.0, 0.8], [0, 0.5, .5, 1.0], [.75, 0, 1.0, .25]]) prior_stddevs = tf.constant(4 * [4 * [.1]]) priors = box_list.BoxList(prior_means) priors.add_field('stddev', prior_stddevs) box_corners = [[0.0, 0.0, 0.5, 0.5], [0.0, 0.0, 0.5, 0.8], [0.5, 0.5, 0.9, 0.9], [.75, 0, .95, .27]] boxes = box_list.BoxList(tf.constant(box_corners)) groundtruth_labels = tf.constant( [[0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 1, 0, 0, 0]], tf.float32) result = target_assigner.assign(priors, boxes, groundtruth_labels, num_valid_rows=3) (cls_targets, cls_weights, reg_targets, reg_weights, _) = result with self.test_session() as sess: with self.assertRaisesWithPredicateMatch( tf.errors.InvalidArgumentError, 'Groundtruth boxes and labels have incompatible shapes!'): sess.run([cls_targets, cls_weights, reg_targets, reg_weights])
def create_target_assigner(reference, stage=None, negative_class_weight=1.0, unmatched_cls_target=None): """Factory function for creating standard target assigners. Args: reference: string referencing the type of TargetAssigner. stage: string denoting stage: {proposal, detection}. negative_class_weight: classification weight to be associated to negative anchors (default: 1.0) unmatched_cls_target: a float32 tensor with shape [d_1, d_2, ..., d_k] which is consistent with the classification target for each anchor (and can be empty for scalar targets). This shape must thus be compatible with the groundtruth labels that are passed to the Assign function (which have shape [num_gt_boxes, d_1, d_2, ..., d_k]). If set to None, unmatched_cls_target is set to be 0 for each anchor. Returns: TargetAssigner: desired target assigner. Raises: ValueError: if combination reference+stage is invalid. """ if reference == 'Multibox' and stage == 'proposal': similarity_calc = sim_calc.NegSqDistSimilarity() matcher = bipartite_matcher.GreedyBipartiteMatcher() box_coder = mean_stddev_box_coder.MeanStddevBoxCoder() elif reference == 'FasterRCNN' and stage == 'proposal': similarity_calc = sim_calc.IouSimilarity() matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.7, unmatched_threshold=0.3, force_match_for_each_row=True) box_coder = faster_rcnn_box_coder.FasterRcnnBoxCoder( scale_factors=[10.0, 10.0, 5.0, 5.0]) elif reference == 'FasterRCNN' and stage == 'detection': similarity_calc = sim_calc.IouSimilarity() # Uses all proposals with IOU < 0.5 as candidate negatives. matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.5, negatives_lower_than_unmatched=True) box_coder = faster_rcnn_box_coder.FasterRcnnBoxCoder( scale_factors=[10.0, 10.0, 5.0, 5.0]) elif reference == 'FastRCNN': similarity_calc = sim_calc.IouSimilarity() matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.5, unmatched_threshold=0.1, force_match_for_each_row=False, negatives_lower_than_unmatched=False) box_coder = faster_rcnn_box_coder.FasterRcnnBoxCoder() else: raise ValueError('No valid combination of reference and stage.') return TargetAssigner(similarity_calc, matcher, box_coder, negative_class_weight=negative_class_weight, unmatched_cls_target=unmatched_cls_target)
def test_get_expected_matches_with_all_rows_be_default(self): similarity_matrix = tf.constant([[0.50, 0.1, 0.8], [0.15, 0.2, 0.3]]) expected_match_results = [-1, 1, 0] matcher = bipartite_matcher.GreedyBipartiteMatcher() match = matcher.match(similarity_matrix) with self.test_session() as sess: match_results_out = sess.run(match._match_results) self.assertAllEqual(match_results_out, expected_match_results)
def _get_agnostic_target_assigner(self): similarity_calc = region_similarity_calculator.NegSqDistSimilarity() matcher = bipartite_matcher.GreedyBipartiteMatcher() box_coder = mean_stddev_box_coder.MeanStddevBoxCoder() return targetassigner.TargetAssigner( similarity_calc, matcher, box_coder, positive_class_weight=1.0, negative_class_weight=1.0, unmatched_cls_target=None)
def test_assign_multidimensional_class_targets(self): similarity_calc = region_similarity_calculator.NegSqDistSimilarity() matcher = bipartite_matcher.GreedyBipartiteMatcher() box_coder = mean_stddev_box_coder.MeanStddevBoxCoder() unmatched_cls_target = tf.constant([[0, 0], [0, 0]], tf.float32) target_assigner = targetassigner.TargetAssigner( similarity_calc, matcher, box_coder, unmatched_cls_target=unmatched_cls_target) prior_means = tf.constant([[0.0, 0.0, 0.5, 0.5], [0.5, 0.5, 1.0, 0.8], [0, 0.5, .5, 1.0], [.75, 0, 1.0, .25]]) prior_stddevs = tf.constant(4 * [4 * [.1]]) priors = box_list.BoxList(prior_means) priors.add_field('stddev', prior_stddevs) box_corners = [[0.0, 0.0, 0.5, 0.5], [0.5, 0.5, 0.9, 0.9], [.75, 0, .95, .27]] boxes = box_list.BoxList(tf.constant(box_corners)) groundtruth_labels = tf.constant([[[0, 1], [1, 0]], [[1, 0], [0, 1]], [[0, 1], [1, .5]]], tf.float32) exp_cls_targets = [[[0, 1], [1, 0]], [[1, 0], [0, 1]], [[0, 0], [0, 0]], [[0, 1], [1, .5]]] exp_cls_weights = [1, 1, 1, 1] exp_reg_targets = [[0, 0, 0, 0], [0, 0, -1, 1], [0, 0, 0, 0], [0, 0, -.5, .2]] exp_reg_weights = [1, 1, 0, 1] exp_matching_anchors = [0, 1, 3] result = target_assigner.assign(priors, boxes, groundtruth_labels, num_valid_rows=3) (cls_targets, cls_weights, reg_targets, reg_weights, match) = result with self.test_session() as sess: (cls_targets_out, cls_weights_out, reg_targets_out, reg_weights_out, matching_anchors_out) = sess.run( [cls_targets, cls_weights, reg_targets, reg_weights, match.matched_column_indices()]) self.assertAllClose(cls_targets_out, exp_cls_targets) self.assertAllClose(cls_weights_out, exp_cls_weights) self.assertAllClose(reg_targets_out, exp_reg_targets) self.assertAllClose(reg_weights_out, exp_reg_weights) self.assertAllClose(matching_anchors_out, exp_matching_anchors) self.assertEquals(cls_targets_out.dtype, np.float32) self.assertEquals(cls_weights_out.dtype, np.float32) self.assertEquals(reg_targets_out.dtype, np.float32) self.assertEquals(reg_weights_out.dtype, np.float32) self.assertEquals(matching_anchors_out.dtype, np.int32)
def test_get_expected_matches_with_only_one_valid_row(self): similarity_matrix = tf.constant([[0.50, 0.1, 0.8], [0.15, 0.2, 0.3]]) num_valid_rows = 1 expected_match_results = [-1, -1, 0] matcher = bipartite_matcher.GreedyBipartiteMatcher() match = matcher.match(similarity_matrix, num_valid_rows=num_valid_rows) with self.test_session() as sess: match_results_out = sess.run(match._match_results) self.assertAllEqual(match_results_out, expected_match_results)
def test_get_expected_matches_with_only_one_valid_row_at_bottom(self): similarity_matrix = tf.constant([[0.15, 0.2, 0.3], [0.50, 0.1, 0.8]]) valid_rows = tf.constant([False, True], dtype=tf.bool) expected_match_results = [-1, -1, 0] matcher = bipartite_matcher.GreedyBipartiteMatcher() match = matcher.match(similarity_matrix, valid_rows) with self.test_session() as sess: match_results_out = sess.run(match._match_results) self.assertAllEqual(match_results_out, expected_match_results)
def test_get_no_matches_with_zero_valid_rows(self): similarity_matrix = tf.constant([[0.50, 0.1, 0.8], [0.15, 0.2, 0.3]]) valid_rows = tf.zeros([2], dtype=tf.bool) expected_match_results = [-1, -1, -1] matcher = bipartite_matcher.GreedyBipartiteMatcher() match = matcher.match(similarity_matrix, valid_rows) with self.test_session() as sess: match_results_out = sess.run(match._match_results) self.assertAllEqual(match_results_out, expected_match_results)
def _get_multi_class_target_assigner(self, num_classes): similarity_calc = region_similarity_calculator.NegSqDistSimilarity() matcher = bipartite_matcher.GreedyBipartiteMatcher() box_coder = mean_stddev_box_coder.MeanStddevBoxCoder() unmatched_cls_target = tf.constant([1] + num_classes * [0], tf.float32) return targetassigner.TargetAssigner( similarity_calc, matcher, box_coder, positive_class_weight=1.0, negative_class_weight=1.0, unmatched_cls_target=unmatched_cls_target)
def create_target_assigner(reference, stage=None, negative_class_weight=1.0, use_matmul_gather=False): """Factory function for creating standard target assigners. Args: reference: string referencing the type of TargetAssigner. stage: string denoting stage: {proposal, detection}. negative_class_weight: classification weight to be associated to negative anchors (default: 1.0) use_matmul_gather: whether to use matrix multiplication based gather which are better suited for TPUs. Returns: TargetAssigner: desired target assigner. Raises: ValueError: if combination reference+stage is invalid. """ if reference == 'Multibox' and stage == 'proposal': similarity_calc = sim_calc.NegSqDistSimilarity() matcher = bipartite_matcher.GreedyBipartiteMatcher() box_coder = mean_stddev_box_coder.MeanStddevBoxCoder() elif reference == 'FasterRCNN' and stage == 'proposal': similarity_calc = sim_calc.IouSimilarity() matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.7, unmatched_threshold=0.3, force_match_for_each_row=True, use_matmul_gather=use_matmul_gather) box_coder = faster_rcnn_box_coder.FasterRcnnBoxCoder( scale_factors=[10.0, 10.0, 5.0, 5.0]) elif reference == 'FasterRCNN' and stage == 'detection': similarity_calc = sim_calc.IouSimilarity() # Uses all proposals with IOU < 0.5 as candidate negatives. matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.5, negatives_lower_than_unmatched=True, use_matmul_gather=use_matmul_gather) box_coder = faster_rcnn_box_coder.FasterRcnnBoxCoder( scale_factors=[10.0, 10.0, 5.0, 5.0]) elif reference == 'FastRCNN': similarity_calc = sim_calc.IouSimilarity() matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.5, unmatched_threshold=0.1, force_match_for_each_row=False, negatives_lower_than_unmatched=False, use_matmul_gather=use_matmul_gather) box_coder = faster_rcnn_box_coder.FasterRcnnBoxCoder() else: raise ValueError('No valid combination of reference and stage.') return TargetAssigner(similarity_calc, matcher, box_coder, negative_class_weight=negative_class_weight)
def test_raises_error_on_invalid_groundtruth_labels(self): similarity_calc = region_similarity_calculator.NegSqDistSimilarity() matcher = bipartite_matcher.GreedyBipartiteMatcher() box_coder = mean_stddev_box_coder.MeanStddevBoxCoder(stddev=1.0) unmatched_class_label = tf.constant([[0, 0], [0, 0], [0, 0]], tf.float32) target_assigner = targetassigner.TargetAssigner( similarity_calc, matcher, box_coder) prior_means = tf.constant([[0.0, 0.0, 0.5, 0.5]]) priors = box_list.BoxList(prior_means) box_corners = [[0.0, 0.0, 0.5, 0.5], [0.5, 0.5, 0.9, 0.9], [.75, 0, .95, .27]] boxes = box_list.BoxList(tf.constant(box_corners)) groundtruth_labels = tf.constant([[[0, 1], [1, 0]]], tf.float32) with self.assertRaises(ValueError): target_assigner.assign(priors, boxes, groundtruth_labels, unmatched_class_label=unmatched_class_label)
def build(matcher_config): if not isinstance(matcher_config, matcher_pb2.Matcher): raise ValueError('matcher_config not of type matcher_pb2.Matcher.') if matcher_config.WhichOneof('matcher_oneof') == 'argmax_matcher': matcher = matcher_config.argmax_matcher matched_threshold = unmatched_threshold = None if not matcher.ignore_thresholds: matched_threshold = matcher.matched_threshold unmatched_threshold = matcher.unmatched_threshold return argmax_matcher.ArgMaxMatcher( matched_threshold=matched_threshold, unmatched_threshold=unmatched_threshold, negatives_lower_than_unmatched=matcher. negatives_lower_than_unmatched, force_match_for_each_row=matcher.force_match_for_each_row, use_matmul_gather=matcher.use_matmul_gather) if matcher_config.WhichOneof('matcher_oneof') == 'bipartite_matcher': matcher = matcher_config.bipartite_matcher return bipartite_matcher.GreedyBipartiteMatcher( matcher.use_matmul_gather) raise ValueError('Empty matcher.')
def graph_fn(similarity_matrix, valid_rows): matcher = bipartite_matcher.GreedyBipartiteMatcher() match = matcher.match(similarity_matrix, valid_rows=valid_rows) return match._match_results