File size: 2,636 Bytes
9b92c75 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | from __future__ import annotations
import torch
from torch import Tensor
def box_cxcywh_to_xyxy(boxes: Tensor) -> Tensor:
cx, cy, width, height = boxes.unbind(-1)
return torch.stack(
(cx - 0.5 * width, cy - 0.5 * height, cx + 0.5 * width, cy + 0.5 * height),
dim=-1,
)
def box_xyxy_to_cxcywh(boxes: Tensor) -> Tensor:
x0, y0, x1, y1 = boxes.unbind(-1)
return torch.stack(
((x0 + x1) * 0.5, (y0 + y1) * 0.5, x1 - x0, y1 - y0), dim=-1
)
def box_area(boxes: Tensor) -> Tensor:
return (boxes[..., 2] - boxes[..., 0]).clamp(min=0) * (
boxes[..., 3] - boxes[..., 1]
).clamp(min=0)
def box_iou(boxes1: Tensor, boxes2: Tensor) -> tuple[Tensor, Tensor]:
area1 = box_area(boxes1)
area2 = box_area(boxes2)
top_left = torch.maximum(boxes1[:, None, :2], boxes2[:, :2])
bottom_right = torch.minimum(boxes1[:, None, 2:], boxes2[:, 2:])
intersection = (bottom_right - top_left).clamp(min=0).prod(dim=-1)
union = area1[:, None] + area2 - intersection
return intersection / union.clamp(min=1e-7), union
def generalized_box_iou(boxes1: Tensor, boxes2: Tensor) -> Tensor:
"""Pairwise generalized IoU for boxes in x0, y0, x1, y1 format."""
iou, union = box_iou(boxes1, boxes2)
top_left = torch.minimum(boxes1[:, None, :2], boxes2[:, :2])
bottom_right = torch.maximum(boxes1[:, None, 2:], boxes2[:, 2:])
enclosing = (bottom_right - top_left).clamp(min=0).prod(dim=-1)
return iou - (enclosing - union) / enclosing.clamp(min=1e-7)
def generalized_box_iou_batched(boxes1: Tensor, boxes2: Tensor) -> Tensor:
"""Batched pairwise generalized IoU, boxes in x0, y0, x1, y1 format.
boxes1: [B, N, 4], boxes2: [B, M, 4] -> [B, N, M]
"""
area1 = box_area(boxes1)
area2 = box_area(boxes2)
top_left = torch.maximum(boxes1[:, :, None, :2], boxes2[:, None, :, :2])
bottom_right = torch.minimum(boxes1[:, :, None, 2:], boxes2[:, None, :, 2:])
intersection = (bottom_right - top_left).clamp(min=0).prod(dim=-1)
union = area1[:, :, None] + area2[:, None, :] - intersection
iou = intersection / union.clamp(min=1e-7)
enc_top_left = torch.minimum(boxes1[:, :, None, :2], boxes2[:, None, :, :2])
enc_bottom_right = torch.maximum(boxes1[:, :, None, 2:], boxes2[:, None, :, 2:])
enclosing = (enc_bottom_right - enc_top_left).clamp(min=0).prod(dim=-1)
return iou - (enclosing - union) / enclosing.clamp(min=1e-7)
def inverse_sigmoid(value: Tensor, eps: float = 1e-5) -> Tensor:
value = value.clamp(min=0.0, max=1.0)
return torch.log(value.clamp(min=eps) / (1.0 - value).clamp(min=eps))
|