nms(non maximum suppression) 非极大值抑制算法在检测任务中是非常常用的,而且检测结果中不可避免出现在同一个目标位置处
产生多个候选框
;因此nms的作用是剔除掉
检测结果中重合率(IOU)大于给定阈值(threshold)的候选框
,最终期望
达到在一个目标位置处只保留一个最优检测结果。
算法原理
方法的输入参数由两部分组成:dets 所有候选区域,包含每一个检测框的左上和右下角位置坐标以及置信度;thresh阈值
我们首先根据每个候选框的置信度进行一个由大到小的排序,置信度最高的排在第一位;
循环开始,首先取置信度最高候选框, 将其加入到最终返回值列表中,然后计算其和剩下所有候选框区域的交并比iou,剔除掉和当前候选区域计算结果中iou>thresh
的候选框, 对剩下的候选区域继续执行上述的循环直到整个数组为空。
nms.py
import numpy as np
# 输入: dets为候选框; thresh为iou阈值
# 返回值 keep
def nms(dets, thresh):
x1 = dets[:, 0]
y1 = dets[:, 1]
x2 = dets[:, 2]
y2 = dets[:, 3]
scores = dets[:, -1]
order = np.argsort(scores)[::-1] # 排序后的索引,由大到小
areas = (x2-x1) * (y2-y1)
# print(areas)
# 最后保留的结果
keep = []
while order.size > 0:
i = order[0] # 取出置信度最高的窗口
keep.append(i)
# 计算窗口i 和其他所有窗口 交叠部分面积
xx1 = np.maximum(x1[i], x1[order[1:]])
yy1 = np.maximum(y1[i], y1[order[1:]])
xx2 = np.minimum(x2[i], x2[order[1:]])
yy2 = np.minimum(y2[i], y2[order[1:]])
w = np.maximum(0.0, xx2 - xx1)
h = np.maximum(0.0, yy2 - yy1)
inter = w * h
# 计算交并比iou
ovr = inter / ( areas[i] + areas[order[1:] ] - inter )
print(ovr)
# inds 为 所有与窗口i的iou值小于threshold值的索引
# np.where返回值为tuple,*[0]才为真正想要的数据
inds = np.where(ovr <= thresh)[0]
print("IOU合并 ", i, order[np.where(ovr > thresh)[0]+1])
# 因为窗口i代表自身,inds + 1即可对应于order中那些不满足条件的窗口索引位置
order = order[inds + 1]
return dets[keep]
测试部分
模拟给出了几组候选框信息,对其执行非极大值抑制操作,最终剩下3组候选框。
test.py
import cv2 as cv
import numpy as np
import nms
boxes = [[200, 200, 400, 400, 0.99],
[220, 220, 420, 420, 0.9],
[100, 100, 150, 150, 0.82],
[200, 240, 400, 440, 0.5],
[150, 250, 300, 400, 0.88]]
boxes = np.array(boxes)
overlap = 0.6 # 阈值
pick = nms.nms(boxes, overlap)
print(pick)
###
canvas = np.zeros((500, 500, 3), dtype='uint8')
color = (0, 255, 255)
for box in boxes:
x1, y1, x2, y2, _ = map(int, box)
cv.rectangle(canvas, (x1, y1), (x2, y2), color, 5)
color = (255, 0, 255)
for box in pick:
# print(box)
x1, y1, x2, y2, _ = map(int, box)
cv.rectangle(canvas, (x1, y1), (x2, y2), color, 2)
cv.imwrite("result.png", canvas)
cv.imshow('nms', canvas)
cv.waitKey()
结果和分析:
5个黄色框是最初出入的所有候选区域,经过nms算法之后,只保留了3个粉红色框部分,剔除掉的2个黄色候选框是因为和200, 200, 400, 400, 0.99
这个候选框计算的IOU结果大于了给定的阈值
使用OpenCV进行可视化,左上角坐标为(0,0),最终结果如图
参考:
https://blog.csdn.net/hongxingabc/article/details/78996407
https://www.cnblogs.com/king-lps/p/8040458.html