0.绪:
非极大值抑制-Non Maximum Suppression,简称NMS;
经常应用在目标检测的后期=物体边界框去除;NMS对检测得到的全部 boxes 进行局部的最大搜索,以搜索某邻域范围内的最大值,从而滤处一部分 boxes,提升最终的检测精度.
1.过程:
去除冗余的重叠 Boxes,对全部的 Boxes 进行迭代-遍历-消除.
s1.将所有框的得分排序,选中最高分及其对应的框;
s2.遍历其余的框,如果和当前最高分框的交并比IOU大于设定阈值,记录此框索引;
遍历完成后,保存最高得分框,并在原集合内删除最高得分框和大于阈值的框;
s3.从未处理的框中继续选择一个得分最高的,重复上述过程.
2.输入输出:
输入:检测到的Boxes(同一个物体可能被检测到很多Boxes,每个box均有分类score);
输出:最优的Box;
3.python代码:
依赖:python2.7和opencv-python
main.py:
# -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import numpy as np
import cv2
import nms
if __name__ == "__main__":
boxes = [[50.,50.,100.,100.,0.95],
[55.,55.,100.,100.,0.75],
[45.,45.,100.,100.,0.83],
[200.,50.,100.,100.,0.81],
[195.,55.,100.,100.,0.67]]
boxes = np.array(boxes)
I = np.zeros((400, 400), dtype=np.uint8)
I = cv2.cvtColor(I, cv2.COLOR_GRAY2BGR)
I1 = I.copy()
scores = boxes[:,4]
for box in boxes:
# 画矩形框
cv2.rectangle(I, (int(box[0]), int(box[1])), (int(box[0]+box[2]), int(box[1]+box[3])), (0, 255, 0), 1)
cv2.namedWindow("image")
cv2.imshow("image", I)
nms_max_overlap = 0.5
indices = nms.non_max_suppression( boxes, nms_max_overlap, scores)
print(indices)
for ii in indices:
# 画矩形框
cv2.rectangle(I1, (int(boxes[ii,0]), int(boxes[ii,1])), (int(boxes[ii,0]+boxes[ii,2]), int(boxes[ii,1]+boxes[ii,3])), (0, 255, 0), 1)
cv2.namedWindow("dst")
cv2.imshow("dst", I1)
cv2.waitKey()
nms.py:
# -*- coding: utf-8 -*-
# vim: expandtab:ts=4:sw=4
import numpy as np
import cv2
def non_max_suppression(boxes, max_bbox_overlap, scores=None):
"""Suppress overlapping detections.
Original code from [1]_ has been adapted to include confidence score.
.. [1] http://www.pyimagesearch.com/2015/02/16/
faster-non-maximum-suppression-python/
Examples
--------
>>> boxes = [d.roi for d in detections]
>>> scores = [d.confidence for d in detections]
>>> indices = non_max_suppression(boxes, max_bbox_overlap, scores)
>>> detections = [detections[i] for i in indices]
Parameters
----------
boxes : ndarray
Array of ROIs (x, y, width, height).
max_bbox_overlap : float
ROIs that overlap more than this values are suppressed.
scores : Optional[array_like]
Detector confidence score.
Returns
-------
List[int]
Returns indices of detections that have survived non-maxima suppression.
"""
if len(boxes) == 0:
return []
boxes = boxes.astype(np.float) #将数组类型转为为float
pick = []
x1 = boxes[:, 0]
y1 = boxes[:, 1]
x2 = boxes[:, 2] + boxes[:, 0] #x1+w
y2 = boxes[:, 3] + boxes[:, 1] #y1+h
area = (x2 - x1 + 1) * (y2 - y1 + 1)
if scores is not None:
idxs = np.argsort(scores) #从小到大排序=顺序
else:
idxs = np.argsort(y2)
while len(idxs) > 0:
last = len(idxs) - 1
i = idxs[last]
pick.append(i)
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]])
w = np.maximum(0, xx2 - xx1 + 1)
h = np.maximum(0, yy2 - yy1 + 1)
overlap = (w * h) / area[idxs[:last]]
idxs = np.delete(
idxs, np.concatenate(
([last], np.where(overlap > max_bbox_overlap)[0])))
return pick
结果:
参考:
1.https://blog.youkuaiyun.com/qq_38906523/article/details/80195119
2.https://blog.youkuaiyun.com/zziahgf/article/details/78525279
3.https://blog.youkuaiyun.com/shuzfan/article/details/52711706
4.https://www.pyimagesearch.com/2015/02/16/faster-non-maximum-suppression-python/ 源码所在