一行代码改进NMS

一篇讲通过改进NMS来提高检测效果的论文。

文章链接: 《Improving Object Detection With One Line of Code》

Github链接: https://github.com/bharatsingh430/soft-nms

Motivation

绝大部分目标检测方法,最后都要用到 NMS-非极大值抑制进行后处理。 通常的做法是将检测框按得分排序,然后保留得分最高的框,同时删除与该框重叠面积大于一定比例的其它框。

这种贪心式方法存在如下图所示的问题: 红色框和绿色框是当前的检测结果,二者的得分分别是0.95和0.80。如果按照传统的NMS进行处理,首先选中得分最高的红色框,然后绿色框就会因为与之重叠面积过大而被删掉。

另一方面,NMS的阈值也不太容易确定,设小了会出现下图的情况(绿色框因为和红色框重叠面积较大而被删掉),设置过高又容易增大误检。

float

思路:不要粗鲁地删除所有IOU大于阈值的框,而是降低其置信度。

Method

先直接上伪代码,如下图:如文章题目而言,就是用一行代码来替换掉原来的NMS。按照下图整个处理一遍之后,指定一个置信度阈值,然后最后得分大于该阈值的检测框得以保留

float

原来的NMS可以描述如下:将IOU大于阈值的窗口的得分全部置为0。

float

文章的改进有两种形式,一种是线性加权的:

float

一种是高斯加权的:

float

分析上面的两种改进形式,思想都是:M为当前得分最高框,\(b_i\) 为待处理框,\(b_i\) 和M的IOU越大,\(b_i\) 的得分\(s_i\) 就下降的越厉害。

具体地,下面是作者给出的代码:(当然不止一行T_T)

def cpu_soft_nms(np.ndarray[float, ndim=2] boxes, float sigma=0.5, float Nt=0.3, float threshold=0.001, unsigned int method=0):
    cdef unsigned int N = boxes.shape[0]
    cdef float iw, ih, box_area
    cdef float ua
    cdef int pos = 0
    cdef float maxscore = 0
    cdef int maxpos = 0
    cdef float x1,x2,y1,y2,tx1,tx2,ty1,ty2,ts,area,weight,ov

    for i in range(N):
        maxscore = boxes[i, 4]
        maxpos = i

        tx1 = boxes[i,0]
        ty1 = boxes[i,1]
        tx2 = boxes[i,2]
        ty2 = boxes[i,3]
        ts = boxes[i,4]

        pos = i + 1
    # get max box
        while pos < N:
            if maxscore < boxes[pos, 4]:
                maxscore = boxes[pos, 4]
                maxpos = pos
            pos = pos + 1

    # add max box as a detection 
        boxes[i,0] = boxes[maxpos,0]
        boxes[i,1] = boxes[maxpos,1]
        boxes[i,2] = boxes[maxpos,2]
        boxes[i,3] = boxes[maxpos,3]
        boxes[i,4] = boxes[maxpos,4]

    # swap ith box with position of max box
        boxes[maxpos,0] = tx1
        boxes[maxpos,1] = ty1
        boxes[maxpos,2] = tx2
        boxes[maxpos,3] = ty2
        boxes[maxpos,4] = ts

        tx1 = boxes[i,0]
        ty1 = boxes[i,1]
        tx2 = boxes[i,2]
        ty2 = boxes[i,3]
        ts = boxes[i,4]

        pos = i + 1
    # NMS iterations, note that N changes if detection boxes fall below threshold
        while pos < N:
            x1 = boxes[pos, 0]
            y1 = boxes[pos, 1]
            x2 = boxes[pos, 2]
            y2 = boxes[pos, 3]
            s = boxes[pos, 4]

            area = (x2 - x1 + 1) * (y2 - y1 + 1)
            iw = (min(tx2, x2) - max(tx1, x1) + 1)
            if iw > 0:
                ih = (min(ty2, y2) - max(ty1, y1) + 1)
                if ih > 0:
                    ua = float((tx2 - tx1 + 1) * (ty2 - ty1 + 1) + area - iw * ih)
                    ov = iw * ih / ua #iou between max box and detection box

                    if method == 1: # linear
                        if ov > Nt: 
                            weight = 1 - ov
                        else:
                            weight = 1
                    elif method == 2: # gaussian
                        weight = np.exp(-(ov * ov)/sigma)
                    else: # original NMS
                        if ov > Nt: 
                            weight = 0
                        else:
                            weight = 1

                    boxes[pos, 4] = weight*boxes[pos, 4]

            # if box score falls below threshold, discard the box by swapping with last box
            # update N
                    if boxes[pos, 4] < threshold:
                        boxes[pos,0] = boxes[N-1, 0]
                        boxes[pos,1] = boxes[N-1, 1]
                        boxes[pos,2] = boxes[N-1, 2]
                        boxes[pos,3] = boxes[N-1, 3]
                        boxes[pos,4] = boxes[N-1, 4]
                        N = N - 1
                        pos = pos - 1

            pos = pos + 1

    keep = [i for i in range(N)]
    return keep

Experiments

下图可以看出,基本可以获得平均1%的提升,且不增加额外的训练和计算负担。

float

高斯方差以及NMS的IOU阈值的敏感性测试:

float

### YOLOv8 Pose 关键点检测改进方法与性能优化 #### 1. 使用 SimAM 注意力机制提升小目标检测能力 通过引入具有切片操作的 **SimAM 注意力机制**,可以在不增加原始网络参数的情况下为特征图推断三维注意力权重。这种方法的核心在于提出优化的能量函数以挖掘每个神经元的重要性,并基于此推导出一种快速解析解[^1]。以下是其实现方式: - 能量函数的设计使得模型能够自动学习哪些区域对于关键点检测更重要。 - 解析解的高效计算特性使其能够在不超过十行代码的情况下完成实现。 ```python import torch import torch.nn as nn class SimAM(nn.Module): def __init__(self, lambda_param=0.01): super(SimAM, self).__init__() self.lambda_param = lambda_param def forward(self, x): n = x.size(2) * x.size(3) mean_x = torch.mean(x, dim=(2, 3), keepdim=True) var_x = torch.var(x, dim=(2, 3), keepdim=True) max_x = torch.max(torch.max(x, dim=2)[0], dim=2)[0].unsqueeze(-1).unsqueeze(-1) min_x = torch.min(torch.min(x, dim=2)[0], dim=2)[0].unsqueeze(-1).unsqueeze(-1) normed_x = (x - mean_x) / (var_x + 1e-7) attention_weights = torch.exp(normed_x.pow(2)) / ((torch.exp(max_x.pow(2))) - (torch.exp(min_x.pow(2)))) refined_attention = attention_weights / (attention_weights.sum(dim=(2, 3)).unsqueeze(-1).unsqueeze(-1)) output = x + self.lambda_param * (refined_attention * x) return output ``` 上述代码展示了如何构建 SimAM 模块并将其嵌入到 YOLOv8 的骨干网络中,从而增强其对小目标关键点的捕捉能力。 --- #### 2. 应用部分自注意力(PSA)模块提高整体精度 为了进一步改善 YOLOv8-Pose 的表现,可以集成高效的 PSA 模块。该模块源自 YOLOv10 并被证明有效提升了姿态估计任务中的特征表达能力[^2]。具体而言: - PSA 模块允许模型专注于输入图像的不同子区域,从而更好地捕获人体关节的空间关系。 - 它还支持动态调整关注范围,在复杂背景条件下尤其有用。 需要注意的是,尽管 PSA 提供了显著增益,但在实际应用时应权衡额外计算成本与其带来的收益。 --- #### 3. 双标签分配策略减少 NMS 后处理需求 传统上,YOLO 系列算法依赖于非极大值抑制(Non-Maximum Suppression, NMS)作为后处理步骤来消除重复预测。然而这增加了延迟时间影响实时性。为此提出了新的训练方案——即具备双标签分配特性和一致性匹配度量的标准架替代原有 TAL 方法。这种新范式不仅消除了对外部过滤器的需求而且保持甚至超越先前版本的效果水平。 总结来说,以上三种技术手段均可单独或者组合应用于改良版 YOLOv8-Pose 中去达成更好的识别成果以及运行效率之间的平衡状态。 ---
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值