IoU及其变体

IoU

IoU简介

IoU (Intersection over Union),又称为交并比,常被用于目标检测中正样本分配、AP计算、非极大值抑制过程中,它就是评估预测框与GT框之间的重合度,IoU值越大,说明预测框更加精确。

假设A是gt框,B为预测框,那么IoU的计算公式为:
IoU=SASBSA+SBSASB IoU = \frac{S_A \cap S_B}{S_A + S_B - S_A \cap S_B}

iou可视化iou可视化

如上图,IoU即为图中的深色重叠部分。

代码实现

def compute_iou(box1,box2):
    """
    :param box1: (x0,y0,x1,y1),分别对应框的(左,上,右,下)边界
           box2: (x0,y0,x1,y1)
    :return iou的值
    """
    assert(box1[2] > box1[0] and box1[3] > box1[1])
    assert(box2[2] > box2[0] and box2[3] > box2[1])
    # 分别计算两个框的面积
    S_1 = (box1[2] - box1[0])*(box1[3] - box1[1])
    S_2 = (box2[2] - box2[0])*(box2[3] - box2[1])

    # 总面积
    sum_area = S_1 + S_2

    # 计算相交区域面积
    left = max(box1[0],box2[0])
    top = max(box1[1],box2[1])
    right = min(box1[2],box2[2])
    bottom = min(box1[3],box2[3])

    if left >= right or top >= bottom:
        return 0.
    else:
        intersect = (right - left)*(bottom - top)
        return intersect / (sum_area - intersect)

IoU的优点

iou的尺度不变性iou的尺度不变性

目标检测中,回归loss相同的情况下,IoU可能大不相同,上图中的各种相交框的情况中,l2或l1的距离相同,但是IoU值不同。
满足度量函数的性质,满足非负性;同一性;对称性;三角不等性。

IoU存在的问题

  1. 如果两个目标没有重叠,IoU将会为0,并且不会反应两个目标之间的距离,在这种情况下,如果将IoU作为损失函数,梯度为0,无法优化。
  2. IoU无法区分两个对象之间不同的对齐方式,例如,两个不同方向上的物体可能会和同一个预测框的IoU相同,如下图所示。也可以理解为,下面三种情况的IoU相同,相比之下,左边的图回归效果更好。
    iou存在的问题iou存在的问题

GIoU

为了解决IoU无法直接优化的问题,Generalized Intersection over Union: A Metric and A Loss for Bounding Box Regression 2019 CVPR提出GIoU。
GIoU的计算公式为:
GIoU=IoUAcUAc GIoU = IoU - \frac{|A_c - U|}{A_c} AcA_c表示两个框的最小闭包区域面积,即同时包含了预测框和真实框的最小框的面积。再计算闭包区域中不属于两个框的区域占闭包区域的比重,最后用IoU减去这个比重。

代码实现

def compute_generalized_iou(box1,box2):
    """
    :param
        box1 (x0,y0,x1,y1) 分别表示框的左、上、右、下边界。
        box2 (x0,y0,x1,y1)
    :return 
        giou
    """

    assert(box1[2] > box1[0] and box1[3] > box1[1])
    assert(box2[2] > box2[0] and box2[3] > box2[1])

    # 计算相交区域面积
    left = max(box1[0],box2[0])
    top = max(box1[1],box2[1])
    right = min(box1[2],box2[2])
    bottom = min(box1[3],box2[3])

    if left >= right or top >= bottom:
        intersect = 0
    else:
        intersect = (right - left)*(bottom - top)

    # 闭包区域
    area_c = (max(box1[2],box2[2]) - min(box1[0],box2[0])) * (max(box1[3],box2[3]) - min(box1[1],box2[1]))

    # 分别计算两个框的面积
    S_1 = (box1[2] - box1[0])*(box1[3] - box1[1])
    S_2 = (box2[2] - box2[0])*(box2[3] - box2[1])

    # 总面积
    sum_area = S_1 + S_2
    giou = intersect/(sum_area - intersect) - ((area_c - (sum_area - intersect))/area_c)
    return giou

GIoU的优点

  • 与IoU相似,GIoU也是一种距离度量,作为损失函数的话,LGIoU=1GIoUL_{GIoU} = 1 - GIoU,满足损失函数的基本要求;
  • GIoU对scale不敏感;
  • GIoU是IoU的下界,在两个框无限重叠的情况下,GIoU = IoU = 1
  • IoU取值为[0,1],但是GIoU有对称区间,取值范围[-1,1],两个框无限远的时候取最小值-1,因此GIoU是非常好的距离度量指标。
  • IoU只关注重叠区域,GIoU在此基础上,还考虑其他非重叠区域,能更好地反应二者的重合度。

GIoU存在问题

  • 存在两个框的闭包,等于两个框的并集,此时GIoU退化为IoU,如下图:
    giou存在的问题giou存在的问题

    或者一个框被另一个框包围,如下图:
    giou存在的问题giou存在的问题

DIoU(Distance-IoU)

对于上述GIoU存在的问题,Distance-IoU Loss: Faster and Better Learning for Bounding Box Regression提出DIoU,考虑了两个框闭包的大小,以及两个框中心点的距离,如下图:

diou展示diou展示

图中,d表示两个框中心点距离,c表示闭包区域的对角线距离,DIoU引入了两个框中心点距离以缓解上述GIoU存在的问题。

DIoU=IoUp2(b,bgt)c2 DIoU = IoU - \frac{p^2(b,b^{gt})}{c^2}

代码实现

def compute_distanceiou(box1,box2):
    """
    :param
        box1 (x0,y0,x1,y1) 分别表示框的左、上、右、下边界。
        box2 (x0,y0,x1,y1)
    :return 
        giou
    """
    assert(box1[2] > box1[0] and box1[3] > box1[1])
    assert(box2[2] > box2[0] and box2[3] > box2[1])

    # 计算相交区域面积
    left = max(box1[0],box2[0])
    top = max(box1[1],box2[1])
    right = min(box1[2],box2[2])
    bottom = min(box1[3],box2[3])

    if left >= right or top >= bottom:
        intersect = 0
    else:
        intersect = (right - left)*(bottom - top)

    
    # 计算中心点
    center_x1 = (box1[0] + box1[2])/2
    center_y1 = (box1[1] + box1[3])/2
    center_x2 = (box2[0] + box2[2])/2
    center_y2 = (box2[1] + box2[3])/2

    # 中心点之间的距离
    center_diag = (center_x2 - center_x1)**2 + (center_y2 - center_y1)**2
    # 闭包区域的对角线长度
    outer_diag = (max(box1[2],box2[2]) - min(box1[0],box2[0]))**2 + (max(box1[3],box2[3]) - min(box1[1],box2[1]))**2
    

    # 分别计算两个框的面积
    S_1 = (box1[2] - box1[0])*(box1[3] - box1[1])
    S_2 = (box2[2] - box2[0])*(box2[3] - box2[1])

    # 总面积
    sum_area = S_1 + S_2
    diou = intersect/(sum_area - intersect) - center_diag/outer_diag
    return diou 

优点

  • DIoU直接优化两个框的距离,收敛速度比GIoU快,特别是两个框存在包裹的情况。

CIoU (Complete-IoU)

CIoU在DIoU的基础上,还考虑长宽比。
CIoU=IoUp2(b,bgt)c2αv CIoU = IoU - \frac{p^2(b,b^{gt})}{c^2} - \alpha v 其中α\alpha为权重系数,vv用来度量长宽比的相似性,定义为:
v=4π2(arctanwgthgtarctanwh)2 v = \frac{4}{\pi^2}(arctan \frac{w^{gt}}{h^{gt}} - arctan \frac{w}{h})^2