以下函数是计算两两锚框之间的IOU,但是有两行代码看了好久,记录一下,怕下次又不理解了。。(哭泣)
def box_iou(boxes1, boxes2):
#计算两个锚框或边界框列表中成对的交并⽐
#boxes形状:(boxes数量,4)4表示每个锚框的左上(x,y)、右下坐标(x, y)。
#areas形状:(box数量,)
box_area = lambda boxes: ((boxes[:, 2] - boxes[:, 0])) * ((boxes[:, 3] - boxes[:, 1]))
areas1 = box_area(boxes1)
areas2 = box_area(boxes2)
print(boxes1[:, None, :2])
print(boxes2[:, :2])
inter_upperlefts = torch.max(boxes1[:, None, :2], boxes2[:, :2])
print(f'inter_upperlefts:{inter_upperlefts}')
# `inter_upperlefts`, `inter_lowerrights`, `inters`的形状:
# (boxes1的数量, boxes2的数量, 2)
inter_lowerrights = torch.min(boxes1[:, None, 2:], boxes2[:, 2:])
inters = (inter_lowerrights - inter_upperlefts).clamp(min=0)
inter_areas = inters[:, :, 0] * inters[:, :, 1]
union_areas = areas1[:, None] + areas2 - inter_areas
return inter_areas / union_areas
box1 = torch.tensor([[67.50, 67.50, 433.50, 433.50],
[128.50, 128.50, 372.50, 372.50]])
box2 = torch.tensor([[ -8.30, 121.10, 509.30, 379.90],
[189.50, 189.50, 311.50, 311.50]])
c = box_iou(box1, box2)
输出结果:
tensor([[[ 67.50, 67.50]],
[[128.50, 128.50]]])
tensor([[ -8.30, 121.10],
[189.50, 189.50]])
inter_upperlefts:tensor([[[ 67.50, 121.10],
[189.50, 189.50]],
[[128.50, 128.50],
[189.50, 189.50]]])
boxes1[:, None, :2]是一个2*1*2的形状,也就是None给Tensor增加了一个维度,boxes2[:, :2]是一个2*2的形状,当torch.max()对两者作用时,会触发广播机制,将两者进行扩充,最终输出的inter_upperlefts形状为2*2*2。
具体点,就是将boxes1中的每个左上坐标,跟boxes2中所有锚框的左上坐标进行比较,取得最大值。
以代码为例,传入的是2*2也就是每个boxes中含有两个锚框,因此在执行上述代码时,会对boxes1和boxes2进行广播,均变成2*2*2。图中的标号代表广播时,将boxes1中的前左上坐标“一个一个”复制n份(n为锚框个数),而boxes2中的左上坐标是“一份一份”的进行复制,这样对应起来就是boxes1中的每一个在跟boxes2中的每一个进行比较后取最大值。在这个过程中要比较(boxes1中锚框个数*boxes2中锚框个数)次,最终inter_leftrights中存储的就是两两比较后的较大左上坐标,inter_lowerrights中存储的两两比较后的较小右下坐标。两者相减再相乘就是两两锚框之间的相交面积。
(emm,描述起来好多字hhh)