《数字图像处理原理与实践(MATLAB版)》代码补遗一则

原书184页,我曾提到,MATLAB中图像处理工具箱提供的Hough直线检测的效果不是特别好,并推荐了一个我个人认为实现得更好的版本。但由于本人并非该代码之原作者,遂未将其收录于书中。近来有读者留言,希望可以获得这部分代码,所以我特将其发布到此博客上,供有需要的读者参考学习。


关于《数字图像处理原理与实践(MATLAB版)》一书代码发布的说明

http://blog.csdn.net/baimafujinji/article/details/40987807 


附全书代码链接


《数字图像处理原理与实践(MATLAB版)》一书之代码Part10(P416~430)

http://blog.csdn.net/baimafujinji/article/details/44856089

《数字图像处理原理与实践(MATLAB版)》一书之代码Part9(P431~438)

http://blog.csdn.net/baimafujinji/article/details/44815599

《数字图像处理原理与实践(MATLAB版)》一书之代码Part8   (P375~415)

 http://blog.csdn.net/baimafujinji/article/details/42110831

《数字图像处理原理与实践(MATLAB版)》一书之代码Part7   (P186~225)

http://blog.csdn.net/baimafujinji/article/details/42080713

《数字图像处理原理与实践(MATLAB版)》一书之代码Part6  (P281~374) 

http://blog.csdn.net/baimafujinji/article/details/41971057

《数字图像处理原理与实践(MATLAB版)》一书之代码Part5  (P225~280)

http://blog.csdn.net/baimafujinji/article/details/41970367

《数字图像处理原理与实践(MATLAB版)》一书之代码Part4  (P135~183)

http://blog.csdn.net/baimafujinji/article/details/41926571

《数字图像处理原理与实践(MATLAB版)》一书之代码Part3   (P81~135)

http://blog.csdn.net/baimafujinji/article/details/41598455

《数字图像处理原理与实践(MATLAB版)》一书之代码Part2     (P43~80)

http://blog.csdn.net/baimafujinji/article/details/41146381

《数字图像处理原理与实践(MATLAB版)》一书之代码Part1   (P1~42)

http://blog.csdn.net/baimafujinji/article/details/41117641




代码原作者为Tao Peng,请尊重原作者权利。

%  Author:  Tao Peng
%           Department of Mechanical Engineering
%           University of Maryland, College Park, Maryland 20742, USA
%           [email protected]
%  Version: alpha       Revision: Dec. 02, 2005


使用时可参考下面这两个例子。

 EXAMPLE #1:
rawimg = imread('TestHT_Chkbd1.bmp');
fltr4img = [1 2 3 2 1; 2 3 4 3 2; 3 4 6 4 3; 2 3 4 3 2; 1 2 3 2 1];
fltr4img = fltr4img / sum(fltr4img(:));
imgfltrd = filter2( fltr4img , rawimg );


[accum, axis_rho, axis_theta, lineprm, lineseg] = Hough_Grd(imgfltrd, 6, 0.02);

figure(1); imagesc(axis_theta*(180/pi), axis_rho, accum); axis xy;
xlabel('Theta (degree)'); ylabel('Pho (pixels)');
title('Accumulation Array from Hough Transform');
figure(2); imagesc(rawimg); colormap('gray'); axis image;
DrawLines_2Ends(lineseg);
title('Raw Image with Line Segments Detected');


%  EXAMPLE #2:
rawimg = imread('TestHT_Pentagon.png');
fltr4img = [1 1 1 1 1; 1 2 2 2 1; 1 2 4 2 1; 1 2 2 2 1; 1 1 1 1 1];
fltr4img = fltr4img / sum(fltr4img(:));
imgfltrd = filter2( fltr4img , rawimg );

[accum, axis_rho, axis_theta, lineprm, lineseg] =  Hough_Grd(imgfltrd, 8, 0.05);

figure(1); imagesc(axis_theta*(180/pi), axis_rho, accum); axis xy;
xlabel('Theta (degree)'); ylabel('Pho (pixels)');
title('Accumulation Array from Hough Transform');
figure(2); imagesc(imgfltrd); colormap('gray'); axis image;
DrawLines_Polar(size(imgfltrd), lineprm);

title('Raw Image (Blurred) with Lines Detected');
figure(3); imagesc(rawimg); colormap('gray'); axis image;
DrawLines_2Ends(lineseg);
title('Raw Image with Line Segments Detected');

function [accum, axis_rho, axis_theta, varargout] = ...
    Hough_Grd(img, varargin)
%Detect lines in a grayscale image
%
%  [accum, axis_rho, axis_theta, lineprm, lineseg, dbg_label] =
%      Hough_Grd(img, grdthres, detsens)
%  Hough transform for line detection based on image's gradient field.
%  NOTE:    Operates on grayscale images, NOT B/W bitmaps.
%           NO loops involved in the implementation of Hough transform,
%               which makes the operation fast.
%           Able to detect the two ends of line segments.
%
%  INPUT: (img, grdthres, detsens)
%  img:         A 2-D grayscale image (NO B/W bitmap)
%  grdthres:    (Optional, default is 8, must be non-negative)
%               The algorithm is based on the gradient field of the
%               input image. A thresholding on the gradient magnitude
%               is performed before the voting process of the Hough
%               transform to remove the 'uniform intensity' (sort-of)
%               image background from the voting process. In other words,
%               pixels with gradient magnitudes smaller than 'grdthres'
%               are considered not belong to any line.
%  detsens:     (Optional, default is 0.08)
%               A value that controls the sensitivity of line detection.
%               The range of the value is from 0 to 1, open ends.
%               Although the physical meaning of this parameter is not
%               obvious, it controls the algorithm in a fuzzy manner.
%               The SMALLER the value is, the MORE features in the image
%               will be considered as lines.
%
%  OUTPUT: [accum, axis_rho, axis_theta, lineprm, lineseg, dbg_label]
%  accum:       The result accumulation array from the Hough transform.
%               The horizontal dimension is 'theta' and the vertical
%               dimension is 'rho'.
%  axis_rho:    Vector that contains the 'rho' values for the rows in
%               the accumulation array.
%  axis_theta:  Vector that contains the 'theta' values for the columns
%               in the accumulation array.
%  lineprm:     (Optional)
%               Parameters (rho, theta) of the lines detected. Is a N-by-2
%               matrix with each row contains the parameters (rho, theta) 
%               for a line. The definitions of 'rho' and 'theta' are as
%               the following:
%               'rho' is the perpendicular distance from the line to the
%               origin of the image. 'rho' can be negative since 'theta'
%               is constrained to [0, pi]. The unit of 'rho' is in pixels.
%               'theta' is the sweep angle from axis X (i.e. horizontal
%               axis of the image) to the direction that is perpendicular
%               to the line. The range of 'theta' is [0, pi].
%  lineseg:     (Optional)
%               Parameters (x1, x2, y1, y2) of line segments detected.
%               Lines given by (rho, theta) are infinite lines. This
%               function tries to detect line segments in the raw image
%               and output them as 'lineseg', which is a Ns-by-4 matrix
%               with each row contains the parameters (x1, x2, y1, y2)
%               that defines the two ends of a line segment.
%  dbg_label:   (Optional, for debug purpose)
%               Labelled segmentation map from the search of peaks in
%               the accumulation array
%
%
%  BUG REPORT:
%  This is an alpha version. Please send your bug reports, comments and
%  suggestions to [email protected] . Thanks.

%  Reserved for extension
%  accumres: (Optional, default is [4, 1], minimum is [2, 0.5])
%               The desired resolutions in 'rho' and 'theta'. Is a
%               2-element vector in following format:
%               [resolution in 'rho' (pixels),
%               resolution in 'theta' (degrees)]




%%%%%%%% Arguments and parameters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


% Validation of arguments
if ndims(img) ~= 2 || ~isnumeric(img),
    error('Hough_Grd: ''img'' has to be 2 dimensional');
end
if ~all(size(img) >= 16),
    error('Hough_Grd: ''img'' has to be larger than 16-by-16');
end


% Parameters (default values)
prm_grdthres = 8;
prm_accumres = [4, 1];
prm_detsens = 0.08;


func_compu_lineprm = true;
prm_fltraccum = true;


% Validation of arguments
vap_grdthres = 1;
if nargin > vap_grdthres,
    if isnumeric(varargin{vap_grdthres}) && ...
            varargin{vap_grdthres}(1) >= 0,
        prm_grdthres = varargin{vap_grdthres}(1);
    else
        error(['Hough_Grd: ''grdthres'' has to be ', ...
            'a non-negative number']);
    end
end
%{
vap_accumres = 3;
if nargin > vap_accumres,
    if numel(varargin{vap_accumres}) == 2 && ...
            isnumeric(varargin{vap_accumres}) && ...
            ( varargin{vap_accumres}(1) >= 2 && ...
            varargin{vap_accumres}(2) >= 0.5 ),
        prm_accumres = varargin{vap_accumres};
    else
        error(['Hough_Grd: ''accumres'' has to be a two-element ', ...
            'vector and no smaller than [2, 0.5]']);
    end
end
%}
vap_detsens = 2;
if nargin > vap_detsens,
    if isnumeric(varargin{vap_detsens}) && ...
            varargin{vap_detsens}(1) > 0 && varargin{vap_detsens}(1) < 1,
        prm_detsens = varargin{vap_detsens};
    else
        error('Hough_Grd: ''detsens'' has to be in the range (0, 1)');
    end
end


func_compu_lineprm = ( nargout > 3 );


% Size of the accumulation array
imgsize = size(img);
coef_rhorng = [ -imgsize(2), sqrt(sum(imgsize.^2)) ];
coef_thetarng = [-pi/18, pi+pi/18];


prm_accumsize = [ ...
    round( (coef_rhorng(2)-coef_rhorng(1)) * (2/prm_accumres(1)) ) , ...
    round( (coef_thetarng(2)-coef_thetarng(1)) * (180/pi) * ...
    (2/prm_accumres(2)) ) ];


% Default filter for the accumulation array
prm_acmfltr_R = 4;
prm_acmfltr_w = [1 2 4 8];


fltr4accum = ones(2 * prm_acmfltr_R - 1) * prm_acmfltr_w(1);
for k = 2 : prm_acmfltr_R,
    fltr4accum(k:(2*prm_acmfltr_R-k), k:(2*prm_acmfltr_R-k)) = ...
        prm_acmfltr_w(k);
end
fltr4accum = fltr4accum / sum(fltr4accum(:));


% Parameters for the algorithm using repeated
% thresholding and segmentation
prm_lp_dthres = min([ 0.1, (0.1+prm_detsens)/2 ]);
prm_lp_maxthres = 0.8;


% Parameters for the algorithm using local maximum filter
prm_useaoi = false;
prm_aoiminsize = [8, 8];


prm_fltrLM_R = 4;
prm_fltrLM_s = 1.3;
prm_fltrLM_r = ceil( prm_fltrLM_R * 0.6 );
prm_fltrLM_npix = 6;


% Reserved parameters
dbg_on = false;      % debug information
dbg_bfigno = 5;
if nargout > 5,  dbg_on = true;  end




%%%%%%%% Building accumulation array %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


% Compute the gradient and the magnitude of gradient
img = double(img);
[grdx, grdy] = gradient(img);
grdmag = sqrt(grdx.^2 + grdy.^2);


% Clear the margins of the gradient field
prm_grdfldmgn = 4;
grdmag([1:prm_grdfldmgn, (end-prm_grdfldmgn+1):end], :) = 0;
grdmag(:, [1:prm_grdfldmgn, (end-prm_grdfldmgn+1):end]) = 0;


% Get the linear indices, as well as the subscripts, of the pixels
% whose gradient magnitudes are larger than the given threshold
grdmasklin = find(grdmag > prm_grdthres);
[grdmask_IdxI, grdmask_IdxJ] = ind2sub(imgsize, grdmasklin);


% Compute (the line parameter) 'theta' for all voting pixels
grdphs_vot = atan2( grdy(grdmasklin), grdx(grdmasklin) );


% -- Regulate 'grdphs_vot' from [-pi, pi] to [0, pi]
grdphs_vot = grdphs_vot + pi * (grdphs_vot < 0);


% Compute the 'theta'-subscript (to the accumulation array)
% for all voting pixels
coef_subtheta = prm_accumsize(2) / ...
    (coef_thetarng(2) - coef_thetarng(1)) * (1 - 1e-6);
sub_theta = ceil( (grdphs_vot - coef_thetarng(1)) * coef_subtheta );


% 'theta' vector for the accumulation array
axis_theta = (coef_thetarng(1) + 0.5 / coef_subtheta) : ...
    (1 / coef_subtheta) : coef_thetarng(2);


% Compute the 'rho' values for all voting pixels
% rho = (J - 0.5) * cos(theta) + (I - 0.5) * sin(theta)
rho_vot = (grdmask_IdxJ - 0.5) .* cos(grdphs_vot) + ...
    (grdmask_IdxI - 0.5) .* sin(grdphs_vot);


% Compute the 'rho'-subscript (to the accumulation array)
% for all voting pixels
coef_subrho = prm_accumsize(1) / ...
    (coef_rhorng(2) - coef_rhorng(1)) * (1 - 1e-6);
sub_rho = ceil( (rho_vot - coef_rhorng(1)) * coef_subrho );


% 'rho' vector for the accumulation array
axis_rho = (coef_rhorng(1) + 0.5 / coef_subrho) : ...
    (1 / coef_subrho) : coef_rhorng(2);


% Build the accumulation array, using gradient magnitude as weight
accum = accumarray( sub2ind(prm_accumsize, sub_rho, sub_theta), ...
    grdmag(grdmasklin) );
accum = [ accum ; ...
    zeros(prm_accumsize(1) * prm_accumsize(2) - numel(accum), 1) ];
accum = reshape( accum, prm_accumsize );




%%%%%%%% Locating peaks in the accumulation array %%%%%%%%%%%%%%%%%%%


% Stop if no need to estimate the parameters of the lines
if ~func_compu_lineprm,
    return;
end


% Smooth the accumulation array
if prm_fltraccum,
    accum = filter2( fltr4accum, accum );
end


% Find the maximum value in the accumulation array
accum_max = max(accum(:));




%------- Algorithm 1: Local maximum filter (begin) -------------
% Build the local maximum filter
fltr4LM = zeros(2 * prm_fltrLM_R + 1);


[mesh4fLM_x, mesh4fLM_y] = meshgrid(-prm_fltrLM_R : prm_fltrLM_R);
mesh4fLM_r = sqrt( mesh4fLM_x.^2 + mesh4fLM_y.^2 );
fltr4LM_mask = ...
( mesh4fLM_r > prm_fltrLM_r & mesh4fLM_r <= prm_fltrLM_R );
fltr4LM = fltr4LM - ...
fltr4LM_mask * (prm_fltrLM_s / sum(fltr4LM_mask(:)));


if prm_fltrLM_R >= 4,
fltr4LM_mask = ( mesh4fLM_r < (prm_fltrLM_r - 1) );
else
fltr4LM_mask = ( mesh4fLM_r < prm_fltrLM_r );
end
fltr4LM = fltr4LM + fltr4LM_mask / sum(fltr4LM_mask(:));


% Select a number of Areas-Of-Interest from the accumulation array
if prm_useaoi,
    % Thresholding and segmentation
    accummask = ( accum > (accum_max * prm_detsens) );
    [accumlabel, accum_nRgn] = bwlabel( accummask, 8 );


    % Select AOIs from segmented regions
    accumAOI = ones(0,4);
    for k = 1 : accum_nRgn,
        accumrgn_lin = find( accumlabel == k );
        [accumrgn_IdxI, accumrgn_IdxJ] = ...
            ind2sub( size(accumlabel), accumrgn_lin );
        rgn_top = min( accumrgn_IdxI );
        rgn_bottom = max( accumrgn_IdxI );
        rgn_left = min( accumrgn_IdxJ );
        rgn_right = max( accumrgn_IdxJ );        
        % The AOIs selected must satisfy a minimum size
        if ( (rgn_bottom - rgn_top + 1) >= prm_aoiminsize(1) || ...
                (rgn_right - rgn_left + 1) >= prm_aoiminsize(2) ),
            accumAOI = [ accumAOI; ...
                max([ 1, rgn_top - prm_fltrLM_R ]), ...
                min([ size(accum,1), rgn_bottom + prm_fltrLM_R ]), ...
                max([ 1, rgn_left - prm_fltrLM_R ]), ...
                min([ size(accum,2), rgn_right + prm_fltrLM_R ]) ];
        end
    end
else
    % Whole accumulation array as the one AOI
    accumAOI = [1, size(accum,1), 1, size(accum,2)];
end


% **** Debug code (begin)
if dbg_on && prm_useaoi,
    dbg_accumLM = zeros(size(accum));
end
% **** Debug code (end)


% For each of the AOIs selected, locate the local maxima
lineprm = zeros(0,2);
for k = 1 : size(accumAOI, 1),
    aoi = accumAOI(k,:);    % just for referencing convenience


    % Apply the local maxima filter
    candLM = conv2( accum(aoi(1):aoi(2), aoi(3):aoi(4)) , ...
        fltr4LM , 'same' );


% Thresholding of 'candLM' & 'accum'
    if prm_useaoi,
        candLM_mask = ( candLM > (max(candLM(:))*prm_detsens) & ...
            accummask(aoi(1):aoi(2),aoi(3):aoi(4)) );
    else
        candLM_mask = ( candLM > (max(candLM(:))*prm_detsens) & ...
            accum(aoi(1):aoi(2),aoi(3):aoi(4)) > (accum_max*prm_detsens) );
    end


    % Clear the margins of 'candLM_mask'
    candLM_mask([1:prm_fltrLM_R, (end-prm_fltrLM_R+1):end], :) = 0;
    candLM_mask(:, [1:prm_fltrLM_R, (end-prm_fltrLM_R+1):end]) = 0;


    % **** Debug code (begin)
    if dbg_on && prm_useaoi,
        dbg_accumLM(aoi(1):aoi(2), aoi(3):aoi(4)) = ...
            dbg_accumLM(aoi(1):aoi(2), aoi(3):aoi(4)) + candLM;
    end
    % **** Debug code (end)


    % Group the local maxima candidates by adjacency, compute the
    % centroid position for each group and take that as the center
    % of one circle detected
    [candLM_label, candLM_nRgn] = bwlabel( candLM_mask, 8 );


    for ilabel = 1 : candLM_nRgn,
        % Indices (to current AOI) of the pixels in the group
        candgrp_masklin = find( candLM_label == ilabel );
        [candgrp_IdxI, candgrp_IdxJ] = ...
            ind2sub( size(candLM_label) , candgrp_masklin );


        % Indices (to 'accum') of the pixels in the group
        candgrp_IdxI = candgrp_IdxI + ( aoi(1) - 1 );
        candgrp_IdxJ = candgrp_IdxJ + ( aoi(3) - 1 );
        candgrp_idx2acm = ...
            sub2ind( size(accum) , candgrp_IdxI , candgrp_IdxJ );


        % Minimum number of qulified pixels in the group
        if sum(numel(candgrp_masklin)) < prm_fltrLM_npix,
            continue;
        end


        % Compute the centroid position
        candgrp_acmsum = sum( accum(candgrp_idx2acm) );
        cc_rho = sum( candgrp_IdxI .* accum(candgrp_idx2acm) ) / ...
            candgrp_acmsum;
        cc_theta = sum( candgrp_IdxJ .* accum(candgrp_idx2acm) ) / ...
            candgrp_acmsum;
        lineprm = [lineprm; cc_rho, cc_theta];
    end
end


% **** Debug code (begin)
if dbg_on,
    figure(dbg_bfigno);
    if prm_useaoi,
        imagesc(dbg_accumLM); axis xy;
    else
        imagesc(candLM); axis xy;
    end
end
% **** Debug code (end)
%------- Algorithm 1: Local maximum filter (end) ---------------




%------- Algo 2: Repeated thresholding & segmentation (begin) --
%{
% Locate the peaks (in pixel coordinates) in the accumulation array
if dbg_on,
    [lineprm, dbg_label] = RecursSegment( accum , ...
        accum_max * [prm_detsens, prm_lp_dthres, prm_lp_maxthres] );
else
    lineprm = RecursSegment( accum , ...
        accum_max * [prm_detsens, prm_lp_dthres, prm_lp_maxthres] );
end


% **** Debug code (begin)
if dbg_on,
    figure(dbg_bfigno);
    imagesc(dbg_label); axis xy; axis equal;
    hold on;
    plot(lineprm(:,2), lineprm(:,1), ...
        'w+', 'LineWidth', 2, 'MarkerSize', 6);
    hold off;
end
% **** Debug code (end)
%}
%------- Algo 2: Repeated thresholding & segmentation (end) ----




% Convert 'lineprm' from pixel coordinates to (rho, theta)
lineprm = [ (lineprm(:,1) - 0.5)/coef_subrho + coef_rhorng(1), ...
(lineprm(:,2) - 0.5)/coef_subtheta + coef_thetarng(1) ];


% Output 'lineprm'
varargout{1} = lineprm;
if nargout <= 4,
    return;
end




%%%%%%%% Locating the line segments in the raw image %%%%%%%%%%%%%%%%


% Parameters for locating the line segments
prm_ls_tTol = [-pi/7.5, pi/7.5];
prm_ls_pTol = [-3.5, 3.5];
prm_ls_minlen = 10;


% Locate the two ends for all lines detected
rgnmask = logical(zeros(imgsize));
lineseg = zeros(0, 4);


for k = 1 : size(lineprm, 1),
    % Compute the 'rho' values for all pixels voted,
    % assuming they contribute to the current line
    rho2_vot = (grdmask_IdxJ - 0.5) * cos( lineprm(k,2) ) + ...
        (grdmask_IdxI - 0.5) .* sin( lineprm(k,2) );


    % Find the pixels that belong to the line
    PixOnLn_votmask = ( grdphs_vot > (lineprm(k,2) + prm_ls_tTol(1)) & ...
        grdphs_vot < (lineprm(k,2) + prm_ls_tTol(2)) & ...
        rho2_vot > (lineprm(k,1) + prm_ls_pTol(1)) & ...
        rho2_vot < (lineprm(k,1) + prm_ls_pTol(2)) );


PixOnLn_lin = grdmasklin( find(PixOnLn_votmask) );
    if isempty(PixOnLn_lin),
        continue;
    end
    [PixOnLn_IdxI, PixOnLn_IdxJ] = ind2sub(imgsize, PixOnLn_lin);


    % Find the axis-aligned bounding box for these pixels
    bndbox = [ min(PixOnLn_IdxI), max(PixOnLn_IdxI), ...
        min(PixOnLn_IdxJ), max(PixOnLn_IdxJ) ];


    % Seperate the line segments by adjacencies
    rgnmask( bndbox(1):bndbox(2), bndbox(3):bndbox(4) ) = 0;
    rgnmask( PixOnLn_lin ) = 1;
    [rgnlabel, nrgn] = bwlabel( ...
        rgnmask(bndbox(1):bndbox(2), bndbox(3):bndbox(4)), 8 );


    for k_rgn = 1 : nrgn,
        % Get the linear indices of pixels that belong to one segment
        seg_lin = find( rgnlabel == k_rgn );
        [seg_IdxI, seg_IdxJ] = ind2sub( size(rgnlabel), seg_lin );


        % Ignore if the line segment is too short
        segspan = [ min(seg_IdxI) + bndbox(1) - 1, ...
            max(seg_IdxI) + bndbox(1) - 1, ...
            min(seg_IdxJ) + bndbox(3) - 1, ...
            max(seg_IdxJ) + bndbox(3) - 1 ];
        if (segspan(2) - segspan(1) + 1) < prm_ls_minlen && ...
                (segspan(4) - segspan(3) + 1) < prm_ls_minlen,
            continue;
        end


        % Get the [x1 x2 y1 y2] structure for the line SEGMENT
        if lineprm(k,2) > pi/4 && lineprm(k,2) < 3*pi/4,
            % ls_base_x = 0;
            ls_base_y = lineprm(k,1) / sin(lineprm(k,2));
            lineseg = [ lineseg; segspan(3) - 0.5, segspan(4) - 0.5, ...
                ls_base_y - (segspan(3) - 0.5) / tan(lineprm(k,2)), ...
                ls_base_y - (segspan(4) - 0.5) / tan(lineprm(k,2)) ];
        else
            % ls_base_y = 0;
            ls_base_x = lineprm(k,1) / cos(lineprm(k,2));
            lineseg = [ lineseg; ...
                ls_base_x - (segspan(1) - 0.5) * tan(lineprm(k,2)), ...
                ls_base_x - (segspan(2) - 0.5) * tan(lineprm(k,2)), ...
                segspan(1) - 0.5, segspan(2) - 0.5 ];
        end
    end
end


% Output 'lineseg'
varargout{2} = lineseg;
if nargout > 5,
    varargout{3} = dbg_label;
end






%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%% Recursive thresholding and segmentation ********************


function [lineprm, varargout] = RecursSegment(accum, struct_thres)
% 'struct_thres' contains [thres, deltathres, maxthres]
% 'lineprm' is in pixel coordinate (w.r.t. 'accum')


% Parameters
prm_as_minpixn = 3;
prm_as_maxsize = [12, 12];


% Thresholding
accummask = ( accum > struct_thres(1) );


% Segmentation and locating the centroids of individual regions
[accumlabel, accum_nRgn] = bwlabel( accummask, 8 );


% Segmentation label (for debug purpose)
func_seglbl = ( nargout > 1 );
if func_seglbl,
    seglbl_lblshft = 4;
    seglabel = accumlabel;
end


lineprm = zeros(0, 2);
for k = 1 : accum_nRgn,
    % Linear indices of the pixels in one connected component
acmrgn_lin = find( accumlabel == k );
    if numel(acmrgn_lin) < prm_as_minpixn,
        continue;
    end
    % Subscripts of the pixels in one connected component
[acmrgn_IdxPho, acmrgn_IdxTheta] = ...
        ind2sub( size(accumlabel), acmrgn_lin );


% Further segmentation if the connected region is too big, or
    % computing the centroid of the region
    % -- Axis-aligned bounding box for the region
    bndbox = [ min(acmrgn_IdxPho), max(acmrgn_IdxPho), ...
        min(acmrgn_IdxTheta), max(acmrgn_IdxTheta) ];


    % -- Further segmentation
    bAddCentrdOfRgn = true;
if ( (bndbox(2) - bndbox(1) + 1) > prm_as_maxsize(1) || ...
            (bndbox(4) - bndbox(3) + 1) > prm_as_maxsize(2) ) && ...
            (struct_thres(1) + struct_thres(2)) <= struct_thres(3),
        if func_seglbl,
            [lineprm_sub, seglabel_sub] = RecursSegment( ...
                accum(bndbox(1):bndbox(2), bndbox(3):bndbox(4)), ...
                [struct_thres(1) + struct_thres(2), struct_thres(2:3)] );
            seglabel(bndbox(1):bndbox(2), bndbox(3):bndbox(4)) = ...
                seglabel(bndbox(1):bndbox(2), bndbox(3):bndbox(4)) + ...
                seglabel_sub + (seglabel_sub > 0) * seglbl_lblshft;
        else
            lineprm_sub = RecursSegment( ...
                accum(bndbox(1):bndbox(2), bndbox(3):bndbox(4)), ...
                [struct_thres(1) + struct_thres(2), struct_thres(2:3)] );
        end
        if ~isempty(lineprm_sub),
            lineprm = [lineprm; lineprm_sub(:,1) + bndbox(1) - 1, ...
                lineprm_sub(:,2) + bndbox(3) - 1 ];
            bAddCentrdOfRgn = false;
        end
    end


    % -- Computing the centroid of the whole region
    if bAddCentrdOfRgn,
        acmrgn_acmsum = sum( accum(acmrgn_lin) );
        lp_IdxPho = sum( acmrgn_IdxPho .* accum(acmrgn_lin) ) / ...
            acmrgn_acmsum;
    lp_IdxTheta = sum( acmrgn_IdxTheta .* accum(acmrgn_lin) ) / ...
            acmrgn_acmsum;
        lineprm = [ lineprm; lp_IdxPho, lp_IdxTheta ];
end
end


% Output the segmentation label
if func_seglbl,
    varargout{1} = seglabel;
end


function DrawLines_2Ends(lineseg, varargin)

hold on;
for k = 1 : size(lineseg, 1),
    % The image origin defined in function '[...] = Hough_Grd(...)' is
    % different from what is defined in Matlab, off by (0.5, 0.5).
    if nargin > 1,
        plot(lineseg(k,1:2)+0.5, lineseg(k,3:4)+0.5, varargin{1});
    else
        plot(lineseg(k,1:2)+0.5, lineseg(k,3:4)+0.5, 'LineWidth', 2);
    end
end
hold off;


function DrawLines_Polar(imgsize, lineprm, varargin)

hold on;
line = zeros(2,2);
for k = 1 : size(lineprm, 1),
    if lineprm(k,2) > pi/4 && lineprm(k,2) < 3*pi/4,
        line(1,1) = 0;
        line(1,2) = lineprm(k,1) / sin(lineprm(k,2));
        line(2,1) = imgsize(2);
        line(2,2) = line(1,2) - line(2,1) / tan(lineprm(k,2));
    else
        line(1,2) = 0;
        line(1,1) = lineprm(k,1) / cos(lineprm(k,2));
        line(2,2) = imgsize(1);
        line(2,1) = line(1,1) - line(2,2) * tan(lineprm(k,2));
    end
    % The image origin defined in function '[...] = Hough_Grd(...)' is
    % different from what is defined in Matlab, off by (0.5, 0.5).
    line = line + 0.5;
    % Draw lines using 'plot'
    if nargin > 2,
        plot(line(:,1), line(:,2), varargin{1});
    else
        plot(line(:,1), line(:,2));
    end
end
hold off;

你可能感兴趣的:(代码,matlab,图像处理,信号处理)