www.pudn.com > lianma.rar > boundaries.m, change:2004-12-16,size:5776b


function B = boundaries(BW, conn, dir) 
%BOUNDARIES Trace object boundaries.   
%   B = BOUNDARIES(BW) traces the exterior boundaries of objects in 
%   the binary image BW.  B is a P-by-1 cell array, where P is the 
%   number of objects in the image. Each cell contains a Q-by-2 
%   matrix, each row of which contains the row and column coordinates 
%   of a boundary pixel.  Q is the number of boundary pixels for the 
%   corresponding object.  Object boundaries are traced in the 
%   clockwise direction. 
% 
%   B = BOUNDARIES(BW, CONN) specifies the connectivity to use when 
%   tracing boundaries.  CONN may be either 8 or 4.  The default 
%   value for CONN is 8. 
% 
%   B = BOUNDARIES(BW, CONN, DIR) specifies the direction used for 
%   tracing boundaries.  DIR should be either 'cw' (trace boundaries 
%   clockwise) or 'ccw' (trace boundaries counterclockwise).  If DIR 
%   is omitted BOUNDARIES traces in the clockwise direction. 
 
%   Copyright 2002-2004 R. C. Gonzalez, R. E. Woods, & S. L. Eddins 
%   Digital Image Processing Using MATLAB, Prentice-Hall, 2004 
%   $Revision: 1.6 $  $Date: 2003/11/21 14:22:07 $ 
 
if nargin < 3 
   dir = 'cw'; 
end 
 
if nargin < 2 
   conn = 8; 
end 
 
L = bwlabel(BW, conn); 
 
% The number of objects is the maximum value of L.  Initialize the 
% cell array B so that each cell initially contains a 0-by-2 matrix. 
numObjects = max(L(:)); 
if numObjects > 0 
   B = {zeros(0, 2)}; 
   B = repmat(B, numObjects, 1); 
else 
   B = {}; 
end 
 
% Pad label matrix with zeros.  This lets us write the 
% boundary-following loop without worrying about going off the edge 
% of the image.  
Lp = padarray(L, [1 1], 0, 'both'); 
 
% Compute the linear indexing offsets to take us from a pixel to its 
% neighbors.   
M = size(Lp, 1); 
if conn == 8 
   % Order is N NE E SE S SW W NW. 
   offsets = [-1, M - 1, M, M + 1, 1, -M + 1, -M, -M-1]; 
else 
   % Order is N E S W. 
   offsets = [-1, M, 1, -M]; 
end 
 
% next_search_direction_lut is a lookup table.  Given the direction 
% from pixel k to pixel k+1, what is the direction to start with when 
% examining the neighborhood of pixel k+1? 
if conn == 8 
   next_search_direction_lut = [8 8 2 2 4 4 6 6]; 
else 
   next_search_direction_lut = [4 1 2 3]; 
end 
 
% next_direction_lut is a lookup table.  Given that we just looked at 
% neighbor in a given direction, which neighbor do we look at next?  
if conn == 8 
   next_direction_lut = [2 3 4 5 6 7 8 1]; 
else 
   next_direction_lut = [2 3 4 1]; 
end 
 
% Values used for marking the starting and boundary pixels. 
START    = -1; 
BOUNDARY = -2; 
 
% Initialize scratch space in which to record the boundary pixels as 
% well as follow the boundary. 
scratch = zeros(100, 1); 
 
% Find candidate starting locations for boundaries. 
[rr, cc] = find((Lp(2:end-1, :) > 0) & (Lp(1:end-2, :) == 0)); 
rr = rr + 1; 
 
for k = 1:length(rr) 
   r = rr(k); 
   c = cc(k); 
   if (Lp(r,c) > 0) & (Lp(r - 1, c) == 0) & isempty(B{Lp(r, c)}) 
      % We've found the start of the next boundary.  Compute its 
      % linear offset, record which boundary it is, mark it, and 
      % initialize the counter for the number of boundary pixels. 
      idx = (c-1)*size(Lp, 1) + r; 
      which = Lp(idx); 
       
      scratch(1) = idx; 
      Lp(idx) = START; 
      numPixels = 1; 
      currentPixel = idx; 
      initial_departure_direction = []; 
       
      done = 0; 
      next_search_direction = 2; 
      while ~done 
         % Find the next boundary pixel. 
         direction = next_search_direction; 
         found_next_pixel = 0; 
         for k = 1:length(offsets) 
            neighbor = currentPixel + offsets(direction); 
            if Lp(neighbor) ~= 0 
               % Found the next boundary pixel. 
                
               if (Lp(currentPixel) == START) & ... 
                      isempty(initial_departure_direction) 
                  % We are making the initial departure from 
                  % the starting pixel. 
                  initial_departure_direction = direction; 
                   
               elseif (Lp(currentPixel) == START) & ... 
                      (initial_departure_direction == direction) 
                  % We are about to retrace our path. 
                  % That means we're done. 
                  done = 1; 
                  found_next_pixel = 1; 
                  break; 
               end 
                
               % Take the next step along the boundary. 
               next_search_direction = ... 
                   next_search_direction_lut(direction); 
               found_next_pixel = 1; 
               numPixels = numPixels + 1; 
               if numPixels > size(scratch, 1) 
                  % Double the scratch space. 
                  scratch(2*size(scratch, 1)) = 0; 
               end 
               scratch(numPixels) = neighbor; 
                
               if Lp(neighbor) ~= START 
                  Lp(neighbor) = BOUNDARY; 
               end 
                
               currentPixel = neighbor; 
               break; 
            end 
             
            direction = next_direction_lut(direction); 
         end 
          
         if ~found_next_pixel 
            % If there is no next neighbor, the object must just 
            % have a single pixel. 
            numPixels = 2; 
            scratch(2) = scratch(1); 
            done = 1; 
         end 
      end 
       
      % Convert linear indices to row-column coordinates and save 
      % in the output cell array.  
      [row, col] = ind2sub(size(Lp), scratch(1:numPixels)); 
      B{which} = [row - 1, col - 1]; 
   end 
end 
 
if strcmp(dir, 'ccw') 
   for k = 1:length(B) 
      B{k} = B{k}(end:-1:1, :); 
   end 
end