9 CV_Assert(img.channels() == 1);
10 CV_Assert(img.depth() !=
sizeof(uchar));
11 CV_Assert(img.rows > 3 && img.cols > 3);
13 cv::Mat marker = cv::Mat::zeros(img.size(), CV_8UC1);
18 if(img.isContinuous())
36 pCurr = img.ptr<uchar>(0);
37 pBelow = img.ptr<uchar>(1);
39 for(y = 1; y < img.rows - 1; ++y)
44 pBelow = img.ptr<uchar>(y + 1);
46 pDst = marker.ptr<uchar>(y);
56 for(x = 1; x < img.cols - 1; ++x)
61 ne = &(pAbove[x + 1]);
67 se = &(pBelow[x + 1]);
69 int A = (*no == 0 && *ne == 1) + (*ne == 0 && *ea == 1) +
70 (*ea == 0 && *se == 1) + (*se == 0 && *so == 1) +
71 (*so == 0 && *sw == 1) + (*sw == 0 && *we == 1) +
72 (*we == 0 && *nw == 1) + (*nw == 0 && *no == 1);
73 int B = *no + *ne + *ea + *se + *so + *sw + *we + *nw;
74 int m1 = iter == 0 ? (*no * *ea * *so) : (*no * *ea * *we);
75 int m2 = iter == 0 ? (*ea * *so * *we) : (*no * *so * *we);
77 if(A == 1 && (B >= 2 && B <= 6) && m1 == 0 && m2 == 0)
90 cv::Mat prev = cv::Mat::zeros(dst.size(), CV_8UC1);
97 cv::absdiff(dst, prev, diff);
100 while(cv::countNonZero(diff) > 0);
114 for(
int i = 1; i < dst.rows - 1; i++)
116 for(
int j = 1; j < dst.cols - 1; j++)
118 float pAct = src.at<float_t>(i, j);
121 if(pAct > 0 && i > 0 && i < src.rows - 1 && j > 0 && j < src.cols - 1)
126 src.at<float_t>(i, j - 1),
127 src.at<float_t>(i - 1, j - 1),
128 src.at<float_t>(i - 1, j),
129 src.at<float_t>(i - 1, j + 1),
130 src.at<float_t>(i, j + 1),
131 src.at<float_t>(i + 1, j + 1),
132 src.at<float_t>(i + 1, j),
133 src.at<float_t>(i + 1, j - 1)
136 bool bigger[8] = {p[0] > pAct, p[1] > pAct, p[2] > pAct, p[3] > pAct, p[4] > pAct, p[5] > pAct, p[6] > pAct, p[7] > pAct};
137 bool smaller[8] = {p[0] < pAct, p[1] < pAct, p[2] < pAct, p[3] < pAct, p[4] < pAct, p[5] < pAct, p[6] < pAct, p[7] < pAct};
143 if(bigger[4] && bigger[0] && !bigger[2] && !bigger[6])
149 q.push(
Index(i, j, pAct));
150 dst.at<int8_t>(i, j) = initCosts;
152 else if(!bigger[4] && !bigger[0] && bigger[2] && bigger[6])
158 q.push(
Index(i, j, pAct));
159 dst.at<int8_t>(i, j) = initCosts;
161 else if(bigger[1] && bigger[5] && !(bigger[2] && bigger[3] && bigger[4]) && !(bigger[0] && bigger[7] && bigger[6]))
167 q.push(
Index(i, j, pAct));
168 dst.at<int8_t>(i, j) = initCosts;
170 else if(bigger[3] && bigger[7] && !(bigger[2] && bigger[1] && bigger[0]) && !(bigger[4] && bigger[5] && bigger[6]))
176 q.push(
Index(i, j, pAct));
177 dst.at<int8_t>(i, j) = initCosts;
186 else if(!bigger[0] && !bigger[1] && !bigger[2] && bigger[3] && !bigger[4] && bigger[6])
188 q.push(
Index(i, j, pAct));
189 dst.at<int8_t>(i, j) = initCosts;
191 else if(!bigger[0] && bigger[1] && !bigger[2] && !bigger[3] && !bigger[4] && bigger[6])
193 q.push(
Index(i, j, pAct));
194 dst.at<int8_t>(i, j) = initCosts;
197 else if(!bigger[0] && bigger[2] && !bigger[4] && bigger[5] && !bigger[6] && !bigger[7])
199 q.push(
Index(i, j, pAct));
200 dst.at<int8_t>(i, j) = initCosts;
202 else if(!bigger[0] && bigger[2] && !bigger[4] && !bigger[5] && !bigger[6] && bigger[7])
204 q.push(
Index(i, j, pAct));
205 dst.at<int8_t>(i, j) = initCosts;
208 else if(!bigger[0] && bigger[1] && !bigger[2] && bigger[4] && !bigger[6] && !bigger[7])
210 q.push(
Index(i, j, pAct));
211 dst.at<int8_t>(i, j) = initCosts;
213 else if(!bigger[0] && !bigger[1] && !bigger[2] && bigger[4] && !bigger[6] && bigger[7])
215 q.push(
Index(i, j, pAct));
216 dst.at<int8_t>(i, j) = initCosts;
219 else if(bigger[0] && !bigger[2] && bigger[3] && !bigger[4] && !bigger[5] && !bigger[6])
221 q.push(
Index(i, j, pAct));
222 dst.at<int8_t>(i, j) = initCosts;
224 else if(bigger[0] && !bigger[2] && !bigger[3] && !bigger[4] && bigger[5] && !bigger[6])
226 q.push(
Index(i, j, pAct));
227 dst.at<int8_t>(i, j) = initCosts;
230 else if(!bigger[0] && !bigger[1] && !bigger[2] && !bigger[3] && !bigger[4] && !bigger[5] && !bigger[6] && !bigger[7])
232 dst.at<int8_t>(i, j) = initCosts;
233 q.push(
Index(i, j, pAct));
241 if(smaller[0] && smaller[1] && bigger[3] && smaller[5] && smaller[6] && smaller[7])
248 q.push(
Index(i, j, pAct));
249 dst.at<int8_t>(i, j) = initCosts;
251 else if(smaller[1] && smaller[2] && smaller[3] && smaller[4] && smaller[5] && bigger[7])
258 q.push(
Index(i, j, pAct));
259 dst.at<int8_t>(i, j) = initCosts;
261 else if(bigger[1] && smaller[3] && smaller[4] && smaller[5] && smaller[6] && smaller[7])
268 q.push(
Index(i, j, pAct));
269 dst.at<int8_t>(i, j) = initCosts;
271 else if(smaller[0] && smaller[1] && smaller[2] && smaller[3] && bigger[5] && smaller[7])
278 q.push(
Index(i, j, pAct));
279 dst.at<int8_t>(i, j) = initCosts;
285 if(pAct > 1 && i > 1 && j > 1 && i < src.rows - 2 && j < src.cols - 2)
289 if((!smaller[5] || !smaller[6] || !smaller[4]) && !bigger[7] && !bigger[3])
300 float pot = src.at<float_t>(m, n);
304 src.at<float_t>(m, n - 1),
305 src.at<float_t>(m - 1, n - 1),
306 src.at<float_t>(m - 1, n),
307 src.at<float_t>(m - 1, n + 1),
308 src.at<float_t>(m, n + 1),
309 src.at<float_t>(m + 1, n + 1),
310 src.at<float_t>(m + 1, n),
311 src.at<float_t>(m + 1, n - 1)
313 bool bigger2[8] = {pp2[0] > pot, pp2[1] > pot, pp2[2] > pot, pp2[3] > pot, pp2[4] > pot, pp2[5] > pot, pp2[6] > pot, pp2[7] > pot};
314 bool smaller2[8] = {pp2[0] < pot, pp2[1] < pot, pp2[2] < pot, pp2[3] < pot, pp2[4] < pot, pp2[5] < pot, pp2[6] < pot, pp2[7] < pot};
316 if((!smaller2[0] || !smaller2[1] || !smaller2[2]) && !bigger2[3] && !bigger2[7] && pot > 1)
318 q.push(
Index(i, j, pAct));
319 dst.at<int8_t>(i, j) = initCosts;
321 q.push(
Index(m, n, pAct));
322 dst.at<int8_t>(m, n) = initCosts;
326 if((!smaller[2] || !smaller[3] || !smaller[4]) && !bigger[1] && !bigger[5])
336 float pot = src.at<float_t>(m, n);
340 src.at<float_t>(m, n - 1),
341 src.at<float_t>(m - 1, n - 1),
342 src.at<float_t>(m - 1, n),
343 src.at<float_t>(m - 1, n + 1),
344 src.at<float_t>(m, n + 1),
345 src.at<float_t>(m + 1, n + 1),
346 src.at<float_t>(m + 1, n),
347 src.at<float_t>(m + 1, n - 1)
349 bool bigger2[8] = {pp2[0] > pot, pp2[1] > pot, pp2[2] > pot, pp2[3] > pot, pp2[4] > pot, pp2[5] > pot, pp2[6] > pot, pp2[7] > pot};
350 bool smaller2[8] = {pp2[0] < pot, pp2[1] < pot, pp2[2] < pot, pp2[3] < pot, pp2[4] < pot, pp2[5] < pot, pp2[6] < pot, pp2[7] < pot};
352 if((!smaller2[0] || !smaller2[7] || !smaller2[6]) && !bigger2[1] && !bigger2[5] && pot > 1)
354 q.push(
Index(i, j, pAct));
355 dst.at<int8_t>(i, j) = initCosts;
357 q.push(
Index(m, n, pAct));
358 dst.at<int8_t>(m, n) = initCosts;
362 if((!smaller[2] || !smaller[3] || !smaller[1]) && !bigger[0] && !bigger[4])
374 float pot = src.at<float_t>(m, n);
379 src.at<float_t>(m, n - 1),
380 src.at<float_t>(m - 1, n - 1),
381 src.at<float_t>(m - 1, n),
382 src.at<float_t>(m - 1, n + 1),
383 src.at<float_t>(m, n + 1),
384 src.at<float_t>(m + 1, n + 1),
385 src.at<float_t>(m + 1, n),
386 src.at<float_t>(m + 1, n - 1)
390 bool bigger2[8] = {pp2[0] > pot, pp2[1] > pot, pp2[2] > pot, pp2[3] > pot, pp2[4] > pot, pp2[5] > pot, pp2[6] > pot, pp2[7] > pot};
391 bool smaller2[8] = {pp2[0] < pot, pp2[1] < pot, pp2[2] < pot, pp2[3] < pot, pp2[4] < pot, pp2[5] < pot, pp2[6] < pot, pp2[7] < pot};
393 if((!smaller2[5] || !smaller2[6] || !smaller2[7]) && !bigger2[0] && !bigger2[4] && pot > 1)
395 q.push(
Index(i, j, pAct));
396 dst.at<int8_t>(i, j) = initCosts;
398 q.push(
Index(m, n, pAct));
399 dst.at<int8_t>(m, n) = initCosts;
403 if((!smaller[7] || !smaller[0] || !smaller[1]) && !bigger[2] && !bigger[6])
413 float pot = src.at<float_t>(m, n);
417 src.at<float_t>(m, n - 1),
418 src.at<float_t>(m - 1, n - 1),
419 src.at<float_t>(m - 1, n),
420 src.at<float_t>(m - 1, n + 1),
421 src.at<float_t>(m, n + 1),
422 src.at<float_t>(m + 1, n + 1),
423 src.at<float_t>(m + 1, n),
424 src.at<float_t>(m + 1, n - 1)
426 bool bigger2[8] = {pp2[0] > pot, pp2[1] > pot, pp2[2] > pot, pp2[3] > pot, pp2[4] > pot, pp2[5] > pot, pp2[6] > pot, pp2[7] > pot};
427 bool smaller2[8] = {pp2[0] < pot, pp2[1] < pot, pp2[2] < pot, pp2[3] < pot, pp2[4] < pot, pp2[5] < pot, pp2[6] < pot, pp2[7] < pot};
429 if((!smaller2[3] || !smaller2[4] || !smaller2[5]) && !bigger2[2] && !bigger2[6] && pot > 1)
431 q.push(
Index(i, j, pAct));
432 dst.at<int8_t>(i, j) = initCosts;
434 q.push(
Index(m, n, pAct));
435 dst.at<int8_t>(m, n) = initCosts;
446 Index pixel = q.front();
449 int costs = dst.at<uint8_t>(pixel.
i, pixel.
j);
452 if(next.i >= 0 && next.j >= 0 && dst.at<uint8_t>(next.i, next.j) == 0)
454 if(src.at<float_t>(next.i, next.j) > 0)
456 dst.at<uint8_t>(next.i, next.j) = costs + pathCosts;
466 if(i == 0 || i == src.rows - 1 || j == 0 || j == src.cols - 1)
467 return Index(-1, -1, -1);
469 int costs = dst.at<uint8_t>(i, j);
472 Index(i, j - 1, src.at<float_t>(i, j - 1)),
473 Index(i - 1, j - 1, src.at<float_t>(i - 1, j - 1)),
474 Index(i - 1, j, src.at<float_t>(i - 1, j)),
475 Index(i - 1, j + 1, src.at<float_t>(i - 1, j + 1)),
476 Index(i, j + 1, src.at<float_t>(i, j + 1)),
477 Index(i + 1, j + 1, src.at<float_t>(i + 1, j + 1)),
478 Index(i + 1, j, src.at<float_t>(i + 1, j)),
479 Index(i + 1, j - 1, src.at<float_t>(i + 1, j - 1))
484 for(
int i = 0; i < 8; i++)
488 int actCosts = dst.at<uint8_t>(p[i].i, p[i].j);
490 if(actCosts != costs)
void greyscale_thinning(const cv::Mat &src, cv::Mat &dst)
Function for finding the ridge of a distance graph.
Index getMaximumNeighbour(int i, int j, const cv::Mat &src, cv::Mat &dst)
function for finding the maximum Neighbour ignoring the last detected pixels
void sceletonize_iteration(cv::Mat &img, int iter)
Perform one thinning iteration.(Normally you wouldn't call this function directly from your code) ...
TFSIMD_FORCE_INLINE const tfScalar & y() const
void sceletonize(const cv::Mat &src, cv::Mat &dst)
Function for thinning the given binary image (Paper Zhang-Suen Thinning)
TFSIMD_FORCE_INLINE const tfScalar & x() const