CVPR2019:使用GIoU作为目标检测新loss

如今一些目标检测算法如YOLO v3已经都在用GIOU代替IOU进行损失计算并取得不错的效果,GIOU的思路简单而有效,今天我们就来解读一下CVPR19的这篇Generalized Intersection over Union: A Metric and A Loss for Bounding Box
Regression
提出的广义IoU-GIoU

目录

  • 背景及介绍
  • 算法流程及代码
  • 实验结果
  • 论文地址

背景及介绍

背景

The dominant trend for improving performance of applications utilizing deep neural networks is to propose either a better architecture backbone or a better strategy to extract reliable local features

正如作者论文中的这一句,如今许多人都专注如何设计一个更好的backbone或者更好地提取特征来提高检测模型的性能,但是他们却忽略了可以直接用IoU/GIoU来代替L范数损失函数,而作者也是以此为出发点提出了GIOU——generalized IoU

  • 如果在目标检测中使用L范数来作为度量标准,将会存在两个检测框L范数的绝对值相同而效果却大不相同的情况,而且L范数对物体的scale比较敏感,而IoU或者GIoU则可以比较好地度量检测框的**“精准”**,具体见下图(绿色框为真实物体,黑色框为检测框):
  • 既然IoUGIoU效果都那么好,为什么要舍弃IoU而选择GIoU呢,我们先来回顾一下IoU的定义:
    I o U = P r e d i c t e d b o x ∩ G r o u n d T r u t h b o x P r e d i c t e d b o x ∪ G r o u n d T r u t h b o x IoU=\frac{{Predicted box}\cap{GroundTruth box}}{{Predicted box}\cup{GroundTruth box}} IoU=PredictedboxGroundTruthboxPredictedboxGroundTruthbox,
    也就是预测框与真实框的交集除以并集,那这会有什么缺点呢?
  1. 预测的检测框如果和真实物体的检测框没有重叠(没有交集)的话,我们从IoU的公式可以看出,IoU始终为0且无法优化,也就是如果算法一开始检测出来的框很离谱,根本没有和真实物体发生交集的话,算法无法优化
  2. 对于两个IoU相同的物体,他们的对齐方式IoU并不敏感,如下图:

GIoU介绍

  • 因此,作者提出了GIoU,假设现在有两个任意性质 A,B,我们找到一个最小的封闭形状C(最小凸集),让C可以刚好把A,B包含在内,然后我们计算C中没有覆盖A和B的面积占C总面积的比值,然后用A与B的IoU减去这个比值,GIoU的公式定义如下:
    I o U − ∣ C / A ∩ B ∣ ∣ C ∣ IoU-\frac{|C/{A}\cap{B}|}{|C|} IoUCC/AB
  • GIoU的性质有以下几个:
  1. GIoU具有作为一个度量标准的优良性质。包括非负性,同一性,对称性,以及三角不等式的性质
  2. IoU类似,GIoU也可以作为一个距离,loss可以这样来计算: L G I o U = 1 − G I o U L_{GIoU}=1-GIoU LGIoU=1GIoU
  3. GIoU总是小于等于IoUIoU的范围是 [ 0 , 1 ] [0,1] [0,1],GIoU的范围是 [ − 1 , 1 ] [-1,1] [1,1]
  4. 在A,B没有很好地对齐时,会导致C的面积增大,从而使GIoU的值变小,而两个矩形框不重合时,也可以计算GIoU,这样也就解决了IoU的两个缺点。

算法流程及代码

算法流程


我们具体地来讲一下GIoU的损失计算流程,假设我们现在Bounding box和ground truth的坐标分别是 B p = ( x 1 p , y 1 p , x 2 p , y 2 p ) B^p=(x^p_1,y^p_1,x^p_2,y^p_2) Bp=(x1p,y1p,x2p,y2p),
B g = ( x 1 g , y 1 g , x 2 g . y 2 g ) B^g=(x^g_1,y^g_1,x^g_2.y^g_2) Bg=(x1g,y1g,x2g.y2g),我们规定 x 2 p > x 1 p x^p_2>x^p_1 x2p>x1p, y 2 p > y 1 p y^p_2>y^p_1 y2p>y1p:
1.我们先计算 B g B^g Bg的面积: A g = ( x 2 g > x 1 g ) × ( y 2 g > y 1 g ) A^g=(x^g_2>x^g_1)×(y^g_2>y^g_1) Ag=(x2g>x1g)×(y2g>y1g)
2.然后我们计算 B p B^p Bp的面积: A p = ( x 2 p > x 1 p ) × ( y 2 p > y 1 p ) A^p=(x^p_2>x^p_1)×(y^p_2>y^p_1) Ap=(x2p>x1p)×(y2p>y1p)
3.计算两个的重叠面积(先计算出重叠部分的四个坐标再算面积):
x 1 I = m a x ( x 1 p , x 1 g ) x^I_1=max(x^p_1,x^g_1) x1I=max(x1p,x1g), x 2 I = m i n ( x 2 p , x 2 g ) x^I_2=min(x^p_2,x^g_2) x2I=min(x2p,x2g)
y 1 I = m a x ( y 1 p , y 1 g ) y^I_1=max(y^p_1,y^g_1) y1I=max(y1p,y1g) y 1 I = m a x ( y 1 p , y 1 g ) y^I_1=max(y^p_1,y^g_1) y1I=max(y1p,y1g)
I = { ( x 2 I > x 1 I ) × ( y 2 I > y 1 I ) x 2 I > x 1 I , y 2 I > y 1 I   0 o t h e r w i s e I=\begin {cases} (x^I_2>x^I_1)×(y^I_2>y^I_1) & x^I_2>x^I_1,y^I_2>y^I_1 \\\ 0 & otherwise \end {cases} I={(x2I>x1I)×(y2I>y1I) 0x2I>x1I,y2I>y1Iotherwise

4.找到可以包含 B p B^p Bp, B g B^g Bg的最小box B c B^c Bc的坐标
x 1 c = m i n ( x 1 p , x 1 g ) x^c_1=min(x^p_1,x^g_1) x1c=min(x1p,x1g), x 2 c = m a x ( x 2 p , x 2 g ) x^c_2=max(x^p_2,x^g_2) x2c=max(x2p,x2g)
y 1 c = m i n ( y 1 p , y 1 g ) y^c_1=min(y^p_1,y^g_1) y1c=min(y1p,y1g) y 1 c = m a x ( y 1 p , y 1 g ) y^c_1=max(y^p_1,y^g_1) y1c=max(y1p,y1g)
5.计算 B c B^c Bc的面积: A c = ( x 2 c − x 1 c ) × ( y 2 c − y 1 c ) A^c=(x^c_2-x^c_1)×(y^c_2-y^c_1) Ac=(x2cx1c)×(y2cy1c)
6.计算IoU: I o U = I U = I A p + A g − I IoU=\frac{I}{U}=\frac{I}{A^p+A^g-I} IoU=UI=Ap+AgII
7.计算GIoU: G I o U = I o U − A c − U A c GIoU = IoU -\frac{A^c-U}{A^c} GIoU=IoUAcAcU
8.最终损失: L G I o U = 1 − G I o U L_{GIoU}=1-GIoU LGIoU=1GIoU

代码

我们再结合代码彻底理解一下GIoU的计算过程,这里的代码出自YOLO v3,这里原始boxes(x,y,w,h):

    def bbox_giou(self, boxes1, boxes2):
        #通过中心坐标分别加减宽高的一半计算bboxex的左上角坐标右下角坐标并拼接在一起
        boxes1 = tf.concat([boxes1[..., :2] - boxes1[..., 2:] * 0.5,
                            boxes1[..., :2] + boxes1[..., 2:] * 0.5], axis=-1)
        boxes2 = tf.concat([boxes2[..., :2] - boxes2[..., 2:] * 0.5,
                            boxes2[..., :2] + boxes2[..., 2:] * 0.5], axis=-1)

        boxes1 = tf.concat([tf.minimum(boxes1[..., :2], boxes1[..., 2:]),
                            tf.maximum(boxes1[..., :2], boxes1[..., 2:])], axis=-1)
        boxes2 = tf.concat([tf.minimum(boxes2[..., :2], boxes2[..., 2:]),
                            tf.maximum(boxes2[..., :2], boxes2[..., 2:])], axis=-1)
        #分别计算两个boxes的面积
        boxes1_area = (boxes1[..., 2] - boxes1[..., 0]) * (boxes1[..., 3] - boxes1[..., 1])
        boxes2_area = (boxes2[..., 2] - boxes2[..., 0]) * (boxes2[..., 3] - boxes2[..., 1])
       
        #计算交集的左上角以及右下角的坐标
        left_up = tf.maximum(boxes1[..., :2], boxes2[..., :2])
        right_down = tf.minimum(boxes1[..., 2:], boxes2[..., 2:])
       
        #计算交集的宽高,如果right_down - left_up < 0,则没有交集,宽高设置为0
        inter_section = tf.maximum(right_down - left_up, 0.0)
        #计算交集面积
        inter_area = inter_section[..., 0] * inter_section[..., 1]
        #计算并集面积
        union_area = boxes1_area + boxes2_area - inter_area
        #计算IoU
        iou = inter_area / union_area
        #计算最小并集的坐标
        enclose_left_up = tf.minimum(boxes1[..., :2], boxes2[..., :2])
        enclose_right_down = tf.maximum(boxes1[..., 2:], boxes2[..., 2:])
        #计算最小并集的宽高,如果enclose_right_down - enclose_left_up < 0,则宽高设置为0
        enclose = tf.maximum(enclose_right_down - enclose_left_up, 0.0)
        #计算最小并集的面积
        enclose_area = enclose[..., 0] * enclose[..., 1]
        #计算GIoU
        giou = iou - 1.0 * (enclose_area - union_area) / enclose_area

        return giou

### 实验结果
作者做了一系列的实验,结果是 IoU loss 可以轻微提升使用 MSE 作为 loss 的表现,而 GIoU 的提升幅度更大,这个结论在 YOLO 算法和 faster R-CNN 系列上都是成立的:
YOLO v3在 PASCAL VOC 2007上的提升
YOLO v3在COCO上的提升
Faster R-CNN在COCO上的提升

论文地址

Generalized Intersection over Union: A Metric and A Loss for Bounding Box
Regression

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值