非极大值抑制 (NMS)及其matlab代码实现

非极大值抑制(Non Maximum Suppression)最常用的领域就是目标检测,比如人脸检测,物体检测等。下面也就其在目标检测领域的应用及其代码实现。

目标检测的基本流程如下:


具体示意图如下:



所以,在输出的ScoreMap中,像素数为numel(ScoreMap),则输出检测到的Box数目为numel(ScoreMap)个,其维数为(4,numel(ScoreMap)),那么在这么多个输出的detBox(检测到的Box)中,哪一个(假设图像中只含一个目标)呢?这就需要采用非极大值抑制去除冗余的detBox,抑制的过程是一个迭代-遍历-消除的过程。具体如下代码实现:

im = imread(testImages{3}) ;
im = im2single(im) ;

% Compute detections
[detections, scores] = detect(im, w, hogCellSize, scales) ;

% Non-maxima suppression
keep = boxsuppress(detections, scores, 0.25) ;

detections = detections(:, keep) ;
scores = scores(keep) ;

% Further keep only top detections
detections = detections(:, 1:10) ;
scores = scores(1:10) ;

function keep = boxsuppress(boxes, scores, threshold)
% BOXSUPPRESS Box non-maxima suprression(非最大值抑制)
%   KEEP = BOXSUPPRESS(BOXES, SCORES, THRESHOLD)

% remove any empty box (xmax < xmin or ymax < ymin)
scores(any([-1 0 1 0 ; 0 -1 0 1] * boxes < 0)) = -inf ;

keep = false(1, size(boxes,2)) ;
while true
  [score, best] = max(scores) ;
  if score == -inf, break ; end
  keep(best) = true ;
  remove = boxinclusion(boxes(:,best), boxes, 'pascalFormat', true) >= threshold ;
  scores(remove) = -inf ;
  scores(best) = -inf ; % `best` is not in `remove` if threshold > 1
end

function dist = calcBoxInclusion(A, B, varargin)
%%boxinclusion
 % GETBOXOVERLAP
%   A and B have a box for each column, in the format [xmin ymin xmax
%   ymax]. The resulting matrix dist has A's boxes along the rows
%   and B's boxes along the columns and contains the percentage of
%   the area of each box B contained in the box A.

opts.pascalFormat = false ;
opts = vl_argparse(opts, varargin) ;

m = size(A,2) ;
n = size(B,2) ;
O = [] ;

if m==0 || n==0, dist = zeros(m,n) ; return ; end

om = ones(1,m) ;
on = ones(1,n) ;

if opts.pascalFormat
  A(3:4,:) = A(3:4,:) + 1 ;
  B(3:4,:) = B(3:4,:) + 1 ;
end

% find length Ox of the overlap range [x1, x2] along x
% x1 cannot be smaller than A.xmin B.xmin
% x2 cannot be larger  than A.xmax B.xmax
% Ox is x2 - x1 or 0

x1 = max(A(1*on,:)', B(1*om,:)) ;
x2 = min(A(3*on,:)', B(3*om,:)) ;
Ox = max(x2 - x1, 0) ;

y1 = max(A(2*on,:)', B(2*om,:)) ;
y2 = min(A(4*on,:)', B(4*om,:)) ;
Oy = max(y2 - y1, 0) ;

% are of the intersection
areaInt = Ox .* Oy ;

% area of the union is sum of areas - inersection
areaA = prod(A(3:4,:) - A(1:2,:)) ;
areaB = prod(B(3:4,:) - B(1:2,:)) ;

% final distance matrix
dist = areaInt ./ (areaB(om,:) + eps) ;

重点部分注释:

scores(any([-1 0 1 0 ; 0 -1 0 1] * boxes < 0)) = -inf ;
这里要注意的是boxes的格式,即为[xmin,ymin,xmax,ymax],其与[-1 0 1 0;0 -1 0 1]相乘,如果其值小于零,也就是xmax<xmin, ymax<ymin,这个框也就无效了,要去除,就是把其对应的Score的值赋为无穷小,在非最大值抑制时不予考虑。


x1 = max(A(1*on,:)', B(1*om,:)) ;
x2 = min(A(3*on,:)', B(3*om,:)) ;

y1 = max(A(2*on,:)', B(2*om,:)) ;
y2 = min(A(4*on,:)', B(4*om,:)) ;

要理解此段代码,见下图所示:


重叠部分的面积即为左上角(x21,y21)(框2的坐标小值)到右下角(x12,y12)(框1坐标的大值)矩形的面积。因为框1已经是按照Score的较大值像素点检测出的Box,框2是按照次较大值检测的Box,如果两者的Box有较大面积重合(设定一个阈值),此时可以说明框1和框2都在目标附近,但是框1更准确一点定位到目标,那么框2也就没必要保留了。继续迭代下一个检测到的Box,是否满足消除条件决定是否保留Box,这就是非最大值抑制。











参考:

1. NMS——非极大值抑制




以下是通过非极大值抑制改进Canny算子的Matlab代码: ```matlab function [edgeImage] = canny_nms(image, sigma, lowThreshold, highThreshold) % Step 1: Apply Gaussian filter to the image kernelSize = ceil(sigma*3)*2 + 1; % Calculate kernel size based on sigma gaussianFilter = fspecial('gaussian', kernelSize, sigma); % Create Gaussian filter filteredImage = imfilter(image, gaussianFilter, 'replicate'); % Apply Gaussian filter % Step 2: Calculate image gradients [Gx, Gy] = gradient(filteredImage); magnitude = sqrt(Gx.^2 + Gy.^2); orientation = atan2(Gy, Gx) * 180 / pi; % Convert to degrees % Step 3: Non-maximum suppression nmsImage = zeros(size(filteredImage)); for i = 2:size(filteredImage,1)-1 for j = 2:size(filteredImage,2)-1 if (orientation(i,j) < 0) % Convert negative angles to positive angles orientation(i,j) = orientation(i,j) + 180; end if ((orientation(i,j) >= 0 && orientation(i,j) < 22.5) || (orientation(i,j) >= 157.5 && orientation(i,j) < 180)) if (magnitude(i,j) >= magnitude(i,j-1) && magnitude(i,j) >= magnitude(i,j+1)) nmsImage(i,j) = magnitude(i,j); end elseif ((orientation(i,j) >= 22.5 && orientation(i,j) < 67.5) || (orientation(i,j) >= 112.5 && orientation(i,j) < 157.5)) if (magnitude(i,j) >= magnitude(i-1,j-1) && magnitude(i,j) >= magnitude(i+1,j+1)) nmsImage(i,j) = magnitude(i,j); end elseif ((orientation(i,j) >= 67.5 && orientation(i,j) < 112.5)) if (magnitude(i,j) >= magnitude(i-1,j) && magnitude(i,j) >= magnitude(i+1,j)) nmsImage(i,j) = magnitude(i,j); end end end end % Step 4: Apply double thresholding highThreshold = max(nmsImage(:)) * highThreshold; lowThreshold = highThreshold * lowThreshold; edgeImage = zeros(size(nmsImage)); strongEdgesRow = []; strongEdgesCol = []; for i = 2:size(nmsImage,1)-1 for j = 2:size(nmsImage,2)-1 if (nmsImage(i,j) >= highThreshold) edgeImage(i,j) = 1; strongEdgesRow = [strongEdgesRow i]; strongEdgesCol = [strongEdgesCol j]; elseif (nmsImage(i,j) >= lowThreshold && nmsImage(i,j) < highThreshold) if (nmsImage(i-1,j-1) >= highThreshold || nmsImage(i-1,j) >= highThreshold || nmsImage(i-1,j+1) >= highThreshold || nmsImage(i,j-1) >= highThreshold || nmsImage(i,j+1) >= highThreshold || nmsImage(i+1,j-1) >= highThreshold || nmsImage(i+1,j) >= highThreshold || nmsImage(i+1,j+1) >= highThreshold) edgeImage(i,j) = 1; strongEdgesRow = [strongEdgesRow i]; strongEdgesCol = [strongEdgesCol j]; end end end end % Step 5: Hysteresis thresholding while ~isempty(strongEdgesRow) currentRow = strongEdgesRow(1); currentCol = strongEdgesCol(1); strongEdgesRow(1) = []; strongEdgesCol(1) = []; if (currentRow > 1 && currentRow < size(edgeImage,1) && currentCol > 1 && currentCol < size(edgeImage,2)) for i = -1:1 for j = -1:1 if (edgeImage(currentRow+i, currentCol+j) == 0 && nmsImage(currentRow+i, currentCol+j) >= lowThreshold) edgeImage(currentRow+i, currentCol+j) = 1; strongEdgesRow = [strongEdgesRow currentRow+i]; strongEdgesCol = [strongEdgesCol currentCol+j]; end end end end end end ``` 此代码中,我们首先应用高斯滤波器对图像进行平滑处理,然后计算图像梯度和方向。接下来,我们执行非极大值抑制来获得边缘强度图像。然后,我们应用双阈值法来确定边缘像素的强度。最后,我们执行滞后阈值化来消除弱边缘像素。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值