非极大值抑制(nonMaximumSuppression):简称为NMS算法。是一种获取局部最大值的有效方法。在目标检测中运用NMS可以剔除多余的候选框(这些框往往具有较高的重合性)。
非极大值抑制算法的Python实现
import numpy as np
import cv2
def non_max_suppression(boxes, max_bbox_overlap, scores=None):
"""Suppress overlapping detections.
非极大值抑制:非极大值抑制的目的是为了去除相似的候选框,从而减少数据量。大于max_bbox_overlap的框被剔除,也就是说max_bbox_overlap越大保留的框越少
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]
from deep_sort.iou_matching import iou
from deep_sort.preprocessing import non_max_suppression
import numpy as np
#候选框
candidates = [[20,20,51,51],
[19,18,49,49],
[18,17,55,55],
[10,10,30,9]
]
候选框置信度
scores= [0.9,0.9,0.0,0.1]
candidates= np.array(candidates)
b = non_max_suppression(candidates,0.1,scores)
print(b)
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)
pick = []
x1 = boxes[:, 0]
y1 = boxes[:, 1]
x2 = boxes[:, 2] + boxes[:, 0]
y2 = boxes[:, 3] + boxes[:, 1]
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
使用:
from deep_sort.iou_matching import *
from deep_sort.preprocessing import *
import numpy as np
import cv2
#创建一个空的面板
window_img = np.zeros((900,900,3),dtype="uint8")
#非极大值抑制阈值
max_bbox_overlap =0.4
#bbox为真实boundingbox的坐标
bbox = [20,20,50,50]
#candidates:候选框。 表示形式(top_left_x,top_left_y,length,width),此处创建了四个候选框
candidates = [[20,20,51,71],
[19,18,49,69],
[18,17,65,55],
[10,10,30,59]
]
#每个候选框对应的score(置信度)
scores= [0.9,0.9,0.0,0.1]
#把candidates,bbox 转化为matrices
candidates= np.array(candidates)
bbox = np.array(bbox)
#在面板上绘制四个候选框,用白线绘制。
for i in range(4):
cv2.rectangle(window_img,(candidates[i,0],candidates[i,1]),
(candidates[i,0]+candidates[i,2],
candidates[i,1]+candidates[i,3]),
(255,255,255))
#在面板上绘制真实的boundingbox,用蓝色绘制。
cv2.rectangle(window_img,(bbox[0],bbox[1]),
(bbox[0]+bbox[2],bbox[1]+bbox[3]),
(255,0,0),thickness=3)
#计算IOU
a= iou(bbox,candidates)
print(a)
#进行非极大值抑制,返回值b为筛选后的候选框的索引号(类型为list)如:b=[2,3],表示筛选后只保留了第3个和第4个候选框
b = non_max_suppression(candidates,max_bbox_overlap,scores)
#
print(b)
#在面板上绘制筛选后的候选框,用红色绘制
for i in b:
cv2.rectangle(window_img,(candidates[i,0],candidates[i,1]),
(candidates[i,0]+candidates[i,2],
candidates[i,1]+candidates[i,3]),
(0,0,255))
#显示图片
cv2.imshow("xulong666",window_img)
cv2.waitKey(0)
显示结果: