@@ -92,94 +92,35 @@ static uint8_t lut_guo_iter1[] = {
9292 1 , 1 , 1 , 1 };
9393
9494// Applies a thinning iteration to a binary image
95- static void thinningIteration (Mat img, int iter, int thinningType){
96- Mat marker = Mat::zeros (img.size (), CV_8UC1);
95+ static void thinningIteration (Mat &img, Mat &marker, const uint8_t * const lut) {
9796 int rows = img.rows ;
9897 int cols = img.cols ;
9998 marker.col (0 ).setTo (1 );
10099 marker.col (cols - 1 ).setTo (1 );
101100 marker.row (0 ).setTo (1 );
102101 marker.row (rows - 1 ).setTo (1 );
103102
104- if (thinningType == THINNING_ZHANGSUEN){
105- marker.forEach <uchar>([=](uchar& value, const int postion[]) {
106- int i = postion[0 ];
107- int j = postion[1 ];
108- if (i == 0 || j == 0 || i == rows - 1 || j == cols - 1 )
109- return ;
110-
111- auto ptr = img.ptr (i, j); // p1
112-
113- // p9 p2 p3
114- // p8 p1 p4
115- // p7 p6 p5
116- uchar p2 = ptr[-cols];
117- uchar p3 = ptr[-cols + 1 ];
118- uchar p4 = ptr[1 ];
119- uchar p5 = ptr[cols + 1 ];
120- uchar p6 = ptr[cols];
121- uchar p7 = ptr[cols - 1 ];
122- uchar p8 = ptr[-1 ];
123- uchar p9 = ptr[-cols - 1 ];
124-
125- int neighbors = p9 | (p2 << 1 ) | (p3 << 2 ) | (p4 << 3 ) | (p5 << 4 ) | (p6 << 5 ) | (p7 << 6 ) | (p8 << 7 );
126-
127- if (iter == 0 )
128- value = lut_zhang_iter0[neighbors];
129- else
130- value = lut_zhang_iter1[neighbors];
131-
132- // int A = (p2 == 0 && p3 == 1) + (p3 == 0 && p4 == 1) +
133- // (p4 == 0 && p5 == 1) + (p5 == 0 && p6 == 1) +
134- // (p6 == 0 && p7 == 1) + (p7 == 0 && p8 == 1) +
135- // (p8 == 0 && p9 == 1) + (p9 == 0 && p2 == 1);
136- // int B = p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9;
137- // int m1 = iter == 0 ? (p2 * p4 * p6) : (p2 * p4 * p8);
138- // int m2 = iter == 0 ? (p4 * p6 * p8) : (p2 * p6 * p8);
139- // if (A == 1 && (B >= 2 && B <= 6) && m1 == 0 && m2 == 0) value = 0;
140- // else value = 1;
141- });
142- }
143- if (thinningType == THINNING_GUOHALL){
144- marker.forEach <uchar>([=](uchar& value, const int postion[]) {
145- int i = postion[0 ];
146- int j = postion[1 ];
147- if (i == 0 || j == 0 || i == rows - 1 || j == cols - 1 )
148- return ;
149-
150- auto ptr = img.ptr (i, j); // p1
151-
152- // p9 p2 p3
153- // p8 p1 p4
154- // p7 p6 p5
155- uchar p2 = ptr[-cols];
156- uchar p3 = ptr[-cols + 1 ];
157- uchar p4 = ptr[1 ];
158- uchar p5 = ptr[cols + 1 ];
159- uchar p6 = ptr[cols];
160- uchar p7 = ptr[cols - 1 ];
161- uchar p8 = ptr[-1 ];
162- uchar p9 = ptr[-cols - 1 ];
163-
164- int neighbors = p9 | (p2 << 1 ) | (p3 << 2 ) | (p4 << 3 ) | (p5 << 4 ) | (p6 << 5 ) | (p7 << 6 ) | (p8 << 7 );
165-
166- if (iter == 0 )
167- value = lut_guo_iter0[neighbors];
168- else
169- value = lut_guo_iter1[neighbors];
170-
171- // int C = ((!p2) & (p3 | p4)) + ((!p4) & (p5 | p6)) +
172- // ((!p6) & (p7 | p8)) + ((!p8) & (p9 | p2));
173- // int N1 = (p9 | p2) + (p3 | p4) + (p5 | p6) + (p7 | p8);
174- // int N2 = (p2 | p3) + (p4 | p5) + (p6 | p7) + (p8 | p9);
175- // int N = N1 < N2 ? N1 : N2;
176- // int m = iter == 0 ? ((p6 | p7 | (!p9)) & p8) : ((p2 | p3 | (!p5)) & p4);
177- // if ((C == 1) && ((N >= 2) && ((N <= 3)) & (m == 0))) value = 0;
178- // else value = 1;
179- });
180- }
103+ marker.forEach <uchar>([=](uchar& value, const int postion[]) {
104+ int i = postion[0 ];
105+ int j = postion[1 ];
106+ if (i == 0 || j == 0 || i == rows - 1 || j == cols - 1 ) { return ; }
107+
108+ auto ptr = img.ptr (i, j); // p1
109+ uchar p2 = ptr[-cols];
110+ uchar p3 = ptr[-cols + 1 ];
111+ uchar p4 = ptr[1 ];
112+ uchar p5 = ptr[cols + 1 ];
113+ uchar p6 = ptr[cols];
114+ uchar p7 = ptr[cols - 1 ];
115+ uchar p8 = ptr[-1 ];
116+ uchar p9 = ptr[-cols - 1 ];
117+
118+ int neighbors = p9 | (p2 << 1 ) | (p3 << 2 ) | (p4 << 3 ) | (p5 << 4 ) | (p6 << 5 ) | (p7 << 6 ) | (p8 << 7 );
119+ value = lut[neighbors];
120+ });
181121
182122 img &= marker;
123+ marker.setTo (0 );
183124}
184125
185126// Apply the thinning procedure to a given image
@@ -188,21 +129,19 @@ void thinning(InputArray input, OutputArray output, int thinningType){
188129 CV_CheckTypeEQ (processed.type (), CV_8UC1, " " );
189130 // Enforce the range of the input image to be in between 0 - 255
190131 processed /= 255 ;
191-
192132 Mat prev = processed.clone ();
193- Mat diff;
194-
133+ Mat marker = Mat::zeros (processed.size (), CV_8UC1);
134+ const auto lutIter0 = (thinningType == THINNING_GUOHALL) ? lut_guo_iter0 : lut_zhang_iter0;
135+ const auto lutIter1 = (thinningType == THINNING_GUOHALL) ? lut_guo_iter1 : lut_zhang_iter1;
195136 do {
196- thinningIteration (processed, 0 , thinningType );
197- thinningIteration (processed, 1 , thinningType );
198- absdiff (processed, prev, diff );
199- if (! hasNonZero (diff)) break ;
137+ thinningIteration (processed, marker, lutIter0 );
138+ thinningIteration (processed, marker, lutIter1 );
139+ const auto res = cv::norm (processed, prev, cv::NORM_L1 );
140+ if (res <= 0 ) { break ; }
200141 processed.copyTo (prev);
201- }
202- while (true );
142+ } while (true );
203143
204144 processed *= 255 ;
205-
206145 output.assign (processed);
207146}
208147
0 commit comments