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

function c = fchcode(b, conn, dir) %FCHCODE Computes the Freeman chain code of a boundary. % C = FCHCODE(B) computes the 8-connected Freeman chain code of a % set of 2-D coordinate pairs contained in B, an np-by-2 array. C % is a structure with the following fields: % % c.fcc = Freeman chain code (1-by-np) % c.diff = First difference of code c.fcc (1-by-np) % c.mm = Integer of minimum magnitude from c.fcc (1-by-np) % c.diffmm = First difference of code c.mm (1-by-np) % c.x0y0 = Coordinates where the code starts (1-by-2) % % C = FCHCODE(B, CONN) produces the same outputs as above, but % with the code connectivity specified in CONN. CONN can be 8 for % an 8-connected chain code, or CONN can be 4 for a 4-connected % chain code. Specifying CONN=4 is valid only if the input % sequence, B, contains transitions with values 0, 2, 4, and 6, % exclusively. % % C = FHCODE(B, CONN, DIR) produces the same outputs as above, but, % in addition, the desired code direction is specified. Values for % DIR can be: % % 'same' Same as the order of the sequence of points in b. % This is the default. % % 'reverse' Outputs the code in the direction opposite to the % direction of the points in B. The starting point % for each DIR is the same. % % The elements of B are assumed to correspond to a 1-pixel-thick, % fully-connected, closed boundary. B cannot contain duplicate % coordinate pairs, except in the first and last positions, which % is a common feature of boundary tracing programs. % % FREEMAN CHAIN CODE REPRESENTATION % The table on the left shows the 8-connected Freeman chain codes % corresponding to allowed deltax, deltay pairs. An 8-chain is % converted to a 4-chain if (1) if conn = 4; and (2) only % transitions 0, 2, 4, and 6 occur in the 8-code. Note that % dividing 0, 2, 4, and 6 by 2 produce the 4-code. % % ----------------------- ---------------- % deltax | deltay | 8-code corresp 4-code % ----------------------- ---------------- % 0 1 0 0 % -1 1 1 % -1 0 2 1 % -1 -1 3 % 0 -1 4 2 % 1 -1 5 % 1 0 6 3 % 1 1 7 % ----------------------- ---------------- % % The formula z = 4*(deltax + 2) + (deltay + 2) gives the following % sequence corresponding to rows 1-8 in the preceding table: z = % 11,7,6,5,9,13,14,15. These values can be used as indices into the % table, improving the speed of computing the chain code. The % preceding formula is not unique, but it is based on the smallest % integers (4 and 2) that are powers of 2. % 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:34:49 $ % Preliminaries. if nargin == 1 dir = 'same'; conn = 8; elseif nargin == 2 dir = 'same'; elseif nargin == 3 % Nothing to do here. else error('Incorrect number of inputs.') end [np, nc] = size(b); if np < nc error('B must be of size np-by-2.'); end % Some boundary tracing programs, such as boundaries.m, output a % sequence in which the coordinates of the first and last points are % the same. If this is the case, eliminate the last point. if isequal(b(1, :), b(np, :)) np = np - 1; b = b(1:np, :); end % Build the code table using the single indices from the formula % for z given above: C(11)=0; C(7)=1; C(6)=2; C(5)=3; C(9)=4; C(13)=5; C(14)=6; C(15)=7; % End of Preliminaries. % Begin processing. x0 = b(1, 1); y0 = b(1, 2); c.x0y0 = [x0, y0]; % Make sure the coordinates are organized sequentially: % Get the deltax and deltay between successive points in b. The % last row of a is the first row of b. a = circshift(b, [-1, 0]); % DEL = a - b is an nr-by-2 matrix in which the rows contain the % deltax and deltay between successive points in b. The two % components in the kth row of matrix DEL are deltax and deltay % between point (xk, yk) and (xk+1, yk+1). The last row of DEL % contains the deltax and deltay between (xnr, ynr) and (x1, y1), % (i.e., between the last and first points in b). DEL = a - b; % If the abs value of either (or both) components of a pair % (deltax, deltay) is greater than 1, then by definition the curve % is broken (or the points are out of order), and the program % terminates. if any(abs(DEL(:, 1)) > 1) | any(abs(DEL(:, 2)) > 1); error('The input curve is broken or points are out of order.') end % Create a single index vector using the formula described above. z = 4*(DEL(:, 1) + 2) + (DEL(:, 2) + 2); % Use the index to map into the table. The following are % the Freeman 8-chain codes, organized in a 1-by-np array. fcc = C(z); % Check if direction of code sequence needs to be reversed. if strcmp(dir, 'reverse') fcc = coderev(fcc); % See below for function coderev. end % If 4-connectivity is specified, check that all components % of fcc are 0, 2, 4, or 6. if conn == 4 val = find(fcc == 1 | fcc == 3 | fcc == 5 | fcc ==7 ); if isempty(val) fcc = fcc./2; else warning('The specified 4-connected code cannot be satisfied.') end end % Freeman chain code for structure output. c.fcc = fcc; % Obtain the first difference of fcc. c.diff = codediff(fcc,conn); % See below for function codediff. % Obtain code of the integer of minimum magnitude. c.mm = minmag(fcc); % See below for function minmag. % Obtain the first difference of fcc c.diffmm = codediff(c.mm, conn); %-------------------------------------------------------------------% function cr = coderev(fcc) % Traverses the sequence of 8-connected Freeman chain code fcc in % the opposite direction, changing the values of each code % segment. The starting point is not changed. fcc is a 1-by-np % array. % Flip the array left to right. This redefines the starting point % as the last point and reverses the order of "travel" through the % code. cr = fliplr(fcc); % Next, obtain the new code values by traversing the code in the % opposite direction. (0 becomes 4, 1 becomes 5, ... , 5 becomes 1, % 6 becomes 2, and 7 becomes 3). ind1 = find(0 <= cr & cr <= 3); ind2 = find(4 <= cr & cr <= 7); cr(ind1) = cr(ind1) + 4; cr(ind2) = cr(ind2) - 4; %-------------------------------------------------------------------% function z = minmag(c) %MINMAG Finds the integer of minimum magnitude in a chain code. % Z = MINMAG(C) finds the integer of minimum magnitude in a given % 4- or 8-connected Freeman chain code, C. The code is assumed to % be a 1-by-np array. % The integer of minimum magnitude starts with min(c), but there % may be more than one such value. Find them all, I = find(c == min(c)); % and shift each one left so that it starts with min(c). J = 0; A = zeros(length(I), length(c)); for k = I; J = J + 1; A(J, :) = circshift(c,[0 -(k-1)]); end % Matrix A contains all the possible candidates for the integer of % minimum magnitude. Starting with the 2nd column, succesively find % the minima in each column of A. The number of candidates decreases % as the seach moves to the right on A. This is reflected in the % elements of J. When length(J)=1, one candidate remains. This is % the integer of minimum magnitude. [M, N] = size(A); J = (1:M)'; for k = 2:N D(1:M, 1) = Inf; D(J, 1) = A(J, k); amin = min(A(J, k)); J = find(D(:, 1) == amin); if length(J)==1 z = A(J, :); return end end %-------------------------------------------------------------------% function d = codediff(fcc, conn) %CODEDIFF Computes the first difference of a chain code. % D = CODEDIFF(FCC) computes the first difference of code, FCC. The % code FCC is treated as a circular sequence, so the last element % of D is the difference between the last and first elements of % FCC. The input code is a 1-by-np vector. % % The first difference is found by counting the number of direction % changes (in a counter-clockwise direction) that separate two % adjacent elements of the code. sr = circshift(fcc, [0, -1]); % Shift input left by 1 location. delta = sr - fcc; d = delta; I = find(delta < 0); type = conn; switch type case 4 % Code is 4-connected d(I) = d(I) + 4; case 8 % Code is 8-connected d(I) = d(I) + 8; end