bbox loss

目标检测任务中 bbox 的预测 采用回归损失实现,可分为 L1 L2 SmoothL1 等

三种损失求导,分析对 loss 的影响

L1:导数恒等于 -1 1,在训练后期,来回震荡,无法收敛到足够精细的值

L2:在前期,x(loss) 较大,收敛过快,容易过拟合

SmoothL1:对L1进行平滑,其实就是 融合了 L1 L2 ,在 x 较大时,导数 恒等于 -1 1,即 L1,在 x 较小时,导数变成 x,即 L2

 

在 bbox 评价时采用的是 IOU,由于 之前的 loss 和 评价方式不同,故后来把 loss 变成了 IOU loss

Liou = 1 - IOU

 

IOU 

 

def iou(rec1, rec2):
    """
    rec1: [left1,top1,right1,bottom1]
    rec2: [left2,top2,right2,bottom2]
    """
    # 重合部分
    left_max = max(rec1[0], rec2[0])
    top_max = max(rec1[1], rec2[1])
    right_min = min(rec1[2], rec2[2])
    bottom_min = min(rec1[3], rec2[3])
    # 两矩形相交时计算IoU
    if (left_max > right_min or bottom_min < top_max):  # 没有交集
        return 0
    else:
        rect1_area = (rec1[2] - rec1[0]) * (rec1[3] - rec1[1])
        rect2_area = (rec2[2] - rec2[0]) * (rec2[3] - rec2[1])
        area_cross = (bottom_min - top_max) * (right_min - left_max)
        return area_cross / (rect1_area + rect2_area - area_cross)

 

存在问题

1. 无法解决两个目标无重叠的问题,如果两个目标没有重叠,iou 为 0,loss 恒为 1,微调位置 无法反应 两目标之间的位置变化,也就是说 IOU loss 无法反应 两个框 之间的距离

2.iou 无法区分 两个目标 的对齐方式,不同的对齐方式下,iou 可能相等,如下图

GIOU

当 AB 完全重合时,IOU = 1,后半部分为0,GIOU = 1,loss = 0;

当 AB 无重叠时,假设离得很远,AC 无穷大,u 在 AC 面前可忽略,IOU = 0,后半部分近似为1,GIOU = -1,loss = 2;

GIOU 取值 [-1, 1],Loss 取值 [0,2]

 

存在问题

1. GIOU 训练较慢

2. GIOU 倾向得到一个较大的 bbox

3. GIOU 区分两个对象之间的对齐方式比较间接,仅通过引入C的方式来反应重叠的方式,不够直接。如下图所示。第二幅图展示来当GIoU一样的情况下,DIoU是不一致的

DIOU  【Distance-IoU】

b 代表预测 bbox 的中心,bgt 代表 ground truth 的中心,分子ρ是 距离,c 是对角线长度

 

CIOU

在DIoU的基础上增加了对长宽比的惩罚项

 

 

EIOU

w=(w1-w2)*(w1-w2)
h=(h1-h2)*(h1-h2)
eiou = iou-(rho2/c2+w/(cw**2)+h/(ch**2))

Leiou = 1 - eiou  

 

这些 IOU 是效果越来越好 

 

 

 示例代码

def bbox_iou(box1, box2, xywh=True, GIoU=False, DIoU=False, CIoU=False, eps=1e-7):
    # Returns Intersection over Union (IoU) of box1(1,4) to box2(n,4)

    # Get the coordinates of bounding boxes
    if xywh:  # transform from xywh to xyxy
        (x1, y1, w1, h1), (x2, y2, w2, h2) = box1.chunk(4, 1), box2.chunk(4, 1)
        w1_, h1_, w2_, h2_ = w1 / 2, h1 / 2, w2 / 2, h2 / 2
        b1_x1, b1_x2, b1_y1, b1_y2 = x1 - w1_, x1 + w1_, y1 - h1_, y1 + h1_
        b2_x1, b2_x2, b2_y1, b2_y2 = x2 - w2_, x2 + w2_, y2 - h2_, y2 + h2_
    else:  # x1, y1, x2, y2 = box1
        b1_x1, b1_y1, b1_x2, b1_y2 = box1.chunk(4, 1)
        b2_x1, b2_y1, b2_x2, b2_y2 = box2.chunk(4, 1)
        w1, h1 = b1_x2 - b1_x1, b1_y2 - b1_y1 + eps
        w2, h2 = b2_x2 - b2_x1, b2_y2 - b2_y1 + eps

    # Intersection area
    inter = (torch.min(b1_x2, b2_x2) - torch.max(b1_x1, b2_x1)).clamp(0) * \
            (torch.min(b1_y2, b2_y2) - torch.max(b1_y1, b2_y1)).clamp(0)

    # Union Area
    union = w1 * h1 + w2 * h2 - inter + eps

    # IoU
    iou = inter / union
    if CIoU or DIoU or GIoU:
        cw = torch.max(b1_x2, b2_x2) - torch.min(b1_x1, b2_x1)  # convex (smallest enclosing box) width
        ch = torch.max(b1_y2, b2_y2) - torch.min(b1_y1, b2_y1)  # convex height
        if CIoU or DIoU:  # Distance or Complete IoU https://arxiv.org/abs/1911.08287v1
            c2 = cw ** 2 + ch ** 2 + eps  # convex diagonal squared
            rho2 = ((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2 + (b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4  # center dist ** 2
            if CIoU:  # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47
                v = (4 / math.pi ** 2) * torch.pow(torch.atan(w2 / h2) - torch.atan(w1 / h1), 2)
                with torch.no_grad():
                    alpha = v / (v - iou + (1 + eps))
                return iou - (rho2 / c2 + v * alpha)  # CIoU
            return iou - rho2 / c2  # DIoU
        c_area = cw * ch + eps  # convex area
        return iou - (c_area - union) / c_area  # GIoU https://arxiv.org/pdf/1902.09630.pdf
    return iou  # IoU

 

 

 

 

参考资料:

https://www.bilibili.com/video/BV1Ra411i7cw?spm_id_from=333.337.search-card.all.click&vd_source=f0fc90583fffcc40abb645ed9d20da32  目标检测iou loss 一网打尽    【讲得挺好】

 

https://blog.csdn.net/weixin_40922744/article/details/102988751  超简单的IoU python3实现

https://www.cnblogs.com/wojianxin/p/12581056.html  python实现IoU

https://blog.csdn.net/weixin_41735859/article/details/89288493  GIoU详解

https://zhuanlan.zhihu.com/p/57992040  CVPR2019: 使用GIoU作为检测任务的Loss

https://blog.csdn.net/liangdong2014/article/details/114380202  详解GIoU、DIoU、CIoU Loss

https://mp.weixin.qq.com/s/0U4Y_ZEI2YvW1sMHxRfwMQ  YOLOv5改进之七:损失函数改进