>その順番がどのように決定されているのか⇒ハフ変換行列(下のグラフ)の「ピーク値が大きい順」です
「ピーク値が大きい順」を具体的に言うと「画像内のエッジがより長く直線的に並んだ箇所の順番」です
オプション「NHoodSize — 抑制する近傍のサイズ」が設けられています。このサイズを大きくすれば、ピーク値近傍すなわち似た様なエッジを何本も選択してしまう事を避けられますが、逆に必要なエッジを見逃してしまう可能性も出てきます。
I = im2gray(imread('gantrycrane.png')); BW = edge(I,'canny');
[H,T,R] = hough(BW,'RhoResolution',0.5,'Theta',-90:0.5:89);
imshow(imadjust(rescale(H)),'XData',T,'YData',R,'InitialMagnification','fit');
title('Hough transform of gantrycrane.png');
xlabel('\theta'), ylabel('\rho'); axis on, axis normal, hold on; colormap(gca,hot);
type houghpeaks
function peaks = houghpeaks(varargin)
%HOUGHPEAKS Identify peaks in Hough transform.
% PEAKS = HOUGHPEAKS(H,NUMPEAKS) locates peaks in the Hough
% transform matrix, H, generated by the HOUGH function. NUMPEAKS
% specifies the maximum number of peaks to identify. PEAKS is
% a Q-by-2 matrix, where Q can range from 0 to NUMPEAKS. Q holds
% the row and column coordinates of the peaks. If NUMPEAKS is
% omitted, it defaults to 1.
%
% PEAKS = HOUGHPEAKS(...,PARAM1,VAL1,PARAM2,VAL2) sets various
% parameters. Parameter names can be abbreviated, and case
% does not matter. Each string parameter is followed by a value
% as indicated below:
%
% 'Threshold' Nonnegative scalar.
% Values of H below 'Threshold' will not be considered
% to be peaks. Threshold can vary from 0 to Inf.
%
% Default: 0.5*max(H(:))
%
% 'NHoodSize' Two-element vector of positive odd integers: [M N].
% 'NHoodSize' specifies the size of the suppression
% neighborhood. This is the neighborhood around each
% peak that is set to zero after the peak is identified.
%
% Default: smallest odd values greater than or equal to
% size(H)/50.
%
% 'Theta' Vector of Hough transform theta values returned by HOUGH.
% Each element of the vector specifies the theta value for
% the corresponding column of the output matrix H.
%
% Default: -90:89
%
% Class Support
% -------------
% H is the output of the HOUGH function. NUMPEAKS is a positive
% integer scalar.
%
% Note
% ----
% The 'Theta' values specified are used for peak suppression. If you
% specify the 'Theta' parameter as input to the hough function, you must
% specify the 'Theta' parameter with the houghpeaks function. Use the
% theta output value from the hough function as the theta input value for
% houghpeaks. Otherwise, peak suppression can result in unexpected
% results.
%
% References
% ----------
% Rafael C. Gonzalez, Richard E. Woods, Steven L. Eddins, "Digital
% Image Processing Using MATLAB", Prentice Hall, 2004
%
% Example
% -------
% % Locate and display two peaks in the Hough transform of the
% % rotated circuit.tif image.
%
% I = imread('circuit.tif');
% BW = edge(imrotate(I,50,'crop'),'canny');
% [H,T,R] = hough(BW);
% P = houghpeaks(H,2);
% imshow(H,[],'XData',T,'YData',R,'InitialMagnification','fit');
% xlabel('\theta'), ylabel('\rho');
% axis on, axis normal, hold on;
% plot(T(P(:,2)),R(P(:,1)),'s','color','white');
%
% See also HOUGH, HOUGHLINES.
% Copyright 1993-2018 The MathWorks, Inc.
[h, numpeaks, threshold, nhood, theta] = parseInputs(varargin{:});
% initialize the loop variables
done = false;
hnew = h;
nhood_center = (nhood-1)/2;
peaks = [];
minTheta = min(theta);
maxTheta = max(theta);
thetaResolution = abs(maxTheta - minTheta) / (numel(theta)-1);
isThetaAntisymmetric = abs(minTheta+thetaResolution*nhood(2)) <= maxTheta;
while ~done
[dummy max_idx] = max(hnew(:)); %#ok
[p, q] = ind2sub(size(hnew), max_idx);
p = p(1); q = q(1);
if hnew(p, q) >= threshold
peaks = [peaks; [p q]]; %#ok<AGROW> % add the peak to the list
% Suppress this maximum and its close neighbors.
p1 = p - nhood_center(1);
p2 = p + nhood_center(1);
q1 = q - nhood_center(2);
q2 = q + nhood_center(2);
% Throw away neighbor coordinates that are out of bounds in
% the rho direction.
[qq, pp] = meshgrid(q1:q2, max(p1,1):min(p2,size(h,1)));
pp = pp(:);
qq = qq(:);
if isThetaAntisymmetric
% For coordinates that are out of bounds in the theta
% direction, we want to consider that H is antisymmetric
% along the rho axis for theta = +/- 90 degrees.
theta_too_low = find(qq < 1);
qq(theta_too_low) = size(h, 2) + qq(theta_too_low);
pp(theta_too_low) = size(h, 1) - pp(theta_too_low) + 1;
theta_too_high = find(qq > size(h, 2));
qq(theta_too_high) = qq(theta_too_high) - size(h, 2);
pp(theta_too_high) = size(h, 1) - pp(theta_too_high) + 1;
end
any_theta_too_low = ~isempty(find(qq < 1, 1));
any_theta_too_high = ~isempty(find(qq > size(h, 2), 1));
if any_theta_too_low || any_theta_too_high
% Remove coordinates that are out of bounds in the theta
% direction.
theta_too_low = find(qq < 1);
qq(theta_too_low) = [];
pp(theta_too_low) = [];
theta_too_high = find(qq > size(h, 2));
qq(theta_too_high) = [];
pp(theta_too_high) = [];
end
% Convert to linear indices to zero out all the values.
hnew(sub2ind(size(hnew), pp, qq)) = 0;
done = size(peaks,1) == numpeaks;
else
done = true;
end
end
%-----------------------------------------------------------------------------
function [h, numpeaks, threshold, nhood, theta] = parseInputs(varargin)
narginchk(1,8);
h = varargin{1};
validateattributes(h, {'double'}, {'real', '2d', 'nonsparse', 'nonempty',...
'finite', 'integer'}, ...
mfilename, 'H', 1);
numpeaks = 1; % set default value for numpeaks
idx = 2;
if nargin > 1
if ~ischar(varargin{2})
numpeaks = varargin{2};
validateattributes(numpeaks, {'double'}, {'real', 'scalar', 'integer', ...
'positive', 'nonempty'}, mfilename, 'NUMPEAKS', 2);
idx = 3;
end
end
% Initialize to empty
nhood = [];
threshold = [];
theta = [];
% Process parameter-value pairs
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
validStrings = {'Threshold','NHoodSize','Theta'};
if nargin > idx-1 % we have parameter/value pairs
done = false;
while ~done
input = varargin{idx};
inputStr = validatestring(input, validStrings,mfilename,'PARAM',idx);
idx = idx+1; %advance index to point to the VAL portion of the input
if idx > nargin
error(message('images:houghpeaks:valForhoughpeaksMissing', inputStr))
end
switch inputStr
case 'Threshold'
threshold = varargin{idx};
validateattributes(threshold, {'double'}, {'real', 'scalar','nonnan' ...
'nonnegative'}, mfilename, inputStr, idx);
case 'NHoodSize'
nhood = varargin{idx};
validateattributes(nhood, {'double'}, {'real', 'vector', ...
'finite','integer','positive','odd'},...
mfilename, inputStr, idx);
if (any(size(nhood) ~= [1,2]))
error(message('images:houghpeaks:invalidNHoodSize', inputStr))
end
if (any(nhood > size(h)))
error(message('images:houghpeaks:tooBigNHoodSize', inputStr))
end
case 'Theta'
theta = varargin{idx};
validateattributes(theta, {'double'}, {'nonempty', 'real',...
'vector','finite'}, mfilename, inputStr, idx);
if (min(theta) < -90)
error(message('images:houghpeaks:invalidThetaMin', inputStr))
end
if (max(theta) >= 90)
error(message('images:houghpeaks:invalidThetaMax', inputStr))
end
% Theta vector must be evenly spaced.
thetaInterval = diff(theta);
if abs(sum(diff(thetaInterval))) > sqrt(eps)
error(message('images:houghpeaks:invalidThetaVectorSpacing'))
end
otherwise
%should never get here
error(message('images:houghpeaks:internalError'))
end
if idx >= nargin
done = true;
end
idx=idx+1;
end
end
% Set the defaults if necessary
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if isempty(nhood)
nhood = size(h)/50;
nhood = max(2*ceil(nhood/2) + 1, 1); % Make sure the nhood size is odd.
end
if isempty(threshold)
threshold = 0.5 * max(h(:));
end
if isempty(theta)
theta = -90:89;
end