Source code for nncore.ops.bbox

# Copyright (c) Ye Liu. Licensed under the MIT License.

import torch


[docs] def bbox_area(bboxes): """ Compute the areas of bounding boxes. Args: bboxes (:obj:`nn.Tensor[N, 4]`): Bounding boxes to be computed. They are expected to be in ``(x1, y1, x2, y2)`` format. Returns: :obj:`nn.Tensor[N]`: The computed areas. """ return (bboxes[:, 2] - bboxes[:, 0]) * (bboxes[:, 3] - bboxes[:, 1])
[docs] def bbox_intersection(bboxes1, bboxes2, aligned=False): """ Compute the intersections among bounding boxes. Args: bboxes1 (:obj:`nn.Tensor[N, 4]`): Bounding boxes to be computed. They are expected to be in ``(x1, y1, x2, y2)`` format. bboxes2 (:obj:`nn.Tensor[M, 4]`): Bounding boxes to be computed. They are expected to be in ``(x1, y1, x2, y2)`` format. aligned (bool, optional): Whether to only compute the intersections among aligned bounding boxes. Default: ``False``. Returns: :obj:`nn.Tensor[N]` | :obj:`nn.Tensor[N, M]`: The computed \ intersection values. """ if aligned: lt = torch.max(bboxes1[:, :2], bboxes2[:, :2]) rb = torch.min(bboxes1[:, 2:], bboxes2[:, 2:]) wh = (rb - lt).clamp(0) inter = wh[:, 0] * wh[:, 1] else: lt = torch.max(bboxes1[:, None, :2], bboxes2[:, :2]) rb = torch.min(bboxes1[:, None, 2:], bboxes2[:, 2:]) wh = (rb - lt).clamp(0) inter = wh[:, :, 0] * wh[:, :, 1] return inter
[docs] def bbox_iou(bboxes1, bboxes2, aligned=False): """ Compute the intersection-over-unions (IoUs) among bounding boxes. Args: bboxes1 (:obj:`nn.Tensor[N, 4]`): Bounding boxes to be computed. They are expected to be in ``(x1, y1, x2, y2)`` format. bboxes2 (:obj:`nn.Tensor[M, 4]`): Bounding boxes to be computed. They are expected to be in ``(x1, y1, x2, y2)`` format. aligned (bool, optional): Whether to only compute the IoU among aligned bounding boxes. Default: ``False``. Returns: :obj:`nn.Tensor[N]` | :obj:`nn.Tensor[N, M]`: The computed pairwise \ IoU values. """ area1 = bbox_area(bboxes1) area2 = bbox_area(bboxes2) inter = bbox_intersection(bboxes1, bboxes2, aligned=aligned) if aligned: iou = inter / (area1 + area2 - inter) else: iou = inter / (area1[:, None] + area2 - inter) return iou
[docs] def bbox_iof(bboxes1, bboxes2, aligned=False): """ Compute the intersection-over-foregrounds (IoFs) among bounding boxes. Args: bboxes1 (:obj:`nn.Tensor[N, 4]`): Bounding boxes to be computed. They are expected to be in ``(x1, y1, x2, y2)`` format. bboxes2 (:obj:`nn.Tensor[M, 4]`): Bounding boxes to be computed. They are expected to be in ``(x1, y1, x2, y2)`` format. aligned (bool, optional): Whether to only compute the IoF among aligned bounding boxes. Default: ``False``. Returns: :obj:`nn.Tensor[N]` | :obj:`nn.Tensor[N, M]`: The computed pairwise \ IoF values. """ area_forground = bbox_area(bboxes1) inter = bbox_intersection(bboxes1, bboxes2, aligned=aligned) if aligned: iof = inter / area_forground else: iof = inter / area_forground[:, None] return iof
[docs] def remove_small_bboxes(bboxes, min_size): """ Remove bounding boxes which contains at least one side smaller than the minimum size. Args: bboxes (:obj:`nn.Tensor[N, 4]`): Bounding boxes to be computed. They are expected to be in ``(x1, y1, x2, y2)`` format. min_size (float): The minimum size of bounding boxes. Returns: :obj:`nn.Tensor[K]`: Indices of the bounding boxes that have both \ sides larger than ``min_size``. """ ws, hs = bboxes[:, 2] - bboxes[:, 0], bboxes[:, 3] - bboxes[:, 1] keep = (ws >= min_size) & (hs >= min_size) keep = keep.nonzero(as_tuple=False).squeeze(1) return keep