Spaces:
Running on Zero
Running on Zero
| 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)) | |