Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong IoU calculation when corners are smaller than 0 #40

Open
Eralien opened this issue Apr 8, 2022 · 6 comments
Open

Wrong IoU calculation when corners are smaller than 0 #40

Eralien opened this issue Apr 8, 2022 · 6 comments

Comments

@Eralien
Copy link

Eralien commented Apr 8, 2022

Hi! Thank you @lilanxiao for your great work. I have been using your work for sometime, and it has been beneficial for my training.

One problem I encountered was under certain circumstances, the IoU calculations are wrong. Most of them happened when the calculated corners of boxes are smaller than zero. Some happened when length or width are too small, which may have something to do with numeric instability. There's maybe other cases, but these two are what I have discovered.

My environment:
Ubuntu 18.04, CUDA 11.2, Pytorch 1.8, python 3.8

@Eralien
Copy link
Author

Eralien commented Apr 8, 2022

I have a simple solution for the corners problem: simply add a translation to all boxes if any of their corners coordinates is negative.

def cal_iou(box1: torch.Tensor, box2: torch.Tensor):
    """calculate iou
    Args:
        box1 (torch.Tensor): (B, N, 5) with x, y, w, h, alpha
        box2 (torch.Tensor): (B, N, 5) with x, y, w, h, alpha

    Returns:
        iou (torch.Tensor): (B, N)
        corners1 (torch.Tensor): (B, N, 4, 2)
        corners1 (torch.Tensor): (B, N, 4, 2)
        U (torch.Tensor): (B, N) area1 + area2 - inter_area
    """
    corners1 = box2corners_th(box1)
    corners2 = box2corners_th(box2)

    # calculate the min corner coordinates
    corners_min = torch.minimum(corners1, corners2).amin(-2) - 1e-5   # eps
    # if any element is negative, translate all coordinates to positive number
    if corners_min.lt(0).any():
        corners1_positive = corners1 - corners_min
        corners2_positive = corners2 - corners_min
        inter_area, _ = oriented_box_intersection_2d(corners1_positive, corners2_positive)    # (B, N)
    else:
        # if not, directly calculate the intersection area
        inter_area, _ = oriented_box_intersection_2d(corners1, corners2)    # (B, N)
    area1 = box1[:, :, 2] * box1[:, :, 3]
    area2 = box2[:, :, 2] * box2[:, :, 3]
    u = area1 + area2 - inter_area
    iou = inter_area / u
    return iou, corners1, corners2, u

I tested the results against the one implemented in detectron2, and the results difference for 1000 random tests are within 1e-3.

@rubbish001
Copy link

代码有问题,不知道怎么改,求作者更新代码

@lilanxiao
Copy link
Owner

hi, thank you for the issue and workaround.
I've just updated my code in the debug branch. I think the new version is probably more stable.
Please let me know if the problem persists.

@Eralien
Copy link
Author

Eralien commented Jun 14, 2022

hi, thank you for the issue and workaround. I've just updated my code in the debug branch. I think the new version is probably more stable. Please let me know if the problem persists.

Thanks! Will test soon.

@rubbish001
Copy link

还是会出现nan

@xiazhiyi99
Copy link

xiazhiyi99 commented Aug 3, 2023

same problem
Can we simply add a constant big value to the corners at the beginning like this?

def cal_iou(box1:Tensor, box2:Tensor):
    corners1 = box2corners_th(box1) + 100
    corners2 = box2corners_th(box2) + 100
    ...

I tried it and it seems fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants