废话不多说,先看motivation:
There is a gap between optimizing the commonly used distance losses and maximizing this metric value.
The optimal objective for a metric is the metric itself. so in the case of axis-aligned 2D bounding boxed,it can be shown that IOU can be directly used as a regression loss.
However(重点来了):IOU has a plateau making it infeasible to optimize in the case of non-overlapping bounding boxes.
接下来看一张图:
黑色表示预测bbox
绿色表示真值bbox
这张图想说明什么呢?There is not a strong correlation between minimizing the commonly used lossed and improving their IOU values.它们的损失函数相同但是它们的IoU和GIoU不一样,也就是说一个好的局部目标优化对于IoU不一定是一个最好的局部优化。
再来一张图:
这张图的IoU 一样但是GIoU不一样,意思是重叠程度相同,但是重叠效果不同,从左到右依次变差,这是IoU不能体现的。
IoU计算及其特点
:
优点:
1.IoU as a distance,eg.Liou=1-IoU
2.IoU is invariant to the scale of the problem.
缺点:
GIoU的计算及其特点
:
可以看到主要是计算最小的包围凸对象C(将A、B包围住),然后|C(A∪B|表示除了A、B,C所占的面积
特点:
1.follows the same definition as IoU(GIoU as a distance),i.e.encoding the shape properties of the compared objects into the region property
2.maintains the scale invariant property of IoU
3.ensures a strong correlation with IoU in the case of overlapping objects
4.
5.
计算GIoU的思路清晰了,最重要的就是找到C,那具体如何实现呢?如何作为一个loss呢?
一定要注意输入的是什么?一般我用到的是( x,y,w,h)
除了那些验证条件1,思路很简单:
1.计算真值bbox面积
2.计算预测bbox面积
3.计算真值bbox和预测bbox相交的面积I
4.找到最小包围bboxC,并计算面积
有没有发现3,4找顶点的操作正好相反呢?
5.计算IoU
6.计算GIoU
7.计算loss
我没有看源码,直接按照这个思路写的代码,如下:
def giou(reference, proposals):
"""Compute the GIoU
args:
reference - Tensor of shape (1, 4),(x,y,w,h)
proposals - Tensor of shape (num_proposals, 4),(x,y,w,h)
"""
# Intersection box
tl = torch.max(reference[:,:2], proposals[:,:2])
br = torch.min(reference[:,:2] + reference[:,2:], proposals[:,:2] + proposals[:,2:])
sz = (br - tl).clamp(0)
# inter Area
intersection = sz.prod(dim=1)
union = reference[:,2:].prod(dim=1) + proposals[:,2:].prod(dim=1) - intersection
iou=intersection / union
# smallest enclosing box
l = torch.min(reference[:, :2], proposals[:, :2])
r = torch.max(reference[:, :2] + reference[:, 2:], proposals[:, :2] + proposals[:, 2:])
length = (r - l).clamp(0)
area=length.prod(dim=1)
#GIOU
giou=iou-(area-union)/area
giou_loss=1-giou
return giou,giou_loss