常见box loss汇总

传统回归loss都是回归表征一个矩形框的四个变量,但这基于一个过于简化的假设,即这四个变量之间是相互独立的。实际上,这四个变量之间是相互关联的,简单的分开计算每个变量的回归loss无法反映这种相关性,而将预测框与GT框之间的iou引入回归loss则很好的解决了这一问题。

一、IOU Loss

IOU Loss,即预测框与GT框之间的交集/预测框与GT框之间的并集,这种损失函数会存在一些问题,具体的问题如下图所示:
在这里插入图片描述

1)当预测框和GT框不相交时(即IOU=0),此时该损失函数不可导,即IOU_Loss无法优化两个框不相交的情况。
2)当两个预测框尺寸且交集范围一致时,IOU_Loss也保持一致,无法区分两者相交这种情况。(无法区分这两种情况,会导致什么问题?)
在这里插入图片描述

二、GIoU Loss

对于两个任意形状的物体A和B,我们计算包括A和B的最小凸包形状C。直观上来说,IOU的弱点是指的是当A和B的交集为0时,失去目标,所以GIOU就是防止这种情况:C的面积中A∪B的面积占比越大越好。
在这里插入图片描述
在这里插入图片描述

三、DIoU Loss

当两个框处于包含关系时,GIOU-Loss退化为IOU。导致在包含的时候,优化变得困难,特别是在水平和垂直方向收敛难。DIOU在GIOU基础上加入了anchor框与目标框之间的归一化距离。
在这里插入图片描述

四、CIoU Loss

当GT框包裹预测框时,此时预测框的中心点的位置都是一样的。因此,按照DIoU Loss的计算公式,三者的值都是相同。为了解决这个问题,CIoU Loss在DIoU Loss的基础上增加了一个影响因子,将预测框和GT框的长宽也考虑进来。
在这里插入图片描述
在这里插入图片描述

Box Loss代码

import math
import torch
#pytorch版本
def bbox_iou(box1, box2, x1y1x2y2=True, GIoU=False, DIoU=False, CIoU=False):
    # Returns the IoU of box1 to box2. box1 is 4, box2 is nx4
    box2 = box2.t()

    # Get the coordinates of bounding boxes
    if x1y1x2y2:  # x1, y1, x2, y2 = box1
        b1_x1, b1_y1, b1_x2, b1_y2 = box1[0], box1[1], box1[2], box1[3]
        b2_x1, b2_y1, b2_x2, b2_y2 = box2[0], box2[1], box2[2], box2[3]
    else:  # transform from xywh to xyxy
        b1_x1, b1_x2 = box1[0] - box1[2] / 2, box1[0] + box1[2] / 2
        b1_y1, b1_y2 = box1[1] - box1[3] / 2, box1[1] + box1[3] / 2
        b2_x1, b2_x2 = box2[0] - box2[2] / 2, box2[0] + box2[2] / 2
        b2_y1, b2_y2 = box2[1] - box2[3] / 2, box2[1] + box2[3] / 2

    # 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:并集的面积
    w1, h1 = b1_x2 - b1_x1, b1_y2 - b1_y1
    w2, h2 = b2_x2 - b2_x1, b2_y2 - b2_y1
    union = (w1 * h1 + 1e-16) + w2 * h2 - inter

    # iou的计算公式
    iou = inter / union  
    if GIoU or DIoU or CIoU:
        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 GIoU:  # Generalized IoU https://arxiv.org/pdf/1902.09630.pdf
            c_area = cw * ch + 1e-16  # convex area
            return iou - (c_area - union) / c_area  # GIoU
        if DIoU or CIoU:  # Distance or Complete IoU https://arxiv.org/abs/1911.08287v1
            # convex diagonal squared
            c2 = cw ** 2 + ch ** 2 + 1e-16
            # centerpoint distance squared
            rho2 = ((b2_x1 + b2_x2) - (b1_x1 + b1_x2)) ** 2 / 4 + ((b2_y1 + b2_y2) - (b1_y1 + b1_y2)) ** 2 / 4
            if DIoU:
                return iou - rho2 / c2  # DIoU
            elif 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 / (1 - iou + v)
                return iou - (rho2 / c2 + v * alpha)  # CIoU

    return iou

#numpy版本
def bbox_iou_libra(box1, box2, GIOU =False, DIOU =False, CIOU =False):
    eps = 1e-6
    b1_x1, b1_y1, b1_x2, b1_y2 = box1[0], box1[1], box1[2], box1[3]
    b2_x1, b2_y1, b2_x2, b2_y2 = box2[0], box2[1], box2[2], box2[3]
    inter = (min(b1_x2, b2_x2) - max(b1_x1, b2_x1) ).clamp(0) *(min(b1_y2 - b1_y2) - max(b2_y1 - b1_y1)).clamp(0)

    w1, h1 = b1_x2 - b1_x1, b1_y2 - b1_y1
    w2, h2 = b2_x2 - b2_x1, b2_y2 - b2_y1
    union = w1*h1 + w2*h2 + eps - inter
    iou = inter / union

    ##计算外界矩形面积
    cw = max(b1_x2, b2_x2) - min(b1_x1, b2_x1)
    cy = max(b1_y2, b2_y2) - min(b1_y1, b2_y1)
    if GIOU:
        c_area = cw*cy + eps
        return iou - (c_area - union)/c_area
    if DIOU or CIOU:
        c2 = cw**2 + cy**2 + eps
        rho2 = ( (b2_x1 + b2_x2) + (b1_x1 + b1_x2))**2 /4 + ((b2_y1 + b2_y2) - (b1_y1 + b1_y2)) ** 2 / 4
        if DIOU:
            return iou - rho2/c2

        elif CIOU:
            v = (4 / math.pi ** 2) * pow(math.atan(w2 / h2) - math.atan(w1 / h1), 2)
            with torch.no_grad():
                alpha = v / (1 - iou + v)
            return iou - (rho2 / c2 + v * alpha)  # CIoU

参考链接:https://mp.weixin.qq.com/s/YQ0Uo3bVwBX4kIgpOI2dZw

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值