| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| """ |
| Utilities for bounding box manipulation and GIoU. |
| """ |
| import numpy as np |
| import torch |
|
|
|
|
| def box_cxcywh_to_xyxy(x): |
| x_c, y_c, w, h = x.unbind(-1) |
| b = [(x_c - 0.5 * w), (y_c - 0.5 * h), (x_c + 0.5 * w), (y_c + 0.5 * h)] |
| return torch.stack(b, dim=-1) |
|
|
|
|
| def box_xyxy_to_cxcywh(x): |
| x0, y0, x1, y1 = x.unbind(-1) |
| b = [(x0 + x1) / 2, (y0 + y1) / 2, (x1 - x0), (y1 - y0)] |
| return torch.stack(b, dim=-1) |
|
|
|
|
| def delta2bbox( |
| proposals, deltas, max_shape=None, wh_ratio_clip=16 / 1000, clip_border=True, add_ctr_clamp=False, ctr_clamp=32 |
| ): |
| dxy = deltas[..., :2] |
| dwh = deltas[..., 2:] |
|
|
| |
| pxy = proposals[..., :2] |
| pwh = proposals[..., 2:] |
|
|
| dxy_wh = pwh * dxy |
|
|
| max_ratio = np.abs(np.log(wh_ratio_clip)) |
| if add_ctr_clamp: |
| dxy_wh = torch.clamp(dxy_wh, max=ctr_clamp, min=-ctr_clamp) |
| dwh = torch.clamp(dwh, max=max_ratio) |
| else: |
| dwh = dwh.clamp(min=-max_ratio, max=max_ratio) |
|
|
| gxy = pxy + dxy_wh |
| gwh = pwh * dwh.exp() |
| x1y1 = gxy - (gwh * 0.5) |
| x2y2 = gxy + (gwh * 0.5) |
| bboxes = torch.cat([x1y1, x2y2], dim=-1) |
| if clip_border and max_shape is not None: |
| bboxes[..., 0::2].clamp_(min=0).clamp_(max=max_shape[1]) |
| bboxes[..., 1::2].clamp_(min=0).clamp_(max=max_shape[0]) |
| return bboxes |
|
|
|
|
| def bbox2delta(proposals, gt, means=(0.0, 0.0, 0.0, 0.0), stds=(1.0, 1.0, 1.0, 1.0)): |
| |
| if proposals.size() != gt.size(): |
| proposals = proposals[:, None] |
| gt = gt[None] |
|
|
| proposals = proposals.float() |
| gt = gt.float() |
| px, py, pw, ph = proposals.unbind(-1) |
| gx, gy, gw, gh = gt.unbind(-1) |
|
|
| dx = (gx - px) / (pw + 0.1) |
| dy = (gy - py) / (ph + 0.1) |
| dw = torch.log(gw / (pw + 0.1)) |
| dh = torch.log(gh / (ph + 0.1)) |
| deltas = torch.stack([dx, dy, dw, dh], dim=-1) |
|
|
| |
| if means != (0.0, 0.0, 0.0, 0.0) or stds != (1.0, 1.0, 1.0, 1.0): |
| means = deltas.new_tensor(means).unsqueeze(0) |
| stds = deltas.new_tensor(stds).unsqueeze(0) |
| deltas = deltas.sub_(means).div_(stds) |
|
|
| return deltas |
|
|