-
Notifications
You must be signed in to change notification settings - Fork 0
/
fchcode.m
155 lines (138 loc) · 5.39 KB
/
fchcode.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
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.
%
% 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);