1:前言
深度学习的目标检测中,IOU表示先验框(bounding box)和真实框(Ground Truth)的交并比,在数学上就是表示两个框之间的交际和两个框的并集的比值。初中我们就知道,交集一定是小于或等于并集。在faster rcnn等目标检测框架中,经常用到这个东西,今天来实现一下。虽然网上有很多版本,都实现的很好,但是可以记录一下学习过程。
2:IOU分析
2.1 名词解释:
一共需要用到8个值,分别是如下的
,前四个是第一个框的坐标,后四个是第二个框的坐标,如图1所示。
图1:矩形的坐标
2.2.一共会出现四种情况:
其中两种情况会相交两种情况不相交。我把第一种叫做(左上右下型),第二种叫做(左下右上型),如图2所示:
图2:两个矩形之间的4种关系
2.3:IOU计算
1:(左上右下型)以图3为例,令中间这块矩形区域叫做中心区域,左图并没有交集,中心区域和任意矩形都不想交,右图表示两个矩形有交集,因此中心区域就是两者的交集。W,H分别表示中心区域的宽和高。
就算不知道两个矩形框的相对位置的情况下,一定满足W = xmin + width1 + width2 - xmax,以图3左图为例,xmin + width1 + width2 - xmax小于0,右图中,W=xmin + width1 + width2 - xmax大于0;同样左图H=ymin + height1 + height2 - ymax小于0,右图H=ymin + height1 + height2 - ymax大于0
最下面那个图W=xmin + width1 + width2 - xmax大于0;同样左图H=ymin + height1 + height2 - ymax小于0
可以判断,当W和H都为负数,表示左边的情况,没有交集;当W和H都为负数时,表示右边的情况,有交集;当W和H有一个是正数一个是负数的时候,也是没有交集的。
在代码上表示W和H都小于0,没有交集,其他有交集。if (w<=0 and H<=0)没有交集,返回0就行了;其他情况,就返回交并比。交集就是W*H,并集就是width1*height1+width2*height2-W*H,因为重合了一部分。最后IOU是
图3:左上右下型
def IOU( box1, box2 ):
"""
:box1:[x1,y1,x2,y2]# (x1,y1)表示左上角,(x2,y2)表示右下角
:box2:[x1,y1,x2,y2]
:return: iou_ratio交并比
"""
width1 = abs(box1[2] - box1[0])
height1 = abs(box1[1] - box1[3])
width2 = abs(box2[2] - box2[0])
height2 = abs(box2[1] - box2[3])
xmax = max(box1[0],box1[2],box2[0],box2[2])
ymax = max(box1[1],box1[3],box2[1],box2[3])
xmin = min(box1[0],box1[2],box2[0],box2[2])
ymin = min(box1[1],box1[3],box2[1],box2[3])
W = xmin + width1 + width2 - xmax
H = ymin + height1 + height2 - ymax
if W <= 0 or H <= 0: # 当H和W都小于等于0的时候没有交集,其他情况有交集。
iou_ratio = 0
else: #其他情况有交集
iou_area = W * H# 交集的面积
box1_area = width1 * height1
box2_area = width2 * height2
iou_ratio = iou_area / (box1_area + box2_area - iou_area) # 并集的面积
return iou_ratio
box1 = [1,3,4,1]
box2 = [2,4,5,2]
box3 = [1,1,3,3]
box4 = [3,3,5,5]
print("第一个IOU为:",IOU(box1,box2))
print("第二个IOU为:",IOU(box3,box4))
# 第一个IOU为:0.2
# 第二个IOU为:0
'''
代码参考了github上的。
如果给出的box是[xCenter,yCenter,Width,Height],中心点坐标和宽高,可以通过以下函数,转换成左上右下的坐标
'''
def exchange(box1):
x,y = box1[0],box1[1]
w,h = box1[2],box1[3]
box2 = []
box2.append(int(x-0.5*w))
box2.append(int(y-0.5*h))
box2.append(int(x+0.5*w))
box2.append(int(y+0.5*h))
return box2
1:(左下右上型)以图4为例。
我们发现,不管如何变化都会存在中心区域,而且同样满足:
W = xmin + width1 + width2 - xmax,H=ymin + height1 + height2 - ymax。也同样满足当W和H都小于0的时候,没有交集,其他情况有交集。因此,上面代码同样适合这种情况。
图4:左下右上型