结合NWD的Shape-IoU!助力yolo v5涨点,源码复现

在这里插入图片描述
标题: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

### YOLOv5NWD技术概述 YOLOv5是一种高效的实时目标检测框架,在工业缺陷检测等领域表现出色[^1]。NWD(No Weights Decay on BatchNorm)是在训练神经网络过程中用于优化权重衰减的技术,有助于提高模型性能。 #### 技术文档与教程资源 对于希望深入了解YOLOv5及其应用到特定场景如手机背板缺陷分割的研究人员来说,可以参考以下资源: - **官方GitHub仓库**:提供最权威的源码和技术说明文件,适合开发者深入研究实现细节。 - **学术论文**:查阅原始作者发表的相关文献能够帮助理解算法设计初衷及理论基础。 - **在线课程平台**:许多网站提供了关于如何使用YOLO系列工具进行物体识别的任务指南,包括但不限于Udemy, Coursera等教育平台上由专家录制的教学视频。 #### 实现示例 下面是一个简单的Python脚本片段展示如何加载预训练好的YOLOv5模型并执行推理操作: ```python import torch from pathlib import Path # 加载预训练模型 model = torch.hub.load('ultralytics/yolov5', 'yolov5s') # 设置图片路径 img_path = "path/to/image.jpg" # 进行预测 results = model(img_path) # 显示结果 results.show() ``` 此代码段展示了基本的功能调用方式;实际项目开发中可能还需要考虑更多因素比如数据增强、超参数调整等方面的工作来提升最终效果。 #### 常见问题解答 当遇到有关于YOLOv5+NWD组合使用的疑问时,通常可以从以下几个方面寻找解决办法: - 如果发现BN层更新缓慢影响收敛速度,则应确认是否正确配置了`weight_decay=0`给Batch Normalization layers以激活NWD机制。 - 对于GPU内存不足的情况,尝试减少batch size大小或是采用混合精度训练方法减轻显存压力。 - 遇到mAP指标不理想的问题,除了检查标注质量外,还应该评估所选backbone架构以及anchor box尺寸设置是否合理匹配目标任务需求。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值