You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
3.9 KiB
146 lines
3.9 KiB
%PEAK2 Find peaks in a matrix
|
|
%
|
|
% ZP = PEAK2(Z, OPTIONS) are the peak values in the 2-dimensional signal Z.
|
|
%
|
|
% [ZP,IJ] = PEAK2(Z, OPTIONS) as above but also returns the indices of the
|
|
% maxima in the matrix Z. Use SUB2IND to convert these to row and column
|
|
% coordinates
|
|
%
|
|
% Options::
|
|
% 'npeaks',N Number of peaks to return (default all)
|
|
% 'scale',S Only consider as peaks the largest value in the horizontal
|
|
% and vertical range +/- S points.
|
|
% 'interp' Interpolate peak (default no interpolation)
|
|
% 'plot' Display the interpolation polynomial overlaid on the point data
|
|
%
|
|
% Notes::
|
|
% - To find minima, use PEAK2(-V).
|
|
% - The interp options fits points in the neighbourhood about the peak with
|
|
% a paraboloid and its peak position is returned.
|
|
%
|
|
% See also PEAK, SUB2IND.
|
|
|
|
|
|
% Copyright (C) 1993-2011, by Peter I. Corke
|
|
%
|
|
% This file is part of The Machine Vision Toolbox for Matlab (MVTB).
|
|
%
|
|
% MVTB is free software: you can redistribute it and/or modify
|
|
% it under the terms of the GNU Lesser General Public License as published by
|
|
% the Free Software Foundation, either version 3 of the License, or
|
|
% (at your option) any later version.
|
|
%
|
|
% MVTB is distributed in the hope that it will be useful,
|
|
% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
% GNU Lesser General Public License for more details.
|
|
%
|
|
% You should have received a copy of the GNU Leser General Public License
|
|
% along with MVTB. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
% Copyright (c) Peter Corke 1/96
|
|
|
|
function [zp,xypout, aout] = peak2(z, varargin)
|
|
|
|
% process input options
|
|
opt.npeaks = 2;
|
|
opt.scale = 1;
|
|
opt.interp = false;
|
|
|
|
[opt,args] = tb_optparse(opt, varargin);
|
|
|
|
|
|
% create a neighbourhood mask for non-local maxima
|
|
% suppression
|
|
h = opt.scale;
|
|
w = 2*h+1;
|
|
M = ones(w,w);
|
|
M(h+1,h+1) = 0;
|
|
|
|
% compute the neighbourhood maximum
|
|
znh = iwindow(double(z), M, 'max', 'wrap');
|
|
|
|
% find all pixels greater than their neighbourhood
|
|
k = find(z > znh);
|
|
|
|
|
|
% sort these local maxima into descending order
|
|
[zpk,ks] = sort(z(k), 'descend');
|
|
|
|
k = k(ks);
|
|
|
|
npks = min(length(k), opt.npeaks);
|
|
k = k(1:npks);
|
|
|
|
[y,x] = ind2sub(size(z), k);
|
|
xy = [x y]';
|
|
|
|
|
|
% interpolate the peaks if required
|
|
if opt.interp
|
|
|
|
|
|
xyp = [];
|
|
zp = [];
|
|
ap = [];
|
|
|
|
% for each previously identified peak x(i), y(i)
|
|
for xyt=xy
|
|
% fit a polynomial to the local neighbourhood
|
|
try
|
|
|
|
x = xyt(1); y = xyt(2);
|
|
|
|
|
|
% now try to interpolate the peak over a 3x3 window
|
|
|
|
zc = z(x, y);
|
|
zn = z(x, y-1);
|
|
zs = z(x, y+1);
|
|
ze = z(x+1, y);
|
|
zw = z(x-1, y);
|
|
|
|
dx = (ze - zw)/(2*(2*zc - ze - zw));
|
|
dy = (zn - zs)/(2*(zn - 2*zc + zs));
|
|
|
|
zest = zc - (ze - zw)^2/(8*(ze - 2*zc + zw)) - (zn - zs)^2/(8*(zn - 2*zc + zs));
|
|
|
|
aest = min(abs([ze/2 - zc + zw/2, zn/2 - zc + zs/2]));
|
|
|
|
|
|
catch
|
|
% handle situation where neighbourhood falls off the data
|
|
% vector
|
|
warning('Peak at %f too close to edge of image, skipping', x(i));
|
|
continue;
|
|
end
|
|
%
|
|
|
|
% store x, y for the refined peak
|
|
xyp = [xyp [x+dx; y+dy]];
|
|
zp = [zp zest];
|
|
ap = [ap aest];
|
|
|
|
end
|
|
else
|
|
% no interpolation case
|
|
xyp = xy;
|
|
zp = z(k)';
|
|
ap = [];
|
|
|
|
end
|
|
|
|
|
|
% return values
|
|
if nargout > 1
|
|
xypout = xyp;
|
|
end
|
|
if nargout > 2
|
|
aout = ap;
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|