www.gusucode.com > 图像识别,文字提取,边缘提取,二值化,设计模式识别,神经网络 > code6/chaincode/chaincode.m

    function [cc] = chaincode(b,unwrap)
%   Freeman Chain Code
%
%   Description: Give Freeman chain code 8-connected representation of a
%                boundary
%   Author.....: Alessandro Mannini <mannini@esod.it>
%   Date.......: 2010, september
%
%   usage:
%   --------------------------------------------------------
%   [cc] = chaincode(b,u)
%
%   INPUT:
%   --------------------------------------------------------
%   b       - boundary as np-by-2 array; 
%             np is the number of pixels and each element is a pair (y,x) of
%             pixel coordinates
%   unwrap  - (optional, default=false) unwrap code;
%             if enable phase inversions are eliminated
%            
%
%   OUTPUT:
%   --------------------------------------------------------
%   cc is structure with the following fields:
%
%   cc.code     - 8-connected Freeman chain code as 1-by-np array (or
%                 1-by-(np-1) if the boundary isn't close)
%   cc.x0,cc.y0 - respectively the abscissa and ordinate of start point
%   cc.ucode    - unwrapped 8-connected Freeman chain code (if required)
%

%
%
%   used direction-to-code convention is:       3  2  1
%                                                \ | /
%                                             4 -- P -- 0
%                                                / | \
%                                               5  6  7
%   
%   and in terms of deltax,deltay if next pixel compared to the current:
%   --------------------------
%   | deltax | deltay | code |
%   |------------------------|
%   |    0   |   +1   |   2  |
%   |    0   |   -1   |   6  |
%   |   -1   |   +1   |   3  |
%   |   -1   |   -1   |   5  |
%   |   +1   |   +1   |   1  |
%   |   +1   |   -1   |   7  |
%   |   -1   |    0   |   4  |
%   |   +1   |    0   |   0  |
%   --------------------------
%

% check input arguments
if nargin>2 
    error('Too many arguments');
elseif nargin==0
    error('Too few arguments');
elseif nargin==1
    unwrap=false;
end    
% compute dx,dy  by a circular shift on coords arrays by 1 element
sb=circshift(b,[-1 0]);
delta=sb-b;
% check if boundary is close, if not cut last element
if abs(delta(end,1))>1 || abs(delta(end,2))>1
    delta=delta(1:(end-1),:);
end
% check if boundary is 8-connected
n8c=find(abs(delta(:,1))>1 | abs(delta(:,2))>1);
if size(n8c,1)>0 
    s='';
    for i=1:size(n8c,1)
        s=[s sprintf(' idx -> %d \n',n8c(i))];
    end
    error('Curve isn''t 8-connected in elements: \n%s',s);
end


% convert dy,dx pairs to scalar indexes thinking to them (+1) as base-3 numbers
% according to: idx=3*(dy+1)+(dx+1)=3dy+dx+4 (adding 1 to have idx starting
% from 1)
% Then use a mapping array cm
%   --------------------------------------
%   | deltax | deltay | code | (base-3)+1 |
%   |-------------------------------------|
%   |    0   |   +1   |   2  |      8     | 
%   |    0   |   -1   |   6  |      2     | 
%   |   -1   |   +1   |   3  |      7     | 
%   |   -1   |   -1   |   5  |      1     | 
%   |   +1   |   +1   |   1  |      9     | 
%   |   +1   |   -1   |   7  |      3     | 
%   |   -1   |    0   |   4  |      4     |  
%   |   +1   |    0   |   0  |      6     | 
%   ---------------------------------------

idx=3*delta(:,1)+delta(:,2)+5;
cm([1 2 3 4 6 7 8 9])=[5 6 7 4 0 3 2 1];

% finally the chain code array and the starting point
cc.x0=b(1,2);
cc.y0=b(1,1);
cc.code=(cm(idx))';

% If unwrapping is required, use the following algorithm
%
% if a(k), k=1..n is the original code and u(k) the unwrapped:
%
% - u(1)=a(1)
% - u(k)=g(k), 
%        g(k) in Z | (g(k)-a(k)) mod 8=0 and |g(k)-u(k-1)| is minimized  
%
if (unwrap) 
    a=cc.code;
    u(1)=a(1);
    la=size(a,1);
    for i=2:la
        n=round((u(i-1)-a(i))/8);
        u(i)=a(i)+n*8;
    end
    cc.ucode=u';
end    

end