deanna-emery's picture
updates
93528c6
raw
history blame
7.63 kB
# Copyright 2023 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Tests for anchor.py."""
# Import libraries
from absl.testing import parameterized
import numpy as np
import tensorflow as tf, tf_keras
from official.vision.ops import anchor
class AnchorTest(parameterized.TestCase, tf.test.TestCase):
# The set of parameters are tailored for the MLPerf configuration, where
# the number of anchors is 495132, rpn_batch_size_per_im=256, and
# rpn_fg_fraction=0.5.
@parameterized.parameters(
(512, 25, 25, 25, 25, (512, 512)),
(512, 25, 25, 25, 25, (512, 640)),
(512, 25, 25, 25, 25, (640, 512)),
(495132, 100, 100, 100, 100, (512, 512)),
(495132, 200, 100, 128, 100, (512, 512)),
(495132, 100, 120, 100, 120, (512, 512)),
(495132, 100, 200, 100, 156, (512, 512)),
(495132, 200, 200, 128, 128, (512, 512)),
)
def testAnchorRpnSample(self, num_anchors, num_positives,
num_negatives, expected_positives,
expected_negatives, image_size):
match_results_np = np.empty([num_anchors])
match_results_np.fill(-2)
match_results_np[:num_positives] = 0
match_results_np[num_positives:num_positives + num_negatives] = -1
match_results = tf.convert_to_tensor(value=match_results_np, dtype=tf.int32)
anchor_labeler = anchor.RpnAnchorLabeler(
match_threshold=0.7,
unmatched_threshold=0.3,
rpn_batch_size_per_im=256,
rpn_fg_fraction=0.5)
rpn_sample_op = anchor_labeler._get_rpn_samples(match_results)
labels = [v.numpy() for v in rpn_sample_op]
self.assertLen(labels[0], num_anchors)
positives = np.sum(np.array(labels[0]) == 1)
negatives = np.sum(np.array(labels[0]) == 0)
self.assertEqual(positives, expected_positives)
self.assertEqual(negatives, expected_negatives)
@parameterized.parameters(
# Single scale anchor.
(5, 5, 1, [1.0], 2.0,
[[-16, -16, 48, 48], [-16, 16, 48, 80],
[16, -16, 80, 48], [16, 16, 80, 80]]),
# Multi scale anchor.
(5, 6, 1, [1.0], 2.0,
[[-16, -16, 48, 48], [-16, 16, 48, 80],
[16, -16, 80, 48], [16, 16, 80, 80], [-32, -32, 96, 96]]),
# # Multi aspect ratio anchor.
(6, 6, 1, [1.0, 4.0, 0.25], 2.0,
[[-32, -32, 96, 96], [-0, -96, 64, 160], [-96, -0, 160, 64]]),
)
def testAnchorGeneration(self, min_level, max_level, num_scales,
aspect_ratios, anchor_size, expected_boxes):
image_size = [64, 64]
anchors = anchor.Anchor(min_level, max_level, num_scales, aspect_ratios,
anchor_size, image_size)
boxes = anchors.boxes.numpy()
self.assertEqual(expected_boxes, boxes.tolist())
@parameterized.parameters(
# Single scale anchor.
(5, 5, 1, [1.0], 2.0,
[[-16, -16, 48, 48], [-16, 16, 48, 80],
[16, -16, 80, 48], [16, 16, 80, 80]]),
# Multi scale anchor.
(5, 6, 1, [1.0], 2.0,
[[-16, -16, 48, 48], [-16, 16, 48, 80],
[16, -16, 80, 48], [16, 16, 80, 80], [-32, -32, 96, 96]]),
# # Multi aspect ratio anchor.
(6, 6, 1, [1.0, 4.0, 0.25], 2.0,
[[-32, -32, 96, 96], [-0, -96, 64, 160], [-96, -0, 160, 64]]),
)
def testAnchorGenerationWithImageSizeAsTensor(self,
min_level,
max_level,
num_scales,
aspect_ratios,
anchor_size,
expected_boxes):
image_size = tf.constant([64, 64], tf.int32)
anchors = anchor.Anchor(min_level, max_level, num_scales, aspect_ratios,
anchor_size, image_size)
boxes = anchors.boxes.numpy()
self.assertEqual(expected_boxes, boxes.tolist())
@parameterized.parameters(
(3, 6, 2, [1.0], 2.0, False),
(3, 6, 2, [1.0], 2.0, True),
)
def testLabelAnchors(self, min_level, max_level, num_scales, aspect_ratios,
anchor_size, has_attribute):
input_size = [512, 512]
ground_truth_class_id = 2
attribute_name = 'depth'
ground_truth_depth = 3.0
# The matched anchors are the anchors used as ground truth and the anchors
# at the next octave scale on the same location.
expected_anchor_locations = [[0, 0, 0], [0, 0, 1]]
anchor_gen = anchor.build_anchor_generator(min_level, max_level, num_scales,
aspect_ratios, anchor_size)
anchor_boxes = anchor_gen(input_size)
anchor_labeler = anchor.AnchorLabeler()
# Uses the first anchors as ground truth. The ground truth should map to
# two anchors with two intermediate scales at the same location.
gt_boxes = anchor_boxes['3'][0:1, 0, 0:4]
gt_classes = tf.constant([[ground_truth_class_id]], dtype=tf.float32)
gt_attributes = {
attribute_name: tf.constant([[ground_truth_depth]], dtype=tf.float32)
} if has_attribute else {}
(cls_targets, box_targets, att_targets, _,
box_weights) = anchor_labeler.label_anchors(anchor_boxes, gt_boxes,
gt_classes, gt_attributes)
for k, v in cls_targets.items():
cls_targets[k] = v.numpy()
for k, v in box_targets.items():
box_targets[k] = v.numpy()
box_weights = box_weights.numpy()
anchor_locations = np.vstack(
np.where(cls_targets[str(min_level)] > -1)).transpose()
self.assertAllClose(expected_anchor_locations, anchor_locations)
# Two anchor boxes on min_level got matched to the gt_boxes.
self.assertAllClose(tf.reduce_sum(box_weights), 2)
if has_attribute:
self.assertIn(attribute_name, att_targets)
for k, v in att_targets[attribute_name].items():
att_targets[attribute_name][k] = v.numpy()
anchor_locations = np.vstack(
np.where(
att_targets[attribute_name][str(min_level)] > 0.0)).transpose()
self.assertAllClose(expected_anchor_locations, anchor_locations)
else:
self.assertEmpty(att_targets)
@parameterized.parameters(
(3, 7, [.5, 1., 2.], 2, 8, (256, 256)),
(3, 8, [1.], 3, 32, (512, 512)),
(3, 3, [1.], 2, 4, (32, 32)),
)
def testEquivalentResult(self, min_level, max_level, aspect_ratios,
num_scales, anchor_size, image_size):
anchor_gen = anchor.build_anchor_generator(
min_level=min_level,
max_level=max_level,
num_scales=num_scales,
aspect_ratios=aspect_ratios,
anchor_size=anchor_size)
anchors = anchor_gen(image_size)
expected_anchor_gen = anchor.Anchor(min_level, max_level, num_scales,
aspect_ratios, anchor_size, image_size)
expected_anchors = expected_anchor_gen.multilevel_boxes
for k in expected_anchors.keys():
self.assertAllClose(expected_anchors[k], anchors[k])
if __name__ == '__main__':
tf.test.main()