非极大值抑制(Non-Maximum Suppression,NMS),顾名思义就是抑制不是极大值的元素,可以理解为局部最大搜索。这个局部代表的是一个邻域,邻域有两个参数可变,一是邻域的维数,二是邻域的大小。而是用于目标检测中提取分数最高的窗口的。例如在行人检测中,滑动窗口经提取特征,经分类器分类识别后,每个窗口都会得到一个分数。但是滑动窗口会导致很多窗口与其他窗口存在包含或者大部分交叉的情况。这时就需要用到NMS来选取那些邻域里分数最高(是行人的概率最大),并且抑制那些分数低的窗口。
Numpy 你语法都不懂就别往下看了,图中的每个知识点都是一个小程序
def stand_nms_non_max_suppression(boxes, probs=None, overlapThresh=0.3, list_res=None):
# if there are no boxes, return an empty list
if len(boxes) == 0:
return []
# if the bounding boxes are integers, convert them to floats -- this
# is important since we'll be doing a bunch of divisions
if boxes.dtype.kind == "i":
boxes = boxes.astype("float")
# initialize the list of picked indexes
pick = []
# grab the coordinates of the bounding boxes
x1 = boxes[:, 0]
y1 = boxes[:, 1]
x2 = boxes[:, 2]
y2 = boxes[:, 3]
# compute the area of the bounding boxes and grab the indexes to sort
# (in the case that no probabilities are provided, simply sort on the
# bottom-left y-coordinate)
area = (x2 - x1 + 1) * (y2 - y1 + 1)
idxs = y2
dt = np.dtype([('age', np.int), ('name', np.float)])
# if probabilities are provided, sort on them instead
if probs is not None:
idxs = probs
# sort the indexes
idxs = np.argsort(idxs)
# keep looping while some indexes still remain in the indexes list
while len(idxs) > 0:
# grab the last index in the indexes list and add the index value
# to the list of picked indexes
last = len(idxs) - 1
i = idxs[last]
# pick.append(i)
# find the largest (x, y) coordinates for the start of the bounding
# box and the smallest (x, y) coordinates for the end of the bounding
# box
xx1 = np.maximum(x1[i], x1[idxs[:last]])
yy1 = np.maximum(y1[i], y1[idxs[:last]])
xx2 = np.minimum(x2[i], x2[idxs[:last]])
yy2 = np.minimum(y2[i], y2[idxs[:last]])
# compute the width and height of the bounding box
w = np.maximum(0, xx2 - xx1 + 1)
h = np.maximum(0, yy2 - yy1 + 1)
# print('aaaa')
xxx = boxes[i][0]
yyy = boxes[i][1]
# if len(list_res):
# print(xxx, yyy,list_res[int(yyy)][int(xxx)])
# else:
# print(xxx, yyy)
# print('bbbb===',i)
# compute the ratio of overlap
overlap = (w * h) / area[idxs[:last]]
list_similar = np.where(overlap > overlapThresh)
# print(list_similar)
# if 0:
if len(list_similar) and len(list_res):
get_max_list = np.array([(i, list_res[int(yyy)][int(xxx)])], dtype=dt)
for x in np.nditer(list_similar):
# print(x,',')
xxx = boxes[x][0]
yyy = boxes[x][1]
nearly_rect_list = np.array([(x,list_res[int(yyy)][int(xxx)])], dtype=dt)
get_max_list = np.append(get_max_list, nearly_rect_list)
after_sort = np.sort(get_max_list, order=['name', 'age'])
nLen1 = len(after_sort) - 1
# print('nLen1 = ',after_sort[nLen1])
# print(after_sort[nLen1][0],after_sort[nLen1][1])
pick.append(after_sort[nLen1][0])
else:
pick.append(i)
# delete all indexes from the index list that have overlap greater
# than the provided overlap threshold
idxs = np.delete(idxs, np.concatenate(([last],
np.where(overlap > overlapThresh)[0])))
return boxes[pick].astype("int")