众所周知,NMS在计算机视觉和深度学习领域有着广泛的应用,特别是目标检测,视频行为动作定位等都有所涉及。其目的是消除重复的检测框或者时间段。下面以行人检测为例进行说明,目标检测算法一般都会给出检测目标的位置和预测置信度(或分数),然后NMS算法会根据分数排序(由高到底)检测框,对于分数较低的检测框会在一定阈值(IOU)条件下舍弃。
IOU的计算有两种计算方法,一种是union,另一种是min,看下图说明就明白了~
其中,广泛使用的是union模式,min模式非常适合目标检测框有包含的情况,以下实例可以看出很大区别。
一、结果图对比
先上图,NMS前行人检测效果图:
NMS后(union,IOU=0.5)为:
NMS后(min,IOU=0.5)为:
从上面图比较看出,min方法在很大程度上抑制了内部检测框的存在。
素材图片+代码下载地址:https://download.csdn.net/download/cuixing001/10841627
二、代码实现
function [selectedBbox,selectedScore,index] = nms2(bbox,score)
% 功能:单个类别的非极大值抑制算法实现
% 输入:bbox, M*4 double类型, 每一行代表[x,y,width,height]
% score, M*1 double类型,预测分数
% 输出: selectedBbox, 最佳的boxes,N*4 double类型, [x,y,width,height]
% selectedScore,N*1 double类型,预测分数
% index , N*1 double类型,非极大值抑制候选索引
% author:cuixing
% email:cuixingxing150@gmail.com
%
%% parameters
IOU = 0.5; % 0-1之间
type = 'min';
%% algorithm
selectedBbox =[];selectedScore =[];index=[];
[~,indexes] = sort(score,'descend');
bbox = bbox(indexes,:);
score = score(indexes,:);
while true
if size(bbox,1)>=2 % 仍可迭代
minx = min(bbox(1,1),bbox(2:end,1));
miny = min(bbox(1,2),bbox(2:end,2));
maxx = max(bbox(1,1)+bbox(1,3),bbox(2:end,1)+bbox(2:end,3));
maxy = max(bbox(1,2)+bbox(1,4),bbox(2:end,2)+bbox(2:end,4));
width = max(bbox(1,3)+bbox(2:end,3)-(maxx-minx),0);
height = max(bbox(1,4)+bbox(2:end,4)-(maxy-miny),0);
inter = width.*height; % 交集面积
if strcmp(type,'union') % 方法选择
o = inter./(bbox(1,3)*bbox(1,4)+bbox(2:end,3).*bbox(2:end,4)-inter);% 交并比
else
o = inter./min(bbox(1,3)*bbox(1,4),bbox(2:end,3).*bbox(2:end,4));% 交并比
end
del_index = o>IOU; % 需要删除的索引值
selectedBbox = [selectedBbox;bbox(1,:)]; % 每次迭代第一组必定是候选项,分数最大
selectedScore = [selectedScore;score(1,:)];% 每次迭代第一组必定是候选项,分数最大
index = [index;indexes(1,:)];% 每次迭代第一组必定是候选项,分数最大
bbox = bbox(2:end,:);% 更新bbox
score = score(2:end,:);% 更新score
indexes = indexes(2:end,:);% 更新indexes
bbox(del_index,:) = []; % 删除重复的
score(del_index,:) = [];
indexes(del_index,:) = [];
elseif size(bbox,1)==1 % 迭代最后一次结束
selectedBbox = [selectedBbox;bbox(1,:)];
selectedScore = [selectedScore;score(1,:)];
index = [index;indexes(1,:)];
break;
else % 迭代结束
break;
end
end
主函数为:
detector = peopleDetectorACF; % 2017a可使用ACF算法检测行人
I = imread('hongkong.jpg');
[bbox,score] = detect(detector,I,'MinSize',[146,64],'SelectStrongest',false);
% NMS前
I1 = insertObjectAnnotation(I,'rectangle',bbox,...
cellstr(num2str(score)),'Color','g');
% NMS算法
[selectedBbox,selectedScore,index] = nms2(bbox,score);
I2 = insertObjectAnnotation(I,'rectangle',selectedBbox,...
cellstr(num2str(selectedScore)),'Color','g');
figure, imshow(I1); ...
title('NMS前');
figure, imshow(I2); ...
title('NMS后');
Reference:
http://ww2.mathworks.cn/help/vision/ref/selectstrongestbboxmulticlass.html
http://ww2.mathworks.cn/help/vision/ref/bboxprecisionrecall.html