@@ -5,65 +5,175 @@ using namespace std;
5
5
namespace cv {
6
6
namespace ximgproc {
7
7
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
+
8
94
// Applies a thinning iteration to a binary image
9
95
static void thinningIteration (Mat img, int iter, int thinningType){
10
96
Mat marker = Mat::zeros (img.size (), CV_8UC1);
97
+ int rows = img.rows ;
98
+ int cols = img.cols ;
11
99
12
100
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
+ });
38
137
}
39
138
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
+ });
64
174
}
65
175
66
- img &= ~ marker;
176
+ img &= marker;
67
177
}
68
178
69
179
// Apply the thinning procedure to a given image
0 commit comments