IOU计算

jupiter
2021-02-19 / 0 评论 / 1,034 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2021年12月07日,已超过1080天没有更新,若内容或图片失效,请留言反馈。

IOU计算&判断两个矩形相交以及求出相交的区域

求解图示一

$$ IOU=area/(area1+area2-area) $$

求解图示二

理论分析-判断两个矩形相交以及求出相交的区域

问题:给定两个矩形A和B,矩形A的左上角坐标为(Xa1,Ya1),右下角坐标为(Xa2,Ya2),矩形B的左上角坐标为(Xb1,Yb1),右下角 坐标为(Xb2,Yb2)。

1.设计一个算法,确定两个矩形是否相交(即有重叠区域)

对于这个问题,一般的思路就是判断一个矩形的四个顶点是否在另一个矩形的区域内。这个思路最简单,但是效率不高,并且存在错误,错误在哪里,下面分析一 下。

如上图,把矩形的相交(区域重叠)分成三种(可能也有其他划分),对于第三种情况,如图中的(3),两个矩形相交,但并不存在一个矩形的顶点在另一个矩形 内部。所以那种思路存在一个错误,对于这种情况的相交则检查不出。

仔细观察上图,想到另一种思路,那就是判断两个矩形的中心坐标的水平和垂直距离,只要这两个值满足某种条件就可以相交。
矩形A的宽 Wa = Xa2-Xa1 高 Ha = Ya2-Ya1
矩形B的宽 Wb = Xb2-Xb1 高 Hb = Yb2-Yb1
矩形A的中心坐标 (Xa3,Ya3) = ( (Xa2+Xa1)/2 ,(Ya2+Ya1)/2 )
矩形B的中心坐标 (Xb3,Yb3) = ( (Xb2+Xb1)/2 ,(Yb2+Yb1)/2 )
所以只要同时满足下面两个式子,就可以说明两个矩形相交。

1) | Xb3-Xa3 | <= Wa/2 + Wb/2
2) | Yb3-Ya3 | <= Ha/2 + Hb/2

即:
| Xb2+Xb1-Xa2-Xa1 | <= Xa2-Xa1 + Xb2-Xb1
| Yb2+Yb1-Ya2-Ya1 | <=Y a2-Ya1 + Yb2-Yb1

2.如果两个矩形相交,设计一个算法,求出相交的区域矩形

Xc1 = max(Xa1,Xb1)
Yc1 = max(Ya1,Yb1)
Xc2 = min(Xa2,Xb2)
Yc2 = min(Ya2,Yb2)
这样就求出了矩形的相交区域。
另外,注意到在不假设矩形相交的前提下,定义(Xc1,Yc1),(Xc2,Yc2),且Xc1,Yc1,Xc2,Yc2的值由上面四个式子得出。这样, 可以依据Xc1,Yc1,Xc2,Yc2的值来判断矩形相交。
Xc1,Yc1,Xc2,Yc2只要同时满足下面两个式子,就可以说明两个矩形相交。
3) Xc1 <= Xc2
4) Yc1 <= Yc2
即:
max(Xa1,Xb1) <= min(Xa2,Xb2)
max(Ya1,Yb1) <= min(Ya2,Yb2)

代码实现

代码

"""
IOU计算
+ input
  + box1:[box1_x1,box1_y1,box1_x2,box1_y2]
  + box2:[box2_x1,box2_y1,box2_x2,box2_y2]
+ output
  + iou值
"""

def cal_iou(box1,box2):
    # 判断是否能相交
    if abs(box2[2]+box2[0]-box1[2]-box1[0])>box2[2]-box2[0]+box1[2]-box1[0]:
        return 0
    if abs(box2[3]+box2[1]-box1[3]-box1[1])>box2[3]-box2[1]+box1[3]-box1[1]:
        return 0
    
    # 求相交区域左上角的坐标和右下角的坐标
    box_intersect_x1 = max(box1[0], box2[0])
    box_intersect_y1 = max(box1[1], box2[1])
    box_intersect_x2 = min(box1[2], box2[2])
    box_intersect_y2 = min(box1[3], box2[3])
    
    # 求二者相交的面积
    area_intersect = (box_intersect_y2 - box_intersect_y1) * (box_intersect_x2 - box_intersect_x1)
    
    # 求box1,box2的面积
    area_box1 = (box1[2] - box1[0]) * (box1[3] - box1[1])
    area_box2 = (box2[2] - box2[0]) * (box2[3] - box2[1])
    
    # 求二者相并的面积
    area_union = area_box1 + area_box2 - area_intersect
    
    # 计算iou(交并比)
    iou = area_intersect / area_union
    
    return iou

验证

box1 = [0,0,500,500]
box2 = [250,250,750,750]
iou = cal_iou(box1,box2)
print(iou)
0.14285714285714285

人为验证

图示

import matplotlib.pyplot as plt
fig1 = plt.figure()
ax1 = fig1.add_subplot(111, aspect='equal')
ax1.add_patch(plt.Rectangle((0, 0),500,500,color='b',alpha=0.5))
ax1.add_patch(plt.Rectangle((250, 250),500,500,color='b',alpha=0.5))
ax1.add_patch(plt.Rectangle((250, 250),250,250,color='r',alpha=0.5))
plt.xlim(0, 750)
plt.ylim(0, 750)
plt.show()

由图易知:

  • area_box1= 250000
  • area_box2= 250000
  • area_intersect= 62500
  • area_union= 437500

因此:

  • iou = 62500 / 437500 = 0.14285714285714285

参考资料

  1. yolo 算法中的IOU算法程序与原理解读:https://blog.csdn.net/caokaifa/article/details/80724842
  2. IOU的计算:https://www.cnblogs.com/darkknightzh/p/9043395.html
  3. 判断两个矩形相交以及求出相交的区域:https://www.cnblogs.com/zhoug2020/p/7451340.html
0

评论 (0)

打卡
取消