非极大值抑制(NMS):抑制不是极大值的元素,可以理解为局部最大搜索,这个局部代表一个邻域,邻域有两个参数可调节:一为邻域的维数,二为邻域的大小。行人检测后期,对检测出的窗口要执行非极大值抑制进行窗口的融合,从而过滤掉一些内部窗口等,达到窗口融合效果,从而使检测的准确率更高。
Histogram of Oriented Gradients for Objection Detection的原理可以被分解成6部分:
- 正类图像取样
- 负类图像取样
- 训练一个线性SVM分类器
- 执行hard-negative mining(不会翻)
- 用hard-negative样本从新训练你的SVM分类器
- 在你的测试集评估你的分类器,用非极大值抑制算法去忽视多余的、重叠的bounding boxes。
这些步之后,你将的到一个很棒的物体检测器
NMS实现
一个向量化的实现:
#coding:utf-8
import numpy as np
def py_cpu_nms(dets, thresh):
"""Pure Python NMS baseline."""
x1 = dets[:, 0]#第0列
y1 = dets[:, 1]
x2 = dets[:, 2]
y2 = dets[:, 3]
scores = dets[:, 4]
areas = (x2 - x1 + 1) * (y2 - y1 + 1)
#从大到小排列,取index
order = scores.argsort()[::-1]
#keep为最后保留的边框
keep = []
while order.size > 0:
#order[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 + 1)
h = np.maximum(0.0, yy2 - yy1 + 1)
inter = w * h
#交/并得到iou值
ovr = inter / (areas[i] + areas[order[1:]] - inter)
#ind为所有与窗口i的iou值小于threshold值的窗口的index,其他窗口此次都被窗口i吸收
inds = np.where(ovr <= thresh)[0]
#下一次计算前要把窗口i去除,所有i对应的在order里的位置是0,所以剩下的加1
order = order[inds + 1]
return keep
import numpy as np
def non_max_suppression_slow(boxes, overlapThresh):
# if there are no boxes, return an empty list,图片中没有生成box,返回空列表
if len(boxes) == 0:
return []
# 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 sort the bounding
# boxes by the bottom-right y-coordinate of the bounding box
area = (x2 - x1 + 1) * (y2 - y1 + 1)
idxs = np.argsort(y2)
# keep looping while some indexes still remain in the indexes
# list
while len(idxs) > 0:
# grab the last index in the indexes list, add the index
# value to the list of picked indexes, then initialize
# the suppression list (i.e. indexes that will be deleted)
# using the last index
last = len(idxs) - 1
i = idxs[last]
pick.append(i)
suppress = [last]
# loop over all indexes in the indexes list
for pos in xrange(0, last):
# grab the current index
j = idxs[pos]
# 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 = max(x1[i], x1[j])
yy1 = max(y1[i], y1[j])
xx2 = min(x2[i], x2[j])
yy2 = min(y2[i], y2[j])
# compute the width and height of the bounding box
w = max(0, xx2 - xx1 + 1)
h = max(0, yy2 - yy1 + 1)
# compute the ratio of overlap between the computed
# bounding box and the bounding box in the area list
overlap = float(w * h) / area[j]
# if there is sufficient overlap, suppress the
# current bounding box
if overlap > overlapThresh:
suppress.append(pos)
# delete all indexes from the index list that are in the
# suppression list
idxs = np.delete(idxs, suppress)
# return only the bounding boxes that were picked
return boxes[pick]
Non-Maximum Suppression for Object Detection in Python
https://blog.csdn.net/wfh2015/article/details/79925188