def test_matcher_low_quality_matcher_when_the_best_box_is_undefined(): num_valid_boxes = np.array([[4], [3]], np.int32) similarity = np.array([[ [0, 0.31, 0, 0, 0], [0.1, 0, 0, 0, 0], [0, 0, 0.32, 0, 0], [0, 0, 0, 0, 0.48], ], [ [1, 0.3, 1, 3, 0], [8, 0.4, 2, 0, 0.2], [0, -1, 0.2, 0.1, 0.39], [0, 0, 0, 0, 0.31], ]]) # yapf: disable expected_matched = np.array([[1, 0, 2, 0, 3], [1, 1, 1, 0, 2]]) matcher = Matcher([0.3, 0.5], [0, -1, 1], allow_low_quality_matches=False) matches, match_labels = matcher(similarity, num_valid_boxes) expected_matched_labels = np.array([[0, -1, -1, 0, -1], [1, -1, 1, 1, -1]]) np.testing.assert_array_equal(matches, expected_matched) np.testing.assert_array_equal(match_labels, expected_matched_labels) matcher = Matcher([0.3, 0.5], [0, -1, 1], allow_low_quality_matches=True) matches, match_labels = matcher(similarity, num_valid_boxes) # Explanation expactation for batch[0] # 0 -> 1 because anchor 0 has the highest IoU with gt 1 so it becomes a low quality match # -1 -> 1 because anchor 1 has the highest IoU with gt 0 => low quality match # -1 -> 1 because anchor 2 has the highest IoU with gt 2 => low quality match # 0 = 0 because anchor 3 isn't close enough to any groundtruths # -1 -> 1 because anchor 4 has the highest IoU with gt 3 => low quality match expected_matched_labels = np.array([[1, 1, 1, 0, 1], [1, -1, 1, 1, 1]]) np.testing.assert_array_equal(matches, expected_matched) np.testing.assert_array_equal(match_labels, expected_matched_labels)
def __init__(self, anchor_ratios=(0.5, 1, 2), **kwargs): super().__init__( 2, SparseCategoricalCrossentropy(reduction=tf.keras.losses.Reduction.NONE, from_logits=True), L1Loss(reduction=tf.keras.losses.Reduction.NONE), multiples=len(anchor_ratios), kernel_initializer_classification_head=initializers.RandomNormal(stddev=0.01), kernel_initializer_box_prediction_head=initializers.RandomNormal(stddev=0.01), **kwargs) #Force each ground_truths to match to at least one anchor matcher = Matcher([0.3, 0.7], [0, -1, 1], allow_low_quality_matches=True) self.target_assigner = TargetAssigner(IoUSimilarity(), matcher, encode_boxes_faster_rcnn, dtype=self._compute_dtype) anchor_strides = (4, 8, 16, 32, 64) anchor_zises = (32, 64, 128, 256, 512) self._anchor_ratios = anchor_ratios # Precompute a deterministic grid of anchors for each layer of the pyramid. # We will extract a subpart of the anchors according to self._anchors = [ Anchors(stride, size, self._anchor_ratios) for stride, size in zip(anchor_strides, anchor_zises) ]
def test_matcher_low_quality_matcher(): num_valid_boxes = np.array([[3], [3]], np.int32) similarity = np.array([[ [0, 0.2, 0.49, 0.1, 0.3], [2, -1, 0.2, 4, 0.38], [1, 0.25, 0.3, 5, 0.37], [0, 0, 0, 0, 0.50], # This line is not valid and should be discarded (num_valid_boxes = 3) ], [ [1, 0.3, 1, 3, 0], [8, 0.4, 2, 0, 0.2], [0, -1, 0.2, 0.1, 0.39], [0, 0, 0, 0, 0], # This line is not valid and should be discarded (num_valid_boxes = 3) ]]) # yapf: disable matcher = Matcher([0.3, 0.5], [0, -1, 1], allow_low_quality_matches=True) matches, match_labels = matcher(similarity, num_valid_boxes) expected_matched = np.array([[1, 2, 0, 2, 3], [1, 1, 1, 0, 2]]) # if allow_low_quality_matches was False # [[1, 0, -1, 1, -1], [1, -1, 1, 1, 0]] expected_matched_labels = np.array([[1, 0, 1, 1, -1], [1, -1, 1, 1, 1]]) np.testing.assert_array_equal(matches, expected_matched) np.testing.assert_array_equal(match_labels, expected_matched_labels)
def test_matcher_low_quality_matcher_with_one_ground_truth(): num_valid_boxes = np.array([[1]], np.int32) similarity = np.array([[ [0, 0.31, 0, 0, 0], ]]) expected_matched = np.array([[0, 0, 0, 0, 0]]) matcher = Matcher([0.3, 0.5], [0, -1, 1], allow_low_quality_matches=False) matches, match_labels = matcher(similarity, num_valid_boxes) expected_matched_labels = np.array([[0, -1, 0, 0, 0]]) assert match_labels.shape == (1, 5) np.testing.assert_array_equal(matches, expected_matched) np.testing.assert_array_equal(match_labels, expected_matched_labels) matcher = Matcher([0.3, 0.5], [0, -1, 1], allow_low_quality_matches=True) matches, match_labels = matcher(similarity, num_valid_boxes) expected_matched_labels = np.array([[0, 1, 0, 0, 0]]) assert match_labels.shape == (1, 5) np.testing.assert_array_equal(matches, expected_matched) np.testing.assert_array_equal(match_labels, expected_matched_labels)
def test_batch_assign_multiclass_targets_with_padded_groundtruth(): similarity_calc = IoUSimilarity() matcher = Matcher([0.5], [0, 1]) box_coder = encode_mean_stddev target_assigner = targetassigner.TargetAssigner(similarity_calc, matcher, box_coder) groundtruth_boxes = np.array([ [[0., 0., 0.2, 0.2], [0., 0., 0., 0.], [0, 0, 0, 0]], [[0, 0.25123152, 1, 1], [0.015789, 0.0985, 0.55789, 0.3842], [0, 0, 0, 0]], ], dtype=np.float32) groundtruth_weights = np.array([[1, 0, 0], [1, 1, 0]], dtype=np.float32) num_boxes = np.array([[2], [3]], np.int32) class_targets = np.array([[1, 0, 0], [3, 2, 0]], dtype=np.float32) anchor_means = np.array([[ [0, 0, .25, .25], [0, .25, 1, 1], [0, .1, .5, .5], [.75, .75, 1, 1] ], [[0, 0, .25, .25], [0, .25, 1, 1], [0, .1, .5, .5], [.75, .75, 1, 1]]], dtype=np.float32) exp_cls_targets = [[1, 0, 0, 0], [0, 3, 2, 0]] exp_cls_weights = [[1, 1, 1, 1], [1, 1, 1, 1]] exp_reg_targets = [[[0, 0, -0.5, -0.5], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0.01231521, 0, 0], [0.15789001, -0.01500003, 0.57889998, -1.15799987], [0, 0, 0, 0]]] exp_reg_weights = [[1, 0, 0, 0], [0, 1, 1, 0]] gt_box_batch = { BoxField.BOXES: groundtruth_boxes, BoxField.LABELS: class_targets, BoxField.WEIGHTS: groundtruth_weights, BoxField.NUM_BOXES: num_boxes } targets, weights = target_assigner.assign({BoxField.BOXES: anchor_means}, gt_box_batch) cls_targets = targets[BoxField.LABELS] cls_weights = weights[BoxField.LABELS] reg_targets = targets[BoxField.BOXES] reg_weights = weights[BoxField.BOXES] np.testing.assert_array_almost_equal(cls_targets, exp_cls_targets) np.testing.assert_array_almost_equal(cls_weights, exp_cls_weights) np.testing.assert_array_almost_equal(reg_targets, exp_reg_targets) np.testing.assert_array_almost_equal(reg_weights, exp_reg_weights)
def test_matcher(): similarity = np.array([ [[1., 1, 1, 3, 1], [2, -1, 2, 0, 4]], [[1., 0.1, 1, 3, 0], [8, 0.4, 2, 0, 0.2]], ]) num_valid_boxes = np.array([[2], [2]], np.int32) matcher = Matcher([0.3, 0.5], [0, -1, 1]) matches, match_labels = matcher(similarity, num_valid_boxes) expected_matched = np.array([[1, 0, 1, 0, 1], [1, 1, 1, 0, 1]]) expected_matched_labels = np.array([[1, 1, 1, 1, 1], [1, -1, 1, 1, 0]]) np.testing.assert_array_equal(matches, expected_matched) np.testing.assert_array_equal(match_labels, expected_matched_labels)
def test_assign_multiclass_with_groundtruth_weights(): similarity_calc = IoUSimilarity() matcher = Matcher([0.5], [0, 1]) box_coder = encode_mean_stddev target_assigner = targetassigner.TargetAssigner(similarity_calc, matcher, box_coder) anchor_means = np.array([[[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]], [[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]]], dtype=np.float32) groundtruth_boxes = np.array( [[[0.0, 0.0, 0.5, 0.5], [0.5, 0.5, 0.9, 0.9], [.75, 0, .95, .27]], [[0.0, 0.0, 0.5, 0.5], [0.5, 0.5, 0.9, 0.9], [.75, 0, .95, .27]]], dtype=np.float32) groundtruth_labels = np.array([[1, 5, 3], [1, 5, 3]], dtype=np.float32) groundtruth_weights = np.array([[0.3, 0., 0.5], [0.3, 0., 0.5]], dtype=np.float32) num_boxes = np.array([[3], [3]], np.int32) # background class gets weight of 1. exp_cls_weights = [[0.3, 0., 1, 0.5], [0.3, 0., 1, 0.5]] exp_reg_weights = [[0.3, 0., 0., 0.5], [0.3, 0., 0., 0.5]] # background class gets weight of 0. gt_box_batch = { BoxField.BOXES: groundtruth_boxes, BoxField.LABELS: groundtruth_labels, BoxField.WEIGHTS: groundtruth_weights, BoxField.NUM_BOXES: num_boxes } targets, weights = target_assigner.assign({BoxField.BOXES: anchor_means}, gt_box_batch) cls_targets = targets[BoxField.LABELS] cls_weights = weights[BoxField.LABELS] reg_targets = targets[BoxField.BOXES] reg_weights = weights[BoxField.BOXES] np.testing.assert_array_almost_equal(cls_weights, exp_cls_weights) np.testing.assert_array_almost_equal(reg_weights, exp_reg_weights)
def __init__(self, num_classes, **kwargs): super().__init__( num_classes, SparseCategoricalCrossentropy( reduction=tf.keras.losses.Reduction.NONE, from_logits=True), L1Loss(reduction=tf.keras.losses.Reduction.NONE ), # like in tensorpack kernel_initializer_classification_head=initializers.RandomNormal( stddev=0.01), kernel_initializer_box_prediction_head=initializers.RandomNormal( stddev=0.001), **kwargs) matcher = Matcher([0.5], [0, 1]) # The same scale_factors is used in decoding as well encode = functools.partial(encode_boxes_faster_rcnn, scale_factors=(10.0, 10.0, 5.0, 5.0)) self.target_assigner = TargetAssigner(IoUSimilarity(), matcher, encode, dtype=self._compute_dtype)