其他分享
首页 > 其他分享> > 非极大值抑制 (Non-Maximum Suppression, NMS)

非极大值抑制 (Non-Maximum Suppression, NMS)

作者:互联网

目录

NMS 基本过程

在上图中,候选框 C 的得分比 A 要低,在评测时,C 候选框会被当做一个 False Positive 来看待,从而降低模型精度。实际上,由于候选框 A 的质量要比 C 好,理想的输出是 A 而不是 C,我们希望能够抑制掉候选框 C


NMS 方法


NMS 方法的实现

def nms(bboxes, scores, thresh=0.5):
	"""
	Args:
		bboxes: 所有预测框的左上点坐标、右下点坐标 (图片的最左上点坐标为 [0, 0])
		scores: 所有预测框的得分
		thresh: 设定的 IoU 阈值
	"""
    x1, y1 = bboxes[:,0], bboxes[:,1]	# 所有预测框的左上角坐标
    x2, y2 = bboxes[:,2], bboxes[:,3]	# 所有预测框的右下角坐标
    # 计算每个 box 的面积
    areas = (x2 - x1) * (y2 - y1)
    # 对得分进行降序排列,order 为降序排列的索引
    _, order = scores.sort(0, descending=True)
    # keep 保留了 NMS 留下的边框 box
    keep = []

    while order.numel() > 0:
        if order.numel() == 1:   # 保留框只剩一个         
        	i = order.item()
            keep.append(i)
            break
        else:
            i = order[0].item()	 # 保留 scores 最大的那个框 box[i]
            keep.append(i)
        # 巧妙利用 tensor.clamp 函数求取每一个框与当前框的最大值和最小值
        xx1 = x1[order[1:]].clamp(min=x1[i])	# 取 Anchor[i] 与其余 Anchors 的最大 x1, y1
        yy1 = y1[order[1:]].clamp(min=y1[i])	
        xx2 = x2[order[1:]].clamp(max=x2[i])	# 取 Anchor[i] 与其余 Anchors 的最小 x2, y2
        yy2 = y2[order[1:]].clamp(max=y2[i])
        # 求取每一个框与当前框的重合部分面积
        inter = (xx2 - xx1).clamp(min=0) * (yy2 - yy1).clamp(min=0)
        # 计算每一个框与当前框的 IoU
        iou = inter / (areas[i] + areas[order[1:]] - inter + 1e-9)
        # 保留 IoU 小于阈值的边框索引 (nonzero 用于返回非零元素的索引)
        idx = (iou <= threshold).nonzero().squeeze()
        if idx.numel() == 0:
            break
        # 这里的 +1 是为了补充 idx 与 order 之间的索引差
        order = order[idx+1]

	# 返回保留下的所有边框的索引值
    return torch.LongTensor(keep)

NMS 的缺陷

针对上述问题陆续产生了一系列改进的方法,如 Soft NMSSofter NMSIoU-Net

抑制得分: Soft NMS

加权平均: Softer NMS

定位置信度: IoU-Net

参考文献

标签:clamp,得分,Non,NMS,IoU,Maximum,边框,order
来源: https://blog.csdn.net/weixin_42437114/article/details/121791564