@@ -5,65 +5,175 @@ using namespace std;
55namespace cv {
66namespace ximgproc {
77
8+ // look up table - there is one entry for each of the 2^8=256 possible
9+ // combinations of 8 binary neighbors.
10+ static uint8_t lut_zhang_iter0[] = {
11+ 1 , 1 , 1 , 0 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 1 ,
12+ 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 ,
13+ 0 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
14+ 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
15+ 0 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
16+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
17+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 ,
18+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
19+ 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 0 , 1 ,
20+ 1 , 1 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 ,
21+ 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
22+ 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
23+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
24+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 1 , 0 ,
25+ 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 ,
26+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
27+ 0 , 0 , 1 , 0 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 ,
28+ 1 , 1 , 0 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
29+ 1 , 1 , 1 , 1 };
30+
31+ static uint8_t lut_zhang_iter1[] = {
32+ 1 , 1 , 1 , 0 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 1 ,
33+ 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 ,
34+ 0 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
35+ 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
36+ 0 , 1 , 1 , 1 , 0 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 ,
37+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
38+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 ,
39+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
40+ 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 0 , 1 ,
41+ 0 , 1 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 ,
42+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
43+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
44+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
45+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 1 , 0 ,
46+ 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
47+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
48+ 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
49+ 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 1 , 1 ,
50+ 0 , 1 , 1 , 1 };
51+
52+ static uint8_t lut_guo_iter0[] = {
53+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 0 , 1 , 1 ,
54+ 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 ,
55+ 0 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 ,
56+ 0 , 0 , 0 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
57+ 0 , 1 , 0 , 0 , 0 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 ,
58+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
59+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
60+ 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 1 ,
61+ 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 1 , 0 , 1 ,
62+ 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 0 ,
63+ 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
64+ 1 , 0 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
65+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
66+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
67+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
68+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
69+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
70+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
71+ 1 , 1 , 1 , 1 };
72+
73+ static uint8_t lut_guo_iter1[] = {
74+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 ,
75+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
76+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
77+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
78+ 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
79+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
80+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
81+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
82+ 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 ,
83+ 1 , 1 , 1 , 1 , 0 , 0 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 ,
84+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
85+ 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 ,
86+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 ,
87+ 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 ,
88+ 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
89+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
90+ 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 ,
91+ 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 1 , 1 ,
92+ 1 , 1 , 1 , 1 };
93+
894// Applies a thinning iteration to a binary image
995static void thinningIteration (Mat img, int iter, int thinningType){
1096 Mat marker = Mat::zeros (img.size (), CV_8UC1);
97+ int rows = img.rows ;
98+ int cols = img.cols ;
1199
12100 if (thinningType == THINNING_ZHANGSUEN){
13- for (int i = 1 ; i < img.rows -1 ; i++)
14- {
15- for (int j = 1 ; j < img.cols -1 ; j++)
16- {
17- uchar p2 = img.at <uchar>(i-1 , j);
18- uchar p3 = img.at <uchar>(i-1 , j+1 );
19- uchar p4 = img.at <uchar>(i, j+1 );
20- uchar p5 = img.at <uchar>(i+1 , j+1 );
21- uchar p6 = img.at <uchar>(i+1 , j);
22- uchar p7 = img.at <uchar>(i+1 , j-1 );
23- uchar p8 = img.at <uchar>(i, j-1 );
24- uchar p9 = img.at <uchar>(i-1 , j-1 );
25-
26- int A = (p2 == 0 && p3 == 1 ) + (p3 == 0 && p4 == 1 ) +
27- (p4 == 0 && p5 == 1 ) + (p5 == 0 && p6 == 1 ) +
28- (p6 == 0 && p7 == 1 ) + (p7 == 0 && p8 == 1 ) +
29- (p8 == 0 && p9 == 1 ) + (p9 == 0 && p2 == 1 );
30- int B = p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9;
31- int m1 = iter == 0 ? (p2 * p4 * p6) : (p2 * p4 * p8);
32- int m2 = iter == 0 ? (p4 * p6 * p8) : (p2 * p6 * p8);
33-
34- if (A == 1 && (B >= 2 && B <= 6 ) && m1 == 0 && m2 == 0 )
35- marker.at <uchar>(i,j) = 1 ;
36- }
37- }
101+ marker.forEach <uchar>([=](uchar& value, const int postion[]) {
102+ int i = postion[0 ];
103+ int j = postion[1 ];
104+ if (i == 0 || j == 0 || i == rows - 1 || j == cols - 1 )
105+ return ;
106+
107+ auto ptr = img.ptr (i, j); // p1
108+
109+ // p9 p2 p3
110+ // p8 p1 p4
111+ // p7 p6 p5
112+ uchar p2 = ptr[-cols];
113+ uchar p3 = ptr[-cols + 1 ];
114+ uchar p4 = ptr[1 ];
115+ uchar p5 = ptr[cols + 1 ];
116+ uchar p6 = ptr[cols];
117+ uchar p7 = ptr[cols - 1 ];
118+ uchar p8 = ptr[-1 ];
119+ uchar p9 = ptr[-cols - 1 ];
120+
121+ int neighbors = p9 | (p2 << 1 ) | (p3 << 2 ) | (p4 << 3 ) | (p5 << 4 ) | (p6 << 5 ) | (p7 << 6 ) | (p8 << 7 );
122+
123+ if (iter == 0 )
124+ value = lut_zhang_iter0[neighbors];
125+ else
126+ value = lut_zhang_iter1[neighbors];
127+
128+ // int A = (p2 == 0 && p3 == 1) + (p3 == 0 && p4 == 1) +
129+ // (p4 == 0 && p5 == 1) + (p5 == 0 && p6 == 1) +
130+ // (p6 == 0 && p7 == 1) + (p7 == 0 && p8 == 1) +
131+ // (p8 == 0 && p9 == 1) + (p9 == 0 && p2 == 1);
132+ // int B = p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9;
133+ // int m1 = iter == 0 ? (p2 * p4 * p6) : (p2 * p4 * p8);
134+ // int m2 = iter == 0 ? (p4 * p6 * p8) : (p2 * p6 * p8);
135+ // if (A == 1 && (B >= 2 && B <= 6) && m1 == 0 && m2 == 0) value = 0;
136+ });
38137 }
39138 if (thinningType == THINNING_GUOHALL){
40- for (int i = 1 ; i < img.rows -1 ; i++)
41- {
42- for (int j = 1 ; j < img.cols -1 ; j++)
43- {
44- uchar p2 = img.at <uchar>(i-1 , j);
45- uchar p3 = img.at <uchar>(i-1 , j+1 );
46- uchar p4 = img.at <uchar>(i, j+1 );
47- uchar p5 = img.at <uchar>(i+1 , j+1 );
48- uchar p6 = img.at <uchar>(i+1 , j);
49- uchar p7 = img.at <uchar>(i+1 , j-1 );
50- uchar p8 = img.at <uchar>(i, j-1 );
51- uchar p9 = img.at <uchar>(i-1 , j-1 );
52-
53- int C = ((!p2) & (p3 | p4)) + ((!p4) & (p5 | p6)) +
54- ((!p6) & (p7 | p8)) + ((!p8) & (p9 | p2));
55- int N1 = (p9 | p2) + (p3 | p4) + (p5 | p6) + (p7 | p8);
56- int N2 = (p2 | p3) + (p4 | p5) + (p6 | p7) + (p8 | p9);
57- int N = N1 < N2 ? N1 : N2;
58- int m = iter == 0 ? ((p6 | p7 | (!p9)) & p8) : ((p2 | p3 | (!p5)) & p4);
59-
60- if ((C == 1 ) && ((N >= 2 ) && ((N <= 3 )) & (m == 0 )))
61- marker.at <uchar>(i,j) = 1 ;
62- }
63- }
139+ marker.forEach <uchar>([=](uchar& value, const int postion[]) {
140+ int i = postion[0 ];
141+ int j = postion[1 ];
142+ if (i == 0 || j == 0 || i == rows - 1 || j == cols - 1 )
143+ return ;
144+
145+ auto ptr = img.ptr (i, j); // p1
146+
147+ // p9 p2 p3
148+ // p8 p1 p4
149+ // p7 p6 p5
150+ uchar p2 = ptr[-cols];
151+ uchar p3 = ptr[-cols + 1 ];
152+ uchar p4 = ptr[1 ];
153+ uchar p5 = ptr[cols + 1 ];
154+ uchar p6 = ptr[cols];
155+ uchar p7 = ptr[cols - 1 ];
156+ uchar p8 = ptr[-1 ];
157+ uchar p9 = ptr[-cols - 1 ];
158+
159+ int neighbors = p9 | (p2 << 1 ) | (p3 << 2 ) | (p4 << 3 ) | (p5 << 4 ) | (p6 << 5 ) | (p7 << 6 ) | (p8 << 7 );
160+
161+ if (iter == 0 )
162+ value = lut_guo_iter0[neighbors];
163+ else
164+ value = lut_guo_iter1[neighbors];
165+
166+ // int C = ((!p2) & (p3 | p4)) + ((!p4) & (p5 | p6)) +
167+ // ((!p6) & (p7 | p8)) + ((!p8) & (p9 | p2));
168+ // int N1 = (p9 | p2) + (p3 | p4) + (p5 | p6) + (p7 | p8);
169+ // int N2 = (p2 | p3) + (p4 | p5) + (p6 | p7) + (p8 | p9);
170+ // int N = N1 < N2 ? N1 : N2;
171+ // int m = iter == 0 ? ((p6 | p7 | (!p9)) & p8) : ((p2 | p3 | (!p5)) & p4);
172+ // if ((C == 1) && ((N >= 2) && ((N <= 3)) & (m == 0))) value = 0;
173+ });
64174 }
65175
66- img &= ~ marker;
176+ img &= marker;
67177}
68178
69179// Apply the thinning procedure to a given image
0 commit comments