def test_iou_0_dim_cuda(self): boxes1 = torch.rand(0, 5, dtype=torch.float32) boxes2 = torch.rand(10, 5, dtype=torch.float32) expected_ious = torch.zeros(0, 10, dtype=torch.float32) ious_cuda = pairwise_iou_rotated(boxes1.cuda(), boxes2.cuda()) self.assertTrue(torch.allclose(ious_cuda.cpu(), expected_ious)) boxes1 = torch.rand(10, 5, dtype=torch.float32) boxes2 = torch.rand(0, 5, dtype=torch.float32) expected_ious = torch.zeros(10, 0, dtype=torch.float32) ious_cuda = pairwise_iou_rotated(boxes1.cuda(), boxes2.cuda()) self.assertTrue(torch.allclose(ious_cuda.cpu(), expected_ious))
def test_iou_precision(self): for device in ["cpu"] + ["cuda"] if torch.cuda.is_available() else []: boxes1 = torch.tensor([[565, 565, 10, 10.0, 0]], dtype=torch.float32, device=device) boxes2 = torch.tensor([[565, 565, 10, 8.3, 0]], dtype=torch.float32, device=device) iou = 8.3 / 10.0 expected_ious = torch.tensor([[iou]], dtype=torch.float32) ious = pairwise_iou_rotated(boxes1, boxes2) self.assertTrue(torch.allclose(ious.cpu(), expected_ious))
def pairwise_iou(boxes1: RotatedBoxes, boxes2: RotatedBoxes) -> None: """ Given two lists of rotated boxes of size N and M, compute the IoU (intersection over union) between __all__ N x M pairs of boxes. The box order must be (x_center, y_center, width, height, angle). Args: boxes1, boxes2 (RotatedBoxes): two `RotatedBoxes`. Contains N & M rotated boxes, respectively. Returns: Tensor: IoU, sized [N,M]. """ return pairwise_iou_rotated(boxes1.tensor, boxes2.tensor)
def softnms_rotated(boxes, scores, sigma, score_threshold, soft_mode="gaussian"): assert soft_mode in ["linear", "gaussian"] iou_matrix = pairwise_iou_rotated(boxes, boxes) undone_mask = scores >= score_threshold while undone_mask.sum() > 1: idx = scores[undone_mask].argmax() idx = undone_mask.nonzero(as_tuple=False)[idx].item() undone_mask[idx] = False ious = iou_matrix[idx, undone_mask] scales = scale_by_iou(ious, sigma, soft_mode) scores[undone_mask] *= scales undone_mask[scores < score_threshold] = False return scores
def test_iou_extreme(self): # Cause floating point issues in cuda kernels (#1266) # See: https://github.com/facebookresearch/detectron2/issues/1266 for device in ["cpu"] + ["cuda"] if torch.cuda.is_available() else []: boxes1 = torch.tensor([[160.0, 153.0, 230.0, 23.0, -37.0]], device=device) boxes2 = torch.tensor( [ [ -1.117407639806935e17, 1.3858420478349148e18, 1000.0000610351562, 1000.0000610351562, 1612.0, ] ], device=device, ) ious = pairwise_iou_rotated(boxes1, boxes2) self.assertTrue(ious.min() >= 0, ious)
def test_iou_too_many_boxes_cuda(self): s1, s2 = 5, 1289035 boxes1 = torch.zeros(s1, 5) boxes2 = torch.zeros(s2, 5) ious_cuda = pairwise_iou_rotated(boxes1.cuda(), boxes2.cuda()) self.assertTupleEqual(tuple(ious_cuda.shape), (s1, s2))
def test_iou_half_overlap_cuda(self): boxes1 = torch.tensor([[0.5, 0.5, 1.0, 1.0, 0.0]], dtype=torch.float32) boxes2 = torch.tensor([[0.25, 0.5, 0.5, 1.0, 0.0]], dtype=torch.float32) expected_ious = torch.tensor([[0.5]], dtype=torch.float32) ious_cuda = pairwise_iou_rotated(boxes1.cuda(), boxes2.cuda()) self.assertTrue(torch.allclose(ious_cuda.cpu(), expected_ious))
def bench(): for _ in range(n): pairwise_iou_rotated(b1, b2) if dev.type == "cuda": torch.cuda.synchronize()