def box_iou(boxes1, boxes2): # 返回每个boxes 的area area1 = box_area(boxes1) area2 = box_area(boxes2) # 左上角取最大的 # boxes1: [N,4], boxes1[:,None] -> [N,1,4] 多了1维 # troch.max(shape[N,1,2], shape[M,2]), 形状不一致,怎么比 # 传入两个张量,就会调用的是 # torch.maximum(input, other,...) # Computes the element-wise maximum of input and other. # 对于维度数不一样,会产生一个矩阵。。 # 相当于先 [1,2] 跟 [M,2] 比较,得到一个 [M,2], 一共有N个[1,2] 所以为[N,M,2] # 对于 [[m]], [[m],...,[m]] 这样是可以元素级比较的,即第一个的第一维要么为1(可以通过repeated) 重复比较,要么跟第二个一样,其他不可行 # 这样一来,boxes1 的每个元素可以和boxes2的每个元素进行计算,正是我们想要的 lt = torch.max(boxes1[:, None, :2], boxes2[:, :2]) # [N,M,2] # 左下角取最小的 rb = torch.min(boxes1[:, None, 2:], boxes2[:, 2:]) # [N,M,2] wh = (rb - lt).clamp(min=0) # [N,M,2] # 求 w,h of intersection inter = wh[:, :, 0] * wh[:, :, 1] # [N,M] # are of intersection union = area1[:, None] + area2 - inter # 并集 iou = inter / union return iou, union
def box_iou(boxes1, boxes2): """ Return intersection-over-union (Jaccard index) of boxes. Both sets of boxes are expected to be in (x1, y1, x2, y2) format. Arguments: boxes1 (Tensor[N, 4]) boxes2 (Tensor[M, 4]) Returns: iou (Tensor[N, M]): the NxM matrix containing the pairwise IoU values for every element in boxes1 and boxes2 union (Tensor[N, M]): the NxM matrix containing the pairwise Union values for every element in boxes1 and boxes2 """ # area1 : {float, vector} of shape (batch_size * num_target_boxes) area1 = box_area(boxes1) # area2 : {float, vector} of shape (batch_size * num_target_boxes) area2 = box_area(boxes2) lt = torch.max(boxes1[:, None, :2], boxes2[:, :2]) # [N,M,2] rb = torch.min(boxes1[:, None, 2:], boxes2[:, 2:]) # [N,M,2] wh = (rb - lt).clamp(min=0) # [N,M,2] inter = wh[:, :, 0] * wh[:, :, 1] # [N,M] union = area1[:, None] + area2 - inter # [N,M] iou = inter / union return iou, union
def generalized_box_iou(boxes1, boxes2): """ Generalized IoU from https://giou.stanford.edu/ The boxes should be in [x0, y0, x1, y1] format Returns a [N, M] pairwise matrix, where N = len(boxes1) and M = len(boxes2) """ # degenerate boxes gives inf / nan results # so do an early check assert (boxes1[:, 2:] >= boxes1[:, :2]).all() assert (boxes2[:, 2:] >= boxes2[:, :2]).all() # vallina box iou # modified from torchvision to also return the union area1 = box_area(boxes1) area2 = box_area(boxes2) lt = torch.max(boxes1[:, None, :2], boxes2[:, :2]) # [N,M,2] rb = torch.min(boxes1[:, None, 2:], boxes2[:, 2:]) # [N,M,2] wh = (rb - lt).clamp(min=0) # [N,M,2] inter = wh[:, :, 0] * wh[:, :, 1] # [N,M] union = area1[:, None] + area2 - inter iou = inter / union # iou, union = box_iou(boxes1, boxes2) lt = torch.min(boxes1[:, None, :2], boxes2[:, :2]) rb = torch.max(boxes1[:, None, 2:], boxes2[:, 2:]) wh = (rb - lt).clamp(min=0) # [N,M,2] area = wh[:, :, 0] * wh[:, :, 1] return iou - (area - union) / area
def clip_iou(boxes1, boxes2): area1 = box_area(boxes1) area2 = box_area(boxes2) lt = torch.max(boxes1[:, :2], boxes2[:, :2]) rb = torch.min(boxes1[:, 2:], boxes2[:, 2:]) wh = (rb - lt).clamp(min=0) inter = wh[:, 0] * wh[:, 1] union = area1 + area2 - inter iou = (inter + 1e-6) / (union + 1e-6) # generalized version # iou=iou-(inter-union)/inter return iou
def _box_inter_union(boxes1: np.array, boxes2: np.array) -> Tuple[np.array, np.array]: area1 = box_area(boxes1) area2 = box_area(boxes2) lt = np.maximum(boxes1[:, None, :2], boxes2[:, :2]) # [N,M,2] rb = np.minimum(boxes1[:, None, 2:], boxes2[:, 2:]) # [N,M,2] wh = (rb - lt).clip(min=0) # [N,M,2] inter = wh[:, :, 0] * wh[:, :, 1] # [N,M] union = area1[:, None] + area2 - inter return inter, union
def __call__(self, boxes1: PascalBoxes, boxes2: PascalBoxes) -> t.Tuple[Tensor, Tensor]: area1 = box_area(boxes1) area2 = box_area(boxes2) lt = torch.max(boxes1[:, None, :2], boxes2[:, :2]) # [N,M,2] rb = torch.min(boxes1[:, None, 2:], boxes2[:, 2:]) # [N,M,2] wh = (rb - lt).clamp(min=0) # [N,M,2] inter = wh[:, :, 0] * wh[:, :, 1] # [N,M] union = area1[:, None] + area2 - inter iou = inter / union return iou, union
def box_iou(boxes1, boxes2): area1 = box_area(boxes1) area2 = box_area(boxes2) lt = torch.max(boxes1[:, None, :2], boxes2[:, :2]) # [N,M,2] rb = torch.min(boxes1[:, None, 2:], boxes2[:, 2:]) # [N,M,2] wh = (rb - lt).clamp(min=0) # [N,M,2] inter = wh[:, :, 0] * wh[:, :, 1] # [N,M] union = area1[:, None] + area2 - inter iou = inter / union return iou, union
def box_iou_itemwise(bboxes1, bboxes2): # bboxes1: [*, 4] # bboxes2: [*, 4] area1 = box_area(bboxes1) area2 = box_area(bboxes2) lt = torch.max(bboxes1[..., :2], bboxes2[..., :2]) rb = torch.min(bboxes1[..., 2:], bboxes2[..., 2:]) sizes = rb - lt sizes = torch.clamp_min(sizes, 0) inter_area = torch.prod(sizes, dim=-1) return inter_area / (area1 + area2 - inter_area)
def _box_iou(boxes1: Tensor, boxes2: Tensor) -> Tuple[Tensor, Tensor]: # from https://github.com/facebookresearch/detr/blob/master/util/box_ops.py area1 = box_area(boxes1) area2 = box_area(boxes2) lt = torch.max(boxes1[:, None, :2], boxes2[:, :2]) # [N,M,2] rb = torch.min(boxes1[:, None, 2:], boxes2[:, 2:]) # [N,M,2] wh = (rb - lt).clamp(min=0) # [N,M,2] inter = wh[:, :, 0] * wh[:, :, 1] # [N,M] union = area1[:, None] + area2 - inter iou = inter / union return iou, union
def check_scene_boxes_validity(boxes, scene_size, size_thres=1, iou_thres=0.): """ Args: box (2D tensor): (num_boxes 4) (x1, y1, x2, y2) x->W y->H scene_size (tuple or list): (H W) """ max_h, max_w = scene_size inside_boundary = (boxes[:, 0] < (max_w - 1)) & \ (boxes[:, 1] < (max_h - 1)) & \ (boxes[:, 2] < (max_w + 1)) & \ (boxes[:, 3] < (max_h + 1)) & \ ((boxes[:, 2] - boxes[:, 0]) > size_thres) & \ ((boxes[:, 3] - boxes[:, 1]) > size_thres) # should greater than 0 pos_check = (boxes >= 0).all(dim=1) inside_boundary = inside_boundary & pos_check # remove lower scoring boxes have an IoU greater than iou_thres with another (higher scoring) box. score = ops_box.box_area(boxes) nms_sorted = ops_box.nms(boxes, score, iou_thres) nms_keep = torch.zeros(boxes.size(0)).type(torch.BoolTensor).to(boxes.device) nms_keep[nms_sorted] = True valid_index = inside_boundary & nms_keep # if torch.sum(valid_index).item() == 0: # return inside_boundary return valid_index
def __call__(self, boxes1: PascalBoxes, boxes2: PascalBoxes) -> t.Tuple[Tensor, Tensor]: area1 = box_area(boxes1) area2 = box_area(boxes2) lt = torch.max(boxes1[:, :2], boxes2[:, :2]) # [N,M,2] rb = torch.min(boxes1[:, 2:], boxes2[:, 2:]) # [N,M,2] wh = (rb - lt).clamp(min=0) # [N,M,2] inter = wh[:, 0] * wh[:, 1] # [N,M] union = area1 + area2 - inter iou = inter / union if self.size_average: iou = iou.mean() return 1 - iou, union
def box_iou(boxes1, boxes2): area1 = box_area(boxes1) # [N]? area2 = box_area(boxes2) # [N]? # TODO: look into dimensions with breakpoint() # I think they don't use convex-hulls, instead they do the smallest upright box # containing both: the target and the predicted boxes lt = torch.max(boxes1[:, None, :2], boxes2[:, :2]) # [N,M,2] rb = torch.min(boxes1[:, None, 2:], boxes2[:, 2:]) # [N,M,2] wh = (rb - lt).clamp(min=0) # [N,M,2] inter = wh[:, :, 0] * wh[:, :, 1] # [N,M] union = area1[:, None] + area2 - inter iou = inter / union return iou, union
def iou(box1, box2): """ Returns the iou between two boxes """ area1 = box_area(box1) area2 = box_area(box2) top_left = torch.max(box1[:, None, :2], box2[:, :2]) # remove None! very Irritating bottom_right = torch.min(box1[:, None, 2:], box2[:, 2:]) # remove None! Very Irritating wh = (bottom_right - top_left).clamp(min=0) inter = wh[:, :, 0] * wh[:, :, 1] union = area1 + area2 - inter #check this iou = inter / union return iou, union
def box_iof(boxes1, boxes2): """ difference with iou is we divide total area of boxes1 by its intersection with boxes2 """ area1 = box_area(boxes1) #[N, ] area2 = box_area(boxes2) #[M, ] lt = torch.max(boxes1[:, None, :2], boxes2[:, :2]) # [N,M,2] rb = torch.min(boxes1[:, None, 2:], boxes2[:, 2:]) # [N,M,2] wh = (rb - lt).clamp(min=0) # [N,M,2] inter = wh[:, :, 0] * wh[:, :, 1] # [N,M] # union = area1[:, None] + area2 - inter # import pdb # pdb.set_trace() # [N, M] / [N, ] iou = inter / area1.unsqueeze(-1).expand_as(inter) return iou
def box_iou(boxes1, boxes2): """ :param boxes1: (N, 4) (x1,y1,x2,y2) :param boxes2: (N, 4) (x1,y1,x2,y2) :return: """ area1 = box_area(boxes1) # (N,) area2 = box_area(boxes2) # (N,) lt = torch.max(boxes1[:, :2], boxes2[:, :2]) # (N,2) rb = torch.min(boxes1[:, 2:], boxes2[:, 2:]) # (N,2) wh = (rb - lt).clamp(min=0) # (N,2) inter = wh[:, 0] * wh[:, 1] # (N,) union = area1 + area2 - inter iou = inter / union return iou, union
def __call__(self, boxlists): """ Arguments: boxlists (list[BoxList]) """ # Compute level ids s = torch.sqrt(torch.cat([box_area(boxlist) for boxlist in boxlists])) # Eqn.(1) in FPN paper target_lvls = torch.floor(self.lvl0 + torch.log2(s / self.s0 + self.eps)) target_lvls = torch.clamp(target_lvls, min=self.k_min, max=self.k_max) return target_lvls.to(torch.int64) - self.k_min
def __call__(self, boxlists): """ Args: boxlists (list[BoxList]) """ # Compute level ids s = torch.sqrt(torch.cat([box_area(boxlist.view(1, 4)) for boxlist in boxlists])) # Eqn.(1) in FPN paper target_lvls = torch.floor(self.lvl0 + torch.log2(s / self.s0) + torch.tensor(self.eps, dtype=s.dtype)) target_lvls = torch.clamp(target_lvls, min=self.k_min, max=self.k_max) return (target_lvls.to(torch.int64) - self.k_min).to(torch.int64)
def area(self): return box_area(self.bbox_xyxy)