在faster-rcnn 中涉及了 IOU 的计算,而 IOU 就是要先计算相交面积。
在detectron 的源码中,仅仅用了几行代码就实现了 anchor 集合 和 gt_boxes 集合的相交面积矩阵计算
代码位置如下
# boxes1 代表的是 gt_boxes
# boxes2 代表的是 系统生成的 上万个 anchor
def pairwise_intersection(boxes1: Boxes, boxes2: Boxes) -> torch.Tensor:
"""
Given two lists of boxes of size N and M,
compute the intersection area between __all__ N x M pairs of boxes.
The box order must be (xmin, ymin, xmax, ymax)
Args:
boxes1,boxes2 (Boxes): two `Boxes`. Contains N & M boxes, respectively.
Returns:
Tensor: intersection, sized [N,M].
"""
boxes1, boxes2 = boxes1.tensor, boxes2.tensor
width_height = torch.min(boxes1[:, None, 2:], boxes2[:, 2:]) - torch.max(
boxes1[:, None, :2], boxes2[:, :2]
) # [N,M,2]
width_height.clamp_(min=0) # [N,M,2]
intersection = width_height.prod(dim=2) # [N,M]
return intersection
其中最为关键的代码行:
width_height = torch.min(boxes1[:, None, 2:], boxes2[:, 2:]) - torch.max(
boxes1[:, None, :2], boxes2[:, :2]
代码分步解释:
取了boxes1 的右下角坐标,并且扩了一个纬度。 假如有139 个 标注框,那么这里的shape 是:[139,1,2]
取了boxes2的右下角坐标 。 假如有 319200 个 anchor,那么这里的shape 是: [319200,2]
这个时候做 torch.min 运算,须先 broadcasting 整个向量,相当于变成:
boxes1 [139,319200,2]
boxes2 [ 139,319200,2]
这两个向量做 min 运算,详细怎么做broadcasting 可参见: https://numpy.org/devdocs/user/theory.broadcasting.html
torch.min(boxes1[:, None, 2:], boxes2[:, 2:])
# 这个代码雷同上面的代码,但由于冒号的位置相反了,所以取的是左上角的坐标
torch.max( boxes1[:, None, :2], boxes2[:, :2]
过滤掉 负数向量即面积为0
宽和高相乘得到相交面积
width_height.clamp_(min=0) # [N,M,2]
intersection = width_height.prod(dim=2) # [N,M]
结果示意图