From d131e7a991e05a02e1724b29b5ed82c346b75f59 Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Thu, 30 May 2024 12:41:21 +0200 Subject: [PATCH] Merge pull request #3743 from vrabaud:thinning Misc thinning fixes. #3743 - edges could be modified - 2 sets of iterations were always done even if the first set did not return any change - countNonZero is slow compared to hasNonZero ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. --- modules/ximgproc/src/thinning.cpp | 11 +++++++++-- modules/ximgproc/test/test_thinning.cpp | 17 +++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/modules/ximgproc/src/thinning.cpp b/modules/ximgproc/src/thinning.cpp index 00017fe0a..76e8ad154 100644 --- a/modules/ximgproc/src/thinning.cpp +++ b/modules/ximgproc/src/thinning.cpp @@ -96,6 +96,10 @@ static void thinningIteration(Mat img, int iter, int thinningType){ Mat marker = Mat::zeros(img.size(), CV_8UC1); int rows = img.rows; int cols = img.cols; + marker.col(0).setTo(1); + marker.col(cols - 1).setTo(1); + marker.row(0).setTo(1); + marker.row(rows - 1).setTo(1); if(thinningType == THINNING_ZHANGSUEN){ marker.forEach([=](uchar& value, const int postion[]) { @@ -133,6 +137,7 @@ static void thinningIteration(Mat img, int iter, int thinningType){ //int m1 = iter == 0 ? (p2 * p4 * p6) : (p2 * p4 * p8); //int m2 = iter == 0 ? (p4 * p6 * p8) : (p2 * p6 * p8); //if (A == 1 && (B >= 2 && B <= 6) && m1 == 0 && m2 == 0) value = 0; + // else value = 1; }); } if(thinningType == THINNING_GUOHALL){ @@ -170,6 +175,7 @@ static void thinningIteration(Mat img, int iter, int thinningType){ //int N = N1 < N2 ? N1 : N2; //int m = iter == 0 ? ((p6 | p7 | (!p9)) & p8) : ((p2 | p3 | (!p5)) & p4); //if ((C == 1) && ((N >= 2) && ((N <= 3)) & (m == 0))) value = 0; + // else value = 1; }); } @@ -183,16 +189,17 @@ void thinning(InputArray input, OutputArray output, int thinningType){ // Enforce the range of the input image to be in between 0 - 255 processed /= 255; - Mat prev = Mat::zeros(processed.size(), CV_8UC1); + Mat prev = processed.clone(); Mat diff; do { thinningIteration(processed, 0, thinningType); thinningIteration(processed, 1, thinningType); absdiff(processed, prev, diff); + if (!hasNonZero(diff)) break; processed.copyTo(prev); } - while (countNonZero(diff) > 0); + while (true); processed *= 255; diff --git a/modules/ximgproc/test/test_thinning.cpp b/modules/ximgproc/test/test_thinning.cpp index 733fe85d4..7d5c5ac48 100644 --- a/modules/ximgproc/test/test_thinning.cpp +++ b/modules/ximgproc/test/test_thinning.cpp @@ -6,9 +6,12 @@ namespace opencv_test { namespace { -static int createTestImage(Mat& src) +static int createTestImage(Mat1b& src) { - src = Mat::zeros(Size(256, 256), CV_8UC1); + src = Mat1b::zeros(Size(256, 256)); + // Create a corner point that should not be affected. + src(0, 0) = 255; + for (int x = 50; x < src.cols - 50; x += 50) { cv::circle(src, Point(x, x/2), 30 + x/2, Scalar(255), 5); @@ -20,13 +23,14 @@ static int createTestImage(Mat& src) TEST(ximgproc_Thinning, simple_ZHANGSUEN) { - Mat src; + Mat1b src; int src_pixels = createTestImage(src); - Mat dst; + Mat1b dst; thinning(src, dst, THINNING_ZHANGSUEN); int dst_pixels = countNonZero(dst); EXPECT_LE(dst_pixels, src_pixels); + EXPECT_EQ(dst(0, 0), 255); #if 0 imshow("src", src); imshow("dst", dst); waitKey(); @@ -35,13 +39,14 @@ TEST(ximgproc_Thinning, simple_ZHANGSUEN) TEST(ximgproc_Thinning, simple_GUOHALL) { - Mat src; + Mat1b src; int src_pixels = createTestImage(src); - Mat dst; + Mat1b dst; thinning(src, dst, THINNING_GUOHALL); int dst_pixels = countNonZero(dst); EXPECT_LE(dst_pixels, src_pixels); + EXPECT_EQ(dst(0, 0), 255); #if 0 imshow("src", src); imshow("dst", dst); waitKey();