soft-nms(softnms)(pytorch实现)& softer nms

softnms和softer nms是nms的两个改进算法

传统nms存在的问题

传统的NMS方法是基于分类分数的,只有最高分数的预测框能留下来,但是大多数情况下IoU和分类分数不是强相关,很多分类标签置信度高的框都位置都不是很准

还会有别的物体的框因为和当前物体的框重合部分过多被删掉的情况

Soft-NMS

发现了这些问题,让我们想想如何避免:

首先说第一个问题:物体重叠是由于输出多个框中存在某些其实是另一个物体,但是也不小心被NMS去掉了。这个问题的解法最终是要落在“将某个候选框删掉”这一步骤上,我们需要找到一种方法,更小心的删掉S中的框,而不是暴力的把所有和最高分框删掉,于是有了这个想法:

对于与最高分框overlap大于阈值t的框M,我们不把他直接去掉,而是将他的置信度降低,这样的方法可以使多一些框被保留下来,从而一定程度上避免overlap的情况出现。

那么读者可能会问,如果只是把置信度降低,那么可能原来周围的多个表示同一个物体的框也没办法去掉了。Soft-NMS这样来解决这个问题,同一个物体周围的框有很多,每次选择分数最高的框,抑制其周围的框,与分数最高的框的IoU越大,抑制的程度越大,一般来说,表示同一个物体的框(比如都是前面的马)的IoU是会比另一个物体的框(比如后面的马)的IoU大,因此,这样就会将其他物体的框保留下来,而同一个物体的框被去掉。

接下来就是Soft NMS的完整算法:

红色的部分表示原始NMS算法,绿色部分表示Soft-NMS算法,区别在于,绿色的框只是把si降低了,而不是把bi直接去掉,极端情况下,如果f只返回0,那么等同于普通的NMS。

接下来说一下f函数:f函数是为了降低目标框的置信度,满足条件,如果bi和M的IoU越大,f(iou(M, bi))就应该越小,Soft-NMS提出了两种f函数:

线性函数:

这个比较好理解,当iou条件满足时,si乘上一个1-iou,线性变小 

高斯函数惩罚,越接近高斯分布中心,惩罚力度越大

Soft-NMS的效果也比较明显:重叠的物体被更大程度的保留下来,以下是效果图

不过Soft-NMS还是需要调整阈值的,由于没有“去掉”某些框的操作,因此,最后所有框都会被加入D中,只是那些被去掉的框的置信度明显降低,所以需要一个阈值(通常很小)来过滤D中的输出框,从而输出最后的预测框。所以Soft-NMS还是需要一些调参的

我们可以看到,对于NMS而言,其直接将 与得分最大的框 重合程度较高的其它预测剔除。而Soft-NMS则以一个权重的形式,将获得的IOU取高斯指数后乘上原得分,之后重新排序。继续循环。

一直是idxs在变

from torch import Tensor
import torch
import torchvision
 
 
def box_area(boxes: Tensor) -> Tensor:
    return (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1])
 
def box_iou(boxes1: Tensor, boxes2: Tensor) -> Tensor:
    area1 = box_area(boxes1)  # 每个框的面积 (N,)
    area2 = box_area(boxes2)  # (M,)
 
    lt = torch.max(boxes1[:, None, :2], boxes2[:, :2])  # [N,M,2] # N中一个和M个比较; 所以由N,M 个
    rb = torch.min(boxes1[:, None, 2:], boxes2[:, 2:])  # [N,M,2]
 
    wh = (rb - lt).clamp(min=0)  # [N,M,2]  # 删除面积小于0 不相交的  clamp 钳;夹钳;
    inter = wh[:, :, 0] * wh[:, :, 1]  # [N,M]  # 切片的用法 相乘维度减1
    iou = inter / (area1[:, None] + area2 - inter)
    return iou  # NxM, boxes1中每个框和boxes2中每个框的IoU值;
 
 
def soft_nms(boxes: Tensor, scores: Tensor, soft_threshold=0.01,  iou_threshold=0.7, weight_method=1, sigma=0.5):
    """
    :param boxes: [N, 4], 此处传进来的框,是经过筛选(选取的得分TopK)之后的
    :param scores: [N]
    :param iou_threshold: 0.7
    :param soft_threshold soft nms 过滤掉得分太低的框 (手动设置)
    :param weight_method 权重方法 1. 线性 2. 高斯
    :return:
    """
    keep = []
    idxs = scores.argsort()
    while idxs.numel() > 0:  # 循环直到null; numel(): 数组元素个数
        # 由于scores得分会改变,所以每次都要重新排序,获取得分最大值
        idxs = scores.argsort()  # 评分排序
        if idxs.size(0) == 1:  # 就剩余一个框了;
            keep.append(idxs[-1])  
            break
        keep_len = len(keep)
        #例如idxs一共4个值,进行一轮之后只看前3个了,再一轮之后只看前2个了....
        #后面的那些并不像以前一样直接删掉,因为可能每次乘了一些值之后又往前提了
        max_score_index = idxs[-(keep_len + 1)]
        max_score_box = boxes[max_score_index][None, :]  # [1, 4]
        idxs = idxs[:-(keep_len + 1)]
        other_boxes = boxes[idxs]  # [?, 4]
        keep.append(max_score_index)  # 位置不能边
        ious = box_iou(max_score_box, other_boxes)  # 一个框和其余框比较 1XM
        # Soft NMS 处理, 和 得分最大框 IOU大于阈值的框, 进行得分抑制
        if weight_method == 1:   # 线性抑制  # 整个过程 只修改分数
            ge_threshod_idxs = idxs[ious[0] >= iou_threshold]
            scores[ge_threshod_idxs] *= (1. - ious[0][ious[0] >= iou_threshold])  # 小于IoU阈值的不变
            # idxs = idxs[scores[idxs] >= soft_threshold]  # 小于soft_threshold删除, 经过抑制后 阈值会越来越小;
        elif weight_method == 2:  # 高斯抑制, 不管大不大于阈值,都计算权重
            scores[idxs] *= torch.exp(-(ious[0] * ious[0]) / sigma) # 权重(0, 1]
            # idxs = idxs[scores[idxs] >= soft_threshold]
        print(idxs)
    keep = idxs.new(keep)  # Tensor
    keep = keep[scores[keep] > soft_threshold]  # 最后处理阈值
    boxes = boxes[keep]  # 保留下来的框
    scores = scores[keep]  # soft nms抑制后得分
    return boxes, scores
 
 
box =  torch.tensor([[2,3.1,7,5],[3,4,8,4.8],[4,4,5.6,7],[0.1,0,8,1]]) 
score = torch.tensor([0.5, 0.3, 0.2, 0.4])
 
output = soft_nms(boxes=box, scores=score, iou_threshold=0.3)
print('IOU of bboxes:')
print(output)

softer nms

Soft-NMS只解决了三个问题中的第一个问题,那么剩下两个问题如何解决呢?

我们先分析第三个问题,对于分类置信度和框的IoU不是强相关的问题,我们需要找到一种方法来衡量框的“位置置信度”,对于第二个问题我们也有办法:只需要让多个框加权合并生成最终的框就可以了,softernms提出这两个想法:

  1. 构建一种IoU的置信度,来建模有多大把握认为当前框和GT是重合的
  2. 提出一种方法根据IoU置信度加权合并多个框优化最终生成框

  • 6
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
### 回答1: soft-nms pytorch源代码是一个基于PyTorch框架实现的软非极大值抑制算法的源代码。该算法可以在目标检测中用于抑制重叠的检测框,从而提高检测的准确性和效率。该源代码提供了一个简单易用的接口,可以方便地集成到现有的目标检测系统中。 ### 回答2: Soft-NMS是一种针对目标检测中非极大值抑制(Non-Maximum Suppression, NMS)的改进算法。Soft-NMS的目的是尽可能保留更多的检测结果,其中,保留哪些检测结果以及去除哪些检测结果是通过计算每个检测框和其他检测框的IoU(Intersection over Union)来决定的。 PyTorch是一个流行的深度学习框架,在PyTorch实现Soft-NMS非常简单。下面是PyTorch官方提供的Soft-NMS源代码: ```python def soft_nms(dets, sigma=0.5, Nt=0.3, threshold=0.001, method=2): """ :param dets: [[x1, y1, x2, y2, score], ...] :param sigma: :param Nt: :param threshold: :param method: :return: indexes to keep """ N = dets.shape[0] indexes = np.arange(N) for i in range(N): pos = i + 1 if i != N - 1: maximum = np.argmax(dets[pos:, 4]) if dets[i, 4] < dets[maximum + pos, 4]: dets[[i, maximum + pos], :] = dets[[maximum + pos, i], :] indexes[[i, maximum + pos]] = indexes[[maximum + pos, i]] t_bbox, t_score = dets[i, :4], dets[i, 4] if method == 1: weight = np.exp(-(np.power((dets[i + 1:, :4] - t_bbox), 2).sum(1) / sigma)) else: weight = np.zeros((N - i - 1,)) _idx = np.where(dets[i + 1:, 4] >= Nt)[0] + i + 1 if len(_idx) > 0: ex_dets = dets[_idx, :] overlap = iou(t_bbox.reshape(1, -1), ex_dets[:, :4]) weight[_idx - (i + 1)] = overlap weight = np.exp(-(weight * weight) / sigma) dets[i + 1:, 4] *= weight score_mask = dets[i + 1:, 4] >= threshold indexes_mask = indexes[i + 1:][score_mask] dets[i + 1:, :] = dets[indexes_mask, :] indexes[i + 1:] = indexes[indexes_mask] if len(indexes_mask) == 0: break keep = np.zeros(N, dtype=np.intp) keep[indexes] = 1 return np.where(keep == 1)[0] ``` 这里,soft_nms函数接受一个包含检测结果的二维数组dets,其中每个元素包含四个坐标[x1, y1, x2, y2]和一个分数score。函数的其他参数包括sigma、Nt、threshold和method等。 对于每个检测框,软NMS算法首先检查其余检测框的IoU。如果另一个检测框的IoU高于给定的Nt阈值,则它的分数将被调整到小于原始分数因子*(1-IoU)。然后,score_mask掩码被用来删掉具有较低分数的检测框,直到达到需要的最终物体数或所有框都不再死亡。最后,保留下来的检测框的索引被返回给用户。 这个PyTorch源代码是一个很好的例子,可以帮助我们了解如何使用Python来自定义各种优化算法,包括Soft-NMS。 ### 回答3: Soft-NMS是一种基于非极大抑制(NMS)的目标检测算法。与传统的NMS算法不同,Soft-NMS通过对重叠框之间的分数进行加权来降低框的置信度,而不是直接将框丢弃。这样可以在一定程度上保留重叠框中的信息。 PyTorch是一种流行的深度学习框架,提供了供用户使用的许多预定义算法和函数。PyTorch实现Soft-NMS的源代码,这使得用户可以直接使用这种功能而不必手动实现。 在PyTorch中,Soft-NMS实现是在torchvision.ops.nms.soft_nms中完成的。它有以下四个参数: - boxes: 包含所有检测框的tensor。 - scores: 所有检测框的分数。 - iou_threshold: 重叠IOU阈值。如果两个框之间的IOU低于此阈值,则不会执行Soft-NMS。 - score_threshold: 分数阈值。如果框的分数低于此阈值,则不会执行Soft-NMS。 整个NMS算法的流程如下: 1. 将分数从高到低排序,并将相应的边界框记录下来。 2. 选择分数最高的框,并记录下该框的索引号。 3. 计算该框与所有其他框之间的IOU值,并使用Soft-NMS算法对其进行加权。 4. 删除其余重叠框,并在剩下的框中重复步骤2-4,直到所有框都被处理。 调用soft_nms函数后,将返回保留下来框的索引列表。然后可以使用这个索引列表来关联boxes和scores,并对检测到的目标进行可视化或其他后处理操作。 在使用Soft-NMS时,需要根据具体情况调整两个阈值。如果两个阈值设置得太低,可能会误保留一些低质量的检测框。如果设置得过高,可能会丢失一些真实的目标。因此,建议在数据集上进行测量和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值