标题:Shape-IoU: More Accurate Metric considering Bounding Box Shape and Scale
作者:Hao Zhang, Shuaijie Zhang
原文链接:https://arxiv.org/abs/2312.17663
代码链接:https://github.com/malagoutou/S
shape iou
边界框回归损失在目标检测中非常重要,典型Loss就是IoU、GIoU、CIoU、SIoU。改动方案基本上都是在IoU上添加新的几何约束(GT框和 Anchor 框的距离、形状和角度),但是都忽略了边界框自身的形状和尺寸的影响。今天笔者为大家推荐一篇最新的开源工作Shape-IoU,借助边界框本身的形状和尺度来计算损失,使边界框回归更加准确,可以有效地提高YOLO系列检测器的性能!
1、概述
作为检测器定位分支的重要组成部分,边界框回归损失在目标检测任务中发挥着重要作用。现有的边界框回归方法通常考虑GT框和预测框之间的几何关系,利用边界框的相对位置和形状来计算损失,而忽略了边界框的形状和尺度等固有属性对边界框回归的影响。为了弥补现有研究的不足,本文提出了一种关注包围盒自身形状和尺度的包围盒回归方法。首先,我们对边界框的回归特性进行了分析,发现边界框本身的形状和尺度因素会对回归结果产生影响。基于以上结论,我们提出了Shape IoU方法,该方法可以通过关注边界框本身的形状和尺度来计算损失,从而使得边界框回归更加准确。最后,我们通过大量的对比实验对我们的方法进行了验证,结果表明我们的方法可以有效地提高检测性能,并且优于现有的方法,在不同的检测任务中达到了先进的性能。
2、原理
如图所示,边界框回归样本A和B中GT框的尺度相同,而C和D中GT框的尺度相同。A和D中GT盒的形状相同,而B和C中GT盒的形状相同。C和D中包围盒的尺度大于A和B中包围盒的尺度,图a中所有包围盒的回归样本具有相同的偏差,形状偏差为0。图a与图b的不同之处在于,图b中所有包围盒回归样本的形状偏差相同,偏差为0。并观察到如下发现:
图a中A和B的偏差相同,但IoU值存在差异。
图a中C和D的偏差相同,但IoU值存在差异,且相比图a中的A和B,IoU值差异不显著。
图b中A和B的形状偏差相同,但IoU值存在差异。
图b中C和D的形状偏差相同,但IoU值存在差异,与图a中A和B相比,IoU值差异不显著。
图a中A和B的Io U值存在差异的原因是它们的GT盒形状不同,偏离方向分别对应它们的长边和短边方向。对于A,其GT盒沿长边方向的偏差对其影响较小。而对B而言,短边方向的偏差对其Io U值的影响更大。与大尺度包围盒相比,小尺度包围盒对Io U值的变化更敏感,GT盒形状对小尺度包围盒的Io U值影响更显著。由于A和B比C和D的尺度小,在形状和偏差相同的情况下,Io U值的变化更显著。同理,在图b中,从形状偏差的角度分析包围盒回归,发现回归样本中GT盒的形状会影响其在回归过程中的Io U值。
基于以上分析,可以得出以下结论:
(1)假设GT盒不是正方形,有长边和短边,当偏差和形状偏差相同且不全为0时,回归样本中包围盒形状和尺度的不同会导致其Io U值的差异。
(2)对于相同尺度的包围盒回归样本,当回归样本的偏差和形状偏差相同且不全为0时,包围盒的形状会对回归样本的Io U值产生影响。包围盒短边方向的偏差和形状偏差对应的Io U值变化更为显著。
(3)对于具有相同形状包围盒的回归样本,当回归样本偏差和形状偏差相同且不全为0时,相比于规模较大的回归样本,规模较小的包围盒回归样本的Io U值受GT盒形状的影响更为显著。
3、shape iou 源代码
def shape_iou(box1, box2, scale1=0.5, eps=1e-7):
(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_
# 计算交集面积
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 = (w1 * h1 + w2 * h2 - inter + eps) # 添加 eps 防止除零
# 计算 IoU
iou = inter / union
# 计算形状距离
ww = 2 * torch.pow(w2, scale1) / (torch.pow(w2, scale1) + torch.pow(h2, scale1))
hh = 2 * torch.pow(h2, scale1) / (torch.pow(w2, scale1) + torch.pow(h2, scale1))
# 计算凸包的宽度和高度
cw = torch.max(b1_x2, b2_x2) - torch.min(b1_x1, b2_x1)
ch = torch.max(b1_y2, b2_y2) - torch.min(b1_y1, b2_y1)
c2 = cw ** 2 + ch ** 2 + eps # 凸包对角线的平方
# 计算中心距离
center_distance_x = ((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2) / 4
center_distance_y = ((b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4
center_distance = hh * center_distance_x + ww * center_distance_y
distance = center_distance / (c2 + eps) # 归一化距离,添加 eps 防止除零
# 计算形状相似度
omiga_w = hh * torch.abs(w1 - w2) / torch.max(w1, w2)
omiga_h = ww * torch.abs(h1 - h2) / torch.max(h1, h2)
shape_cost = torch.pow(1 - torch.exp(-1 * omiga_w), 4) + torch.pow(1 - torch.exp(-1 * omiga_h), 4)
# 最终的 Shape-IoU
iou = iou - distance - 0.5 * shape_cost
return iou # 返回融合了形状和距离的 IoU
4、A Normalized Gaussian Wasserstein Distance for Tiny Object Detection(NWD)提升小目标检测能力
4.1 nwd简介
论文链接:nwd
NWD是一个新的度量方法来计算框和框之间的相似度,就是把框建模成高斯分布,然后用Wasserstein距离来度量这两个分布之间的相
似度,来代替loU。这个距离的好处是,即便是2个框完全不重叠,或者重叠很少,还是可以度量出相似度出来。另外,NWD对于目标的
尺度不敏感,对于小目标的更加的稳定。
相比于loU,NWD有以下好处:
1.尺度不变性。
2. 对于位置的差别变换平缓。
3.具有度量不想交的框的相似度的能力。
4.2 nwd代码
根据shape iou论文提到的nwd撰写代码:
def nwd(box1, box2, scale1=0.5, eps=1e-7):
(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_
# 计算形状距离
ww = 2 * torch.pow(w2, scale1) / (torch.pow(w2, scale1) + torch.pow(h2, scale1))
hh = 2 * torch.pow(h2, scale1) / (torch.pow(w2, scale1) + torch.pow(h2, scale1))
# 计算 NWD
B = (torch.pow(w1 - w2,2)+torch.pow(h1 - h2,2))/4
center_distance_x1 = (b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2
center_distance_y1 = (b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2
D =(hh*center_distance_x1+ww*center_distance_y1+B)**(1/2)
nwd=torch.exp(-D/3)
return nwd # 返回融合了形状和距离的 IoU
5、shape iou加入yolo5复现
5.1在metrics.py中插入上述shape iou代码
def shape_iou(box1, box2, scale1=0.5, eps=1e-7):
(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_
# 计算交集面积
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 = (w1 * h1 + w2 * h2 - inter + eps) # 添加 eps 防止除零
# 计算 IoU
iou = inter / union
# 计算形状距离
ww = 2 * torch.pow(w2, scale1) / (torch.pow(w2, scale1) + torch.pow(h2, scale1))
hh = 2 * torch.pow(h2, scale1) / (torch.pow(w2, scale1) + torch.pow(h2, scale1))
# 计算凸包的宽度和高度
cw = torch.max(b1_x2, b2_x2) - torch.min(b1_x1, b2_x1)
ch = torch.max(b1_y2, b2_y2) - torch.min(b1_y1, b2_y1)
c2 = cw ** 2 + ch ** 2 + eps # 凸包对角线的平方
# 计算中心距离
center_distance_x = ((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2) / 4
center_distance_y = ((b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4
center_distance = hh * center_distance_x + ww * center_distance_y
distance = center_distance / (c2 + eps) # 归一化距离,添加 eps 防止除零
# 计算形状相似度
omiga_w = hh * torch.abs(w1 - w2) / torch.max(w1, w2)
omiga_h = ww * torch.abs(h1 - h2) / torch.max(h1, h2)
shape_cost = torch.pow(1 - torch.exp(-1 * omiga_w), 4) + torch.pow(1 - torch.exp(-1 * omiga_h), 4)
# 最终的 Shape-IoU
iou = iou - distance - 0.5 * shape_cost
return iou # 返回融合了形状和距离的 IoU
5.2在metrics.py中插入上述nwd代码
def nwd(box1, box2, scale1=0.5, eps=1e-7):
(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_
# 计算形状距离
ww = 2 * torch.pow(w2, scale1) / (torch.pow(w2, scale1) + torch.pow(h2, scale1))
hh = 2 * torch.pow(h2, scale1) / (torch.pow(w2, scale1) + torch.pow(h2, scale1))
# 计算 NWD
B = (torch.pow(w1 - w2,2)+torch.pow(h1 - h2,2))/4
center_distance_x1 = (b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2
center_distance_y1 = (b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2
D =(hh*center_distance_x1+ww*center_distance_y1+B)**(1/2)
nwd=torch.exp(-D/3)
# 最终的 Shape-IoU
# iou = iou - distance - 0.5 * shape_cost - 0.5 * nwd
return nwd # 返回融合了形状和距离的 IoU
5.3在loss.py中插入下面代码
首先在loss.py导入shape_iou和nwd
from utils.metrics import shape_iou,nwd
然后再computeloss函数里面将原来ciou loss改为下面代码(这里比重设置为0.8:0.2)
iou = shape_iou(pbox, tbox[i]) # 使用 shape_iou 计算 IoU
nwd1=nwd(pbox, tbox[i])
lbox += 0.8*(1.0 - iou).mean()+0.2*(1.0-nwd1).mean() # 使用 shape IoU 损失
6、总结
本文为大家推荐了一篇最新的开源工作Shape - IoU和Nwd。这篇文章指出现有Loss侧重于考虑GT框与预测框之间的几何约束,而忽略了边界框本身的形状、尺度等几何因素对回归结果的影响。然后提出了Shape - IoU方法,可以关注包围盒本身的形状和尺度来计算损失,从而提高精度,而nwd则有利于提升小目标的检测效果,最后使用SOTA单阶段检测器在不同规模的数据集上进行了一系列的对比实验,证明Shape - IoU或者结合Nwd的Shape - IoU优于现有的方法。
7、其他
可以结合一些可落地项目,在项目的基础上进行算法改进完成论文创新撰写;
相应的落地应用链接可点击:https://mbd.pub/o/author-aGqammlpYw==/work