Spaces:
Build error
Build error
# Copyright (c) Meta Platforms, Inc. and affiliates. | |
# All rights reserved. | |
# | |
# This source code is licensed under the license found in the | |
# LICENSE file in the root directory of this source tree. | |
import torch | |
from ..utils import ext_loader | |
ext_module = ext_loader.load_ext('_ext', ['box_iou_rotated']) | |
def box_iou_rotated(bboxes1: torch.Tensor, | |
bboxes2: torch.Tensor, | |
mode: str = 'iou', | |
aligned: bool = False, | |
clockwise: bool = True) -> torch.Tensor: | |
"""Return intersection-over-union (Jaccard index) of boxes. | |
Both sets of boxes are expected to be in | |
(x_center, y_center, width, height, angle) format. | |
If ``aligned`` is ``False``, then calculate the ious between each bbox | |
of bboxes1 and bboxes2, otherwise the ious between each aligned pair of | |
bboxes1 and bboxes2. | |
.. note:: | |
The operator assumes: | |
1) The positive direction along x axis is left -> right. | |
2) The positive direction along y axis is top -> down. | |
3) The w border is in parallel with x axis when angle = 0. | |
However, there are 2 opposite definitions of the positive angular | |
direction, clockwise (CW) and counter-clockwise (CCW). MMCV supports | |
both definitions and uses CW by default. | |
Please set ``clockwise=False`` if you are using the CCW definition. | |
The coordinate system when ``clockwise`` is ``True`` (default) | |
.. code-block:: none | |
0-------------------> x (0 rad) | |
| A-------------B | |
| | | | |
| | box h | |
| | angle=0 | | |
| D------w------C | |
v | |
y (pi/2 rad) | |
In such coordination system the rotation matrix is | |
.. math:: | |
\\begin{pmatrix} | |
\\cos\\alpha & -\\sin\\alpha \\\\ | |
\\sin\\alpha & \\cos\\alpha | |
\\end{pmatrix} | |
The coordinates of the corner point A can be calculated as: | |
.. math:: | |
P_A= | |
\\begin{pmatrix} x_A \\\\ y_A\\end{pmatrix} | |
= | |
\\begin{pmatrix} x_{center} \\\\ y_{center}\\end{pmatrix} + | |
\\begin{pmatrix}\\cos\\alpha & -\\sin\\alpha \\\\ | |
\\sin\\alpha & \\cos\\alpha\\end{pmatrix} | |
\\begin{pmatrix} -0.5w \\\\ -0.5h\\end{pmatrix} \\\\ | |
= | |
\\begin{pmatrix} x_{center}-0.5w\\cos\\alpha+0.5h\\sin\\alpha | |
\\\\ | |
y_{center}-0.5w\\sin\\alpha-0.5h\\cos\\alpha\\end{pmatrix} | |
The coordinate system when ``clockwise`` is ``False`` | |
.. code-block:: none | |
0-------------------> x (0 rad) | |
| A-------------B | |
| | | | |
| | box h | |
| | angle=0 | | |
| D------w------C | |
v | |
y (-pi/2 rad) | |
In such coordination system the rotation matrix is | |
.. math:: | |
\\begin{pmatrix} | |
\\cos\\alpha & \\sin\\alpha \\\\ | |
-\\sin\\alpha & \\cos\\alpha | |
\\end{pmatrix} | |
The coordinates of the corner point A can be calculated as: | |
.. math:: | |
P_A= | |
\\begin{pmatrix} x_A \\\\ y_A\\end{pmatrix} | |
= | |
\\begin{pmatrix} x_{center} \\\\ y_{center}\\end{pmatrix} + | |
\\begin{pmatrix}\\cos\\alpha & \\sin\\alpha \\\\ | |
-\\sin\\alpha & \\cos\\alpha\\end{pmatrix} | |
\\begin{pmatrix} -0.5w \\\\ -0.5h\\end{pmatrix} \\\\ | |
= | |
\\begin{pmatrix} x_{center}-0.5w\\cos\\alpha-0.5h\\sin\\alpha | |
\\\\ | |
y_{center}+0.5w\\sin\\alpha-0.5h\\cos\\alpha\\end{pmatrix} | |
Args: | |
boxes1 (torch.Tensor): rotated bboxes 1. It has shape (N, 5), | |
indicating (x, y, w, h, theta) for each row. Note that theta is in | |
radian. | |
boxes2 (torch.Tensor): rotated bboxes 2. It has shape (M, 5), | |
indicating (x, y, w, h, theta) for each row. Note that theta is in | |
radian. | |
mode (str): "iou" (intersection over union) or iof (intersection over | |
foreground). | |
clockwise (bool): flag indicating whether the positive angular | |
orientation is clockwise. default True. | |
`New in version 1.4.3.` | |
Returns: | |
torch.Tensor: Return the ious betweens boxes. If ``aligned`` is | |
``False``, the shape of ious is (N, M) else (N,). | |
""" | |
assert mode in ['iou', 'iof'] | |
mode_dict = {'iou': 0, 'iof': 1} | |
mode_flag = mode_dict[mode] | |
rows = bboxes1.size(0) | |
cols = bboxes2.size(0) | |
if aligned: | |
ious = bboxes1.new_zeros(rows) | |
else: | |
if bboxes1.device.type == 'mlu': | |
ious = bboxes1.new_zeros([rows, cols]) | |
else: | |
ious = bboxes1.new_zeros(rows * cols) | |
if not clockwise: | |
flip_mat = bboxes1.new_ones(bboxes1.shape[-1]) | |
flip_mat[-1] = -1 | |
bboxes1 = bboxes1 * flip_mat | |
bboxes2 = bboxes2 * flip_mat | |
if bboxes1.device.type == 'npu': | |
scale_mat = bboxes1.new_ones(bboxes1.shape[-1]) | |
scale_mat[-1] = 1.0 / 0.01745329252 | |
bboxes1 = bboxes1 * scale_mat | |
bboxes2 = bboxes2 * scale_mat | |
bboxes1 = bboxes1.contiguous() | |
bboxes2 = bboxes2.contiguous() | |
ext_module.box_iou_rotated( | |
bboxes1, bboxes2, ious, mode_flag=mode_flag, aligned=aligned) | |
if not aligned: | |
ious = ious.view(rows, cols) | |
return ious | |