该文章分析的非常好,这里做个记录保存;
主要思路:从一维的集合求解拓展至二维的集合求解,求出交并比IOU;
IoU 的全称为交并比(Intersection over Union),通过这个名称我们大概可以猜到 IoU 的计算方法。IoU 计算的是 “预测的边框” 和 “真实的边框” 的交集和并集的比值。
开始计算之前,我们首先进行分析下交集和并集到底应该怎么计算:我们首先需要计算交集,然后并集通过两个边框的面积的和减去交集部分即为并集,因此 IoU 的计算的难点在于交集的计算。大部分人可能会对两张图像的位置进行分类分析,从而针对不同情况进行不同求解,这样考虑两个边框的相对位置,然后按照相对位置(左上,左下,右上,右下,包含,互不相交)分情况讨论,来计算交集。
原文作者的吐槽:上图就是你的直觉,这样想没有错。但计算一个交集,就要分多种情况讨论,要是程序真的按照这逻辑编写就太搞笑了。因此对这个问题进行进一步地研究显得十分有必要。
让我们重新思考一下两个框交集的计算。两个框交集的计算的实质是两个集合交集的计算,因此我们可以将两个框的交集的计算简化为:
将上面求解交集问题分解为两个方向的一维求交集的问题即可,代码如下:
def iou(set_a, set_b):
'''
一维 iou 的计算
'''
x1, x2 = set_a # (left, right)
y1, y2 = set_b # (left, right)
low = max(x1, y1)
high = min(x2, y2)
# intersection
if high-low<0:
inter = 0
else:
inter = high-low
# union
union = (x2 - x1) + (y2 - y1) - inter
# iou
iou = inter / union
return iou
上面,我们计算了两个一维集合的 iou,将上面的程序进行扩展,即可得到两个框 IoU 计算的程序。
def iou(box1, box2):
'''
两个框(二维)的 iou 计算
注意:边框以左上为原点
box:[top, left, bottom, right]
'''
in_h = min(box1[2], box2[2]) - max(box1[0], box2[0])
in_w = min(box1[3], box2[3]) - max(box1[1], box2[1])
inter = 0 if in_h<0 or in_w<0 else in_h*in_w
union = (box1[2] - box1[0]) * (box1[3] - box1[1]) + \
(box2[2] - box2[0]) * (box2[3] - box2[1]) - inter
iou = inter / union
return iou
可以看到,代码非常的简洁明了!!!
可以简单测试一下,例如:
box1 = [ 0,0, 100,100 ] , box2 = [50,50, 150,150 ],
结果即为1/7