首页 > 其他分享 >YOLOv9改进策略【损失函数篇】| 引入Soft-NMS,提升密集遮挡场景检测精度,包括GIoU-NMS、DIoU-NMS、CIoU-NMS、SIoU-NMS、 EIou-NMS

YOLOv9改进策略【损失函数篇】| 引入Soft-NMS,提升密集遮挡场景检测精度,包括GIoU-NMS、DIoU-NMS、CIoU-NMS、SIoU-NMS、 EIou-NMS

时间:2024-09-13 16:53:11浏览次数:3  
标签:GIoU NMS EIou iou torch b1 b2 Soft

一、背景:

传统的非极大值抑制(NMS)算法在目标检测中存在一个问题,即当一个物体的检测框与具有最高得分的检测框M有重叠(在预定义的重叠阈值内)时,会将该检测框的得分设置为零,从而导致该物体可能被遗漏,降低了平均精度。为了解决这个问题,作者提出了Soft-NMS算法。

本文将YOLOv9默认的NMS修改成GIoU-NMSDIoU-NMSCIoU-NMSSIoU-NMSEIou-NMS

文章目录


二、原理

Soft-NMS - 用一行代码改进对象检测

2.1 NMS原理

在目标检测等任务中,通常会产生多个可能的检测框或候选区域。这些检测框可能会有重叠,并且可能会对同一个目标进行多次检测。

NMS 的核心思想就是在这些检测结果中,找到局部最大值并抑制非极大值。

具体来说,对于一组检测结果,按照某个分数(如置信度)进行排序,然后依次选取分数最高的检测框,将其与其他检测框进行比较,如果其他检测框与该框的重叠度超过一定阈值,则认为该检测框不是最优的,将其抑制(通常是将其分数置为 0 或降低其分数)。

在这里插入图片描述

2.2 Soft-NMS的原理

  • 传统NMS算法的问题:传统的NMS算法从具有得分S的检测框列表B开始,选择得分最高的检测框M,将其从B中移除并添加到最终检测集D中,同时移除B中与M重叠大于阈值 N t N_t Nt​的任何框。该算法的主要问题是将相邻检测的得分设置为零,若物体实际上在该重叠阈值内,就会被遗漏,导致平均精度下降。
  • Soft - NMS的改进Soft-NMS通过修改传统NMS算法的得分衰减方式来解决这个问题。它不是将与M有高重叠的检测框的得分直接设置为零,而是根据与M的重叠程度来降低其分类得分。具体来说,提出了两种重新评分函数:
    • 线性衰减函数: s i = { s i , i o u ( M , b i ) < N t s i ( 1 − i o u ( M , b i ) ) , i o u ( M , b i ) ≥ N t s_i = \begin{cases} s_i, & iou(\mathcal{M}, b_i) < N_t \\ s_i(1 - iou(\mathcal{M}, b_i)), & iou(\mathcal{M}, b_i) \geq N_t \end{cases} si​={si​,si​(1−iou(M,bi​)),​iou(M,bi​)<Nt​iou(M,bi​)≥Nt​​,该函数将重叠阈值(N_t)以上的检测得分进行线性衰减。
    • 高斯衰减函数: s i = s i e − k a ( M , b i ) 2 σ , ∀ b i ∉ D s_i = s_i e^{-\frac{ka(\mathcal{M}, b_i)^2}{\sigma}}, \forall b_i \notin \mathcal{D} si​=si​e−σka(M,bi​)2​,∀bi​∈/D,对与M有重叠的检测框的得分进行高斯衰减。
  • 计算复杂度Soft-NMS中每一步的计算复杂度为 O ( N ) O(N) O(N)(N为检测框的数量),因为需要更新所有与M有重叠的检测框的得分,所以对于N个检测框,Soft-NMS的计算复杂度为 O ( N 2 ) O(N^2) O(N2),与传统的贪心NMS相同。由于NMS并非应用于所有检测框(在每次迭代中会修剪具有最小阈值的框),所以这一步并不昂贵,不会影响当前检测器的运行时间。

在这里插入图片描述在这里插入图片描述

2.3 Soft-NMS的优势

  • 性能提升:在标准数据集(如PASCAL VOC2007和MS - COCO)上,通过简单地改变NMS算法为Soft-NMS,无需任何额外的超参数,就能使coco-style mAP指标得到持续改进。例如,在PASCAL VOC2007上,RFCN和Faster-RCNN的性能提高了1.7%;在MS-COCO上,R-FCN提高了1.3%,Faster-RCNN提高了1.1%和1.1%。使用Deformable-RFCN,Soft-NMS将目标检测的最先进水平从39.8%提高到40.9%。
  • 易于集成Soft-NMS不需要任何额外的训练,且实现简单,因此可以很容易地集成到任何目标检测管道中。
  • 对不同类型检测器的适用性:对于基于提议(proposal - based)的检测器,如RFCN和Faster - RCNN,Soft - NMS能显著提高性能;对于非基于提议的检测器,如SSD和YOLOv2,使用线性函数时,Soft-NMS也能获得一定的性能提升(约0.5%)。
  • 稳定性和灵活性:通过敏感性分析可知,Soft-NMS的参数 σ \sigma σ在一定范围内(如0.4到0.7)性能稳定,且在不同重叠阈值下的表现优于传统NMS。低 σ \sigma σ值在较低的 O t O_t Ot​下表现更好,高 σ \sigma σ值在较高的 O t O_t Ot​下表现更好,并且可以通过调整 σ \sigma σ来提高检测器在不同定位情况下的性能,而传统NMS中较大的 N t N_t Nt​对AP的提升非常小。
  • 精度与召回率的平衡:在精度与召回率的关系上,随着 O t O_t Ot​和召回率的增加,Soft - NMS在精度上有显著提升。因为传统NMS将与M重叠大于 N t N_t Nt​的所有框的得分设置为零,导致许多框被遗漏,精度在召回率较高时不增加。而Soft - NMS重新评分相邻框而不是完全抑制它们,从而在召回率较高时提高了精度。在较高的 O t O_t Ot​下,即使召回率较低,Soft - NMS也能获得显著的改进,因为在这种设置下,近失更有可能发生。
  • 定性结果优势:从定性结果来看,Soft-NMS在一些情况下表现更好,例如当错误检测(false positives)与好的检测(true positive)有小重叠或低重叠时,它能降低错误检测的得分,从而抑制这些错误检测;对于一些动物图像,当NMS抑制检测框时,Soft-NMS能为相邻框分配稍低的得分,从而能够检测到真正的阳性结果。

论文:https://openaccess.thecvf.com/content_ICCV_2017/papers/Bodla_Soft-NMS_–_Improving_ICCV_2017_paper.pdf
源码:https://github.com/bharatsingh430/soft-nms

三、添加步骤

3.1 utils/general.py

此处需要查看的文件是utils/general.py

metrics.py中定义了全项目通用代码,相关实用函数实现。NMS的计算方法就在其中,我们想要加入新的NMS就只需要将代码放到这个文件内即可。

utils/general.py中找到non_max_suppression函数

在这里插入图片描述

在此函数上方添加如下代码:

def box_iou_for_nms(box1, box2, GIoU=False, DIoU=False, CIoU=False, SIoU=False, EIou=False, eps=1e-7):
    # Returns Intersection over Union (IoU) of box1(1,4) to box2(n,4)

    b1_x1, b1_y1, b1_x2, b1_y2 = box1.chunk(4, -1)
    b2_x1, b2_y1, b2_x2, b2_y2 = box2.chunk(4, -1)
    w1, h1 = b1_x2 - b1_x1, (b1_y2 - b1_y1).clamp(eps)
    w2, h2 = b2_x2 - b2_x1, (b2_y2 - b2_y1).clamp(eps)

    # Intersection area
    inter = (b1_x2.minimum(b2_x2) - b1_x1.maximum(b2_x1)).clamp(0) * \
            (b1_y2.minimum(b2_y2) - b1_y1.maximum(b2_y1)).clamp(0)

    # Union Area
    union = w1 * h1 + w2 * h2 - inter + eps

    # IoU
    iou = inter / union
    if CIoU or DIoU or GIoU or EIou:
        cw = b1_x2.maximum(b2_x2) - b1_x1.minimum(b2_x1)  # convex (smallest enclosing box) width
        ch = b1_y2.maximum(b2_y2) - b1_y1.minimum(b2_y1)  # convex height
        if CIoU or DIoU or EIou:  # Distance or Complete IoU https://arxiv.org/abs/1911.08287v1
            c2 = cw ** 2 + ch ** 2 + eps  # convex diagonal squared
            rho2 = ((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2 + (b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4  # center dist ** 2
            if CIoU:  # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47
                v = (4 / math.pi ** 2) * (torch.atan(w2 / h2) - torch.atan(w1 / h1)).pow(2)
                with torch.no_grad():
                    alpha = v / (v - iou + (1 + eps))
                return iou - (rho2 / c2 + v * alpha)  # CIoU
            elif EIou:
                rho_w2 = ((b2_x2 - b2_x1) - (b1_x2 - b1_x1)) ** 2
                rho_h2 = ((b2_y2 - b2_y1) - (b1_y2 - b1_y1)) ** 2
                cw2 = cw ** 2 + eps
                ch2 = ch ** 2 + eps
                return iou - (rho2 / c2 + rho_w2 / cw2 + rho_h2 / ch2)
            return iou - rho2 / c2  # DIoU
        c_area = cw * ch + eps  # convex area
        return iou - (c_area - union) / c_area  # GIoU https://arxiv.org/pdf/1902.09630.pdf
    elif SIoU:
        # SIoU Loss https://arxiv.org/pdf/2205.12740.pdf
        s_cw = (b2_x1 + b2_x2 - b1_x1 - b1_x2) * 0.5 + eps
        s_ch = (b2_y1 + b2_y2 - b1_y1 - b1_y2) * 0.5 + eps
        sigma = torch.pow(s_cw ** 2 + s_ch ** 2, 0.5)
        sin_alpha_1 = torch.abs(s_cw) / sigma
        sin_alpha_2 = torch.abs(s_ch) / sigma
        threshold = pow(2, 0.5) / 2
        sin_alpha = torch.where(sin_alpha_1 > threshold, sin_alpha_2, sin_alpha_1)
        angle_cost = torch.cos(torch.arcsin(sin_alpha) * 2 - math.pi / 2)
        rho_x = (s_cw / cw) ** 2
        rho_y = (s_ch / ch) ** 2
        gamma = angle_cost - 2
        distance_cost = 2 - torch.exp(gamma * rho_x) - torch.exp(gamma * rho_y)
        omiga_w = torch.abs(w1 - w2) / torch.max(w1, w2)
        omiga_h = 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)
        return iou - 0.5 * (distance_cost + shape_cost)
    return iou  # IoU


def soft_nms(bboxes, scores, iou_thresh=0.5, sigma=0.5, score_threshold=0.25):
    order = torch.arange(0, scores.size(0)).to(bboxes.device)
    keep = []

    while order.numel() > 1:
        if order.numel() == 1:
            keep.append(order[0])
            break
        else:
            i = order[0]
            keep.append(i)

        # 修改成你想要使用的IOU,如果不修改默认的就是普通iou
        iou = box_iou_for_nms(bboxes[i], bboxes[order[1:]], CIoU=True).squeeze()

        idx = (iou > iou_thresh).nonzero().squeeze()
        if idx.numel() > 0:
            iou = iou[idx]
            newScores = torch.exp(-torch.pow(iou, 2) / sigma)
            scores[order[idx + 1]] *= newScores

        newOrder = (scores[order[1:]] > score_threshold).nonzero().squeeze()
        if newOrder.numel() == 0:
            break
        else:
            maxScoreIndex = torch.argmax(scores[order[newOrder + 1]])
            if maxScoreIndex != 0:
                newOrder[[0, maxScoreIndex],] = newOrder[[maxScoreIndex, 0],]
            order = order[newOrder + 1]

    return torch.LongTensor(keep)


在这里插入图片描述

3.1.1 CIoU-NMS

此时,添加完成后就已经配置好了,在soft_nms中默认配置的是CIoU-NMS

在这里插入图片描述

3.1.2 GIoU-NMS

utils/general.py中的soft_nms函数下修改如下代码:


iou = box_iou_for_nms(bboxes[i], bboxes[order[1:]], GIoU=True).squeeze()

3.1.3 DIoU-NMS

utils/general.py中的soft_nms函数下修改如下代码:


iou = box_iou_for_nms(bboxes[i], bboxes[order[1:]], DIoU=True).squeeze()

3.1.4 SIoU-NMS

utils/general.py中的soft_nms函数下修改如下代码:


iou = box_iou_for_nms(bboxes[i], bboxes[order[1:]], SIoU=True).squeeze()

3.1.5 EIoU-NMS

utils/general.py中的soft_nms函数下修改如下代码:


iou = box_iou_for_nms(bboxes[i], bboxes[order[1:]], EIoU=True).squeeze()

标签:GIoU,NMS,EIou,iou,torch,b1,b2,Soft
From: https://blog.csdn.net/qq_42591591/article/details/142141984

相关文章

  • YOLOv5改进 | NMS | 将NMS修改为soft-NMS【完整代码】
    秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转......
  • 昇腾 - AscendCL C++应用开发 目标检测中的非极大值抑制NMS和计算候选边界框之间的交
    昇腾-AscendCLC++应用开发目标检测中的非极大值抑制(NMS,Non-MaximumSuppression)涉及计算候选边界框之间的交并比(IOU,IntersectionoverUnion)flyfish结构体BBox:定义了一个边界框的数据结构,包含中心坐标、宽高、置信度分数、类别索引和输出索引。函数IOU:计算两个......
  • Object Detection: Non-Maximum Suppression (NMS)
    ObjectDetection:Non-MaximumSuppression(NMS)https://kikaben.com/object-detection-non-maximum-suppression/ObjectdetectionmodelslikeYOLOv5andSSDpredictobjects’locationsbygeneratingboundingboxes(showninbluerectanglesbelow).However,......
  • NMS(non maximum suppression)非极大值抑制
    参考学习:算法精讲-预测阶段后处理-NMS非极大值抑制_哔哩哔哩_bilibili以YOLOv1的模型来讲,预测阶段后处理就是把每个boundingbox中的每个种类的值算出全概率,再对比boundingbox中同种类物品,先设定一个阈值,把boundingbox中同种类全概率低于阈值的算为0,再进行一次降序排序,通过遍历......
  • nms_bev函数
     defnms_bev(boxes,scores,thresh,pre_max_size=None,post_max_size=None):"""NMSfunctionGPUimplementation(forBEVboxes).TheoverlapoftwoboxesforIoUcalculationisdefinedastheexactoverlappingareaofthetwo......
  • YOLOv5改进 | 损失函数 | EIoU、SIoU、WIoU、DIoU、FocuSIoU等多种损失函数
    秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转   ......
  • 基于GWO灰狼优化的LDPC码NMS译码算法最优归一化参数计算和误码率matlab仿真
    1.算法仿真效果matlab2022a仿真结果如下(完整代码运行后无水印):     2.算法涉及理论知识概要       LDPC码是一种线性错误修正码,以其接近香农极限的优良性能而被广泛应用于现代通信系统中。NMS译码是一种基于最小平方误差准则的软判决译码方法,其目标是找到一......
  • 非极大值抑制(NMS):目标检测中的去冗余关键技术
    非极大值抑制(NMS):目标检测中的去冗余关键技术在目标检测算法中,非极大值抑制(Non-MaximumSuppression,NMS)是一种用于去除冗余检测框的关键技术。它通过抑制重叠度过高的检测框,从而提高检测结果的准确性和效率。本文将详细解释NMS的工作原理,并提供代码示例,帮助读者深入理解这......
  • 2025秋招计算机视觉面试题(七)-NMS详细工作机制及代码实现
    问题看到一句话:NMS都不懂,还做什么Detection!虎躯一震……懂是大概懂,但代码能写出来吗???在目标检测网络中,产生proposal后使用分类分支给出每个框的每类置信度,使用回归分支修正框的位置,最终会使用NMS方法去除同个类别当中IOU重叠度较高且scores即置信度较低的那些......
  • 单阶段目标检测--NMS
    目录一、概念:二、算法过程三、代码实现一、概念:        在目标检测的初始结果中,同一个物体,可能对应有多个边界框(boundingbox,bb),这些边界框通常相互重叠。如何从中选择一个最合适的(也就是与真实目标框最接近的)呢?通常采用的做法是NMS(Nonmaximumsuppression),......