diff --git a/test/test_ops.py b/test/test_ops.py index 88124f7ba17..75940b7e509 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -1384,6 +1384,10 @@ def test_bbox_cxcywhr_to_xyxyxyxy(self): box_xyxyxyxy = ops.box_convert(box_tensor, in_fmt="cxcywhr", out_fmt="xyxyxyxy") torch.testing.assert_close(box_xyxyxyxy, exp_xyxyxyxy) + # Reverse conversion + box_cxcywhr = ops.box_convert(box_xyxyxyxy, in_fmt="xyxyxyxy", out_fmt="cxcywhr") + torch.testing.assert_close(box_cxcywhr, box_tensor) + def test_bbox_xywhr_to_xyxyxyxy(self): box_tensor = torch.tensor([[4, 5, 4, 2, 90]], dtype=torch.float) exp_xyxyxyxy = torch.tensor([[4, 5, 4, 1, 6, 1, 6, 5]], dtype=torch.float) @@ -1392,6 +1396,10 @@ def test_bbox_xywhr_to_xyxyxyxy(self): box_xyxyxyxy = ops.box_convert(box_tensor, in_fmt="xywhr", out_fmt="xyxyxyxy") torch.testing.assert_close(box_xyxyxyxy, exp_xyxyxyxy) + # Reverse conversion + box_xywhr = ops.box_convert(box_xyxyxyxy, in_fmt="xyxyxyxy", out_fmt="xywhr") + torch.testing.assert_close(box_xywhr, box_tensor) + @pytest.mark.parametrize("inv_infmt", ["xwyh", "cxwyh", "xwyhr", "cxwyhr", "xxxxyyyy"]) @pytest.mark.parametrize("inv_outfmt", ["xwcx", "xhwcy", "xwcxr", "xhwcyr", "xyxyxxyy"]) def test_bbox_invalid(self, inv_infmt, inv_outfmt): diff --git a/torchvision/ops/_box_convert.py b/torchvision/ops/_box_convert.py index 62744fee060..4484007bc83 100644 --- a/torchvision/ops/_box_convert.py +++ b/torchvision/ops/_box_convert.py @@ -178,10 +178,9 @@ def _box_xyxyxyxy_to_xywhr(boxes: Tensor) -> Tensor: x1, y1, x3, y3, x2, y2, x4, y4 = boxes.unbind(-1) r_rad = torch.atan2(y1 - y3, x3 - x1) r = r_rad * 180 / torch.pi - cos, sin = torch.cos(r_rad), torch.sin(r_rad) - w = (x2 - x1) * cos + (y1 - y2) * sin - h = (x2 - x1) * sin + (y2 - y1) * cos + w = ((x3 - x1) ** 2 + (y1 - y3) ** 2).sqrt() + h = ((x3 - x2) ** 2 + (y3 - y2) ** 2).sqrt() boxes = torch.stack((x1, y1, w, h, r), dim=-1) diff --git a/torchvision/transforms/v2/functional/_meta.py b/torchvision/transforms/v2/functional/_meta.py index 4f1c192455e..f6473e5547d 100644 --- a/torchvision/transforms/v2/functional/_meta.py +++ b/torchvision/transforms/v2/functional/_meta.py @@ -252,13 +252,13 @@ def _xyxyxyxy_to_xywhr(xyxyxyxy: torch.Tensor, inplace: bool) -> torch.Tensor: xyxyxyxy = xyxyxyxy.float() r_rad = torch.atan2(xyxyxyxy[..., 1].sub(xyxyxyxy[..., 3]), xyxyxyxy[..., 2].sub(xyxyxyxy[..., 0])) - cos, sin = r_rad.cos(), r_rad.sin() - # x1, y1, x3, y3, (x2 - x1), (y2 - y1) x4, y4 - xyxyxyxy[..., 4:6].sub_(xyxyxyxy[..., :2]) - # (x2 - x1) * cos + (y1 - y2) * sin = w - xyxyxyxy[..., 2] = xyxyxyxy[..., 4].mul(cos).sub(xyxyxyxy[..., 5].mul(sin)) - # (x2 - x1) * sin + (y2 - y1) * cos = h - xyxyxyxy[..., 3] = xyxyxyxy[..., 5].mul(cos).add(xyxyxyxy[..., 4].mul(sin)) + # x1, y1, (x3 - x1), (y3 - y1), (x2 - x3), (y2 - y3) x4, y4 + xyxyxyxy[..., 4:6].sub_(xyxyxyxy[..., 2:4]) + xyxyxyxy[..., 2:4].sub_(xyxyxyxy[..., :2]) + # sqrt((x3 - x1) ** 2 + (y1 - y3) ** 2) = w + xyxyxyxy[..., 2] = xyxyxyxy[..., 2].pow(2).add(xyxyxyxy[..., 3].pow(2)).sqrt() + # sqrt((x3 - x2) ** 2 + (y3 - y2) ** 2) = h + xyxyxyxy[..., 3] = xyxyxyxy[..., 4].pow(2).add(xyxyxyxy[..., 5].pow(2)).sqrt() xyxyxyxy[..., 4] = r_rad.div_(torch.pi).mul_(180.0) return xyxyxyxy[..., :5].to(dtype)