Cyril666's picture
First model version
6250360
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
import math
import torch
import pandas as pd
from maskrcnn_benchmark.data.datasets.evaluation.word import io_
class BoxCoder(object):
"""
This class encodes and decodes a set of bounding boxes into the representation used for training the regressors.
"""
def __init__(self, weights, bbox_xform_clip=math.log(1000. / 16)):
"""
Arguments:
weights (4-element tuple)
bbox_xform_clip (float)
"""
self.weights = weights
self.bbox_xform_clip = bbox_xform_clip
def encode(self, reference_boxes, proposals):
"""
Encode a set of proposals with respect to some
reference boxes
Arguments:
reference_boxes (Tensor): reference boxes
proposals (Tensor): boxes to be encoded
"""
TO_REMOVE = 1 # TODO remove
ex_widths = proposals[:, 2] - proposals[:, 0] + TO_REMOVE
ex_heights = proposals[:, 3] - proposals[:, 1] + TO_REMOVE
ex_ctr_x = proposals[:, 0] + 0.5 * ex_widths
ex_ctr_y = proposals[:, 1] + 0.5 * ex_heights
gt_widths = reference_boxes[:, 2] - reference_boxes[:, 0] + TO_REMOVE
gt_heights = reference_boxes[:, 3] - reference_boxes[:, 1] + TO_REMOVE
gt_ctr_x = reference_boxes[:, 0] + 0.5 * gt_widths
gt_ctr_y = reference_boxes[:, 1] + 0.5 * gt_heights
wx, wy, ww, wh = self.weights
targets_dx = wx * (gt_ctr_x - ex_ctr_x) / ex_widths
targets_dy = wy * (gt_ctr_y - ex_ctr_y) / ex_heights
targets_dw = ww * torch.log(gt_widths / ex_widths)
targets_dh = wh * torch.log(gt_heights / ex_heights)
targets = torch.stack((targets_dx, targets_dy, targets_dw, targets_dh), dim=1)
return targets
def encode_iou(self, reference_boxes, proposals):
"""
Encode a set of proposals with respect to some
reference boxes
Arguments:
reference_boxes (Tensor): reference boxes
proposals (Tensor): boxes to be encoded
"""
TO_REMOVE = 1 # TODO remove
ex_widths = proposals[:, 2] - proposals[:, 0] + TO_REMOVE
ex_heights = proposals[:, 3] - proposals[:, 1] + TO_REMOVE
ex_ctr_x = proposals[:, 0] + 0.5 * ex_widths
ex_ctr_y = proposals[:, 1] + 0.5 * ex_heights
gt_widths = reference_boxes[:, 2] - reference_boxes[:, 0] + TO_REMOVE
gt_heights = reference_boxes[:, 3] - reference_boxes[:, 1] + TO_REMOVE
gt_ctr_x = reference_boxes[:, 0] + 0.5 * gt_widths
gt_ctr_y = reference_boxes[:, 1] + 0.5 * gt_heights
wx, wy, ww, wh = self.weights
targets_dx = wx * (gt_ctr_x - ex_ctr_x) / ex_widths
targets_dy = wy * (gt_ctr_y - ex_ctr_y) / ex_heights
targets_dw = ww * torch.log(gt_widths / ex_widths)
targets_dh = wh * torch.log(gt_heights / ex_heights)
targets = torch.stack((targets_dx, targets_dy, targets_dw, targets_dh), dim=1)
return targets
def decode(self, rel_codes, boxes):
"""
From a set of original boxes and encoded relative box offsets,
get the decoded boxes.
Arguments:
rel_codes (Tensor): encoded boxes # predict [2, 12000, 4]
boxes (Tensor): reference boxes. # anchor [2, 12000, 4] xmin0 ymin1 xmax2 ymax3
"""
boxes = boxes.to(rel_codes.dtype)
TO_REMOVE = 1 # TODO remove
widths = boxes[:, 2] - boxes[:, 0] + TO_REMOVE
heights = boxes[:, 3] - boxes[:, 1] + TO_REMOVE
ctr_x = boxes[:, 0] + 0.5 * widths
ctr_y = boxes[:, 1] + 0.5 * heights
wx, wy, ww, wh = self.weights
dx = rel_codes[:, 0::4] / wx
dy = rel_codes[:, 1::4] / wy
dw = rel_codes[:, 2::4] / ww
dh = rel_codes[:, 3::4] / wh
dw = torch.clamp(dw, max=self.bbox_xform_clip)
dh = torch.clamp(dh, max=self.bbox_xform_clip)
pred_ctr_x = dx * widths[:, None] + ctr_x[:, None]
pred_ctr_y = dy * heights[:, None] + ctr_y[:, None]
pred_w = torch.exp(dw) * widths[:, None]
pred_h = torch.exp(dh) * heights[:, None]
##############################
pred_boxes = torch.zeros_like(rel_codes)
pred_boxes[:, 0::4] = pred_ctr_x - 0.5 * pred_w
pred_boxes[:, 1::4] = pred_ctr_y - 0.5 * pred_h
pred_boxes[:, 2::4] = pred_ctr_x + 0.5 * pred_w - 1
pred_boxes[:, 3::4] = pred_ctr_y + 0.5 * pred_h - 1
return pred_boxes
def decode_iou(self, rel_codes, boxes, num_p = 8):
"""
From a set of original boxes and encoded relative box offsets,
get the decoded boxes.
Arguments:
rel_codes (Tensor): encoded boxes # predict [2, 12000, 4]
boxes (Tensor): reference boxes. # anchor [2, 12000, 4] xmin0 ymin1 xmax2 ymax3
"""
boxes = boxes.to(rel_codes.dtype)
TO_REMOVE = 1 # TODO remove
widths = boxes[:, 2] - boxes[:, 0] + TO_REMOVE
heights = boxes[:, 3] - boxes[:, 1] + TO_REMOVE
ctr_x = boxes[:, 0] + 0.5 * widths
ctr_y = boxes[:, 1] + 0.5 * heights
# 123
# 8#4
# 765
if num_p == 8: # 8 boundary points
x_1 = boxes[:, 0] + widths * rel_codes[:, 0]
y_1 = boxes[:, 1] + heights * rel_codes[:, 1]
x_2 = ctr_x + widths * rel_codes[:, 2]
y_2 = boxes[:, 1] + heights * rel_codes[:, 3]
x_3 = boxes[:, 2] + widths * rel_codes[:, 4]
y_3 = boxes[:, 1] + heights * rel_codes[:, 5]
x_4 = boxes[:, 2] + widths * rel_codes[:, 6]
y_4 = ctr_y + heights * rel_codes[:, 7]
x_5 = boxes[:, 2] + widths * rel_codes[:, 8]
y_5 = boxes[:, 3] + heights * rel_codes[:, 9]
x_6 = ctr_x + widths * rel_codes[:, 10]
y_6 = boxes[:, 3] + heights * rel_codes[:, 11]
x_7 = boxes[:, 0] + widths * rel_codes[:, 12]
y_7 = boxes[:, 3] + heights * rel_codes[:, 13]
x_8 = boxes[:, 0] + widths * rel_codes[:, 14]
y_8 = ctr_y + heights * rel_codes[:, 15]
x_total = torch.stack([x_1, x_2, x_3, x_4, x_5, x_6, x_7, x_8], 0)
y_total = torch.stack([y_1, y_2, y_3, y_4, y_5, y_6, y_7, y_8], 0)
x_min = torch.min(x_total, 0, keepdim=True) # [1, N]
x_max = torch.max(x_total, 0, keepdim=True)
y_min = torch.min(y_total, 0, keepdim=True)
y_max = torch.max(y_total, 0, keepdim=True)
N1, N2 = x_min[0].shape
x_min = x_min[0].view([N2])
x_max = x_max[0].view([N2])
y_min = y_min[0].view([N2])
y_max = y_max[0].view([N2])
x_min = torch.stack([x_min, ctr_x], 0)
x_max = torch.stack([x_max, ctr_x], 0)
y_min = torch.stack([y_min, ctr_y], 0)
y_max = torch.stack([y_max, ctr_y], 0)
x_min = torch.min(x_min, 0, keepdim=True) # [1, N]
x_max = torch.max(x_max, 0, keepdim=True)
y_min = torch.min(y_min, 0, keepdim=True)
y_max = torch.max(y_max, 0, keepdim=True)
pred_boxes = torch.zeros_like(boxes)
pred_boxes[:, 0] = x_min[0][0, :]
pred_boxes[:, 1] = y_min[0][0, :]
pred_boxes[:, 2] = x_max[0][0, :]
pred_boxes[:, 3] = y_max[0][0, :]
return pred_boxes