Skip to content

Segmentation masks IoU support #5726

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

Open
ilbash opened this issue Apr 2, 2022 · 6 comments
Open

Segmentation masks IoU support #5726

ilbash opened this issue Apr 2, 2022 · 6 comments

Comments

@ilbash
Copy link

ilbash commented Apr 2, 2022

🚀 The feature

pairwise distance on segmentation masks like (torchvision.ops.box_iou)

Motivation, pitch

motivation: cost matrix construction in object tracking

Alternatives

pycocotools.maskUtils.iou

Additional context

No response

cc @datumbox @YosuaMichael

@datumbox
Copy link
Contributor

datumbox commented Apr 4, 2022

@Ilyabasharov thanks for the recommendation.

I think it's an operator we could consider adding in TorchVision. If you send a PR that adds it, I'll be happy to review it.

@oke-aditya
Copy link
Contributor

I had a thought over this. Masks are always interpreted very differently.
If we see pycocotools. They actually support rle masks #4415 .

Also I'm not sure what IoU in segmentation would actually refer to?
If the masks are represented as bit masks (or boolean masks) Say

ground truth
[
 [ 0  0 0 0 1]
 [ 1 0 1 0 0 ]
]
Pred mask
[
 [0 1 0 0 1 ]
 [0 1 1 0 0 ]
]

Then I think IoU is simply jaccard index between these two? This isn't the case if masks are represented as rle masks.
Maybe refer detectron2 as well https://github.com/facebookresearch/detectron2/blob/6886f85baee349556749680ae8c85cdba1782d8e/detectron2/structures/masks.py#L173

As in currently our mask utils support boolean or bit masks.

@vadimkantorov
Copy link

Related discussion: #4415

@ilbash
Copy link
Author

ilbash commented Apr 21, 2022

@datumbox oke-aditya
Here is my the answer def mask_iou(mask1: torch.Tensor, mask2: torch.Tensor, ) -> torch.Tensor:

@VasLem
Copy link

VasLem commented Apr 16, 2023

Extending on @Ilyabasharov 's function, here is a naive extension that accepts batches:

import torch
@torch.jit.script
def mask_iou(
    mask1: torch.Tensor,
    mask2: torch.Tensor,
) -> torch.Tensor:

    """
    Inputs:
    mask1: BxNxHxW torch.float32. Consists of [0, 1]
    mask2: BxMxHxW torch.float32. Consists of [0, 1]
    Outputs:
    ret: BxNxM torch.float32. Consists of [0 - 1]
    """

    B, N, H, W = mask1.shape
    B, M, H, W = mask2.shape

    mask1 = mask1.view(B, N, H * W)
    mask2 = mask2.view(B, M, H * W)

    intersection = torch.matmul(mask1, mask2.swapaxes(1, 2))

    area1 = mask1.sum(dim=2).unsqueeze(1)
    area2 = mask2.sum(dim=2).unsqueeze(1)

    union = (area1.swapaxes(1, 2) + area2) - intersection

    ret = torch.where(
        union == 0,
        torch.tensor(0.0, device=mask1.device),
        intersection / union,
    )

    return ret

@vadimkantorov
Copy link

vadimkantorov commented Apr 16, 2023

@VasLem might become even nicer to use mask1.flatten(start_dim = -2) instead of the view. though maybe some extra asserts on shape correctness would be nice as well

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

No branches or pull requests

5 participants