From b385767c1c0c5a5221a05e87000c5d91b32b729f Mon Sep 17 00:00:00 2001 From: Suleyman TURKMEN Date: Sun, 24 Nov 2024 04:29:47 +0300 Subject: [PATCH] Update drawing.cpp and test_contours.cpp --- modules/imgproc/src/drawing.cpp | 124 ++++++++++++------------- modules/imgproc/src/precomp.hpp | 1 + modules/imgproc/test/test_contours.cpp | 51 ++++++++-- 3 files changed, 105 insertions(+), 71 deletions(-) diff --git a/modules/imgproc/src/drawing.cpp b/modules/imgproc/src/drawing.cpp index c6efd4f21a..7ba512f7f8 100644 --- a/modules/imgproc/src/drawing.cpp +++ b/modules/imgproc/src/drawing.cpp @@ -2477,21 +2477,70 @@ void cv::drawContours( InputOutputArray _image, InputArrayOfArrays _contours, CV_Assert(ncontours <= (size_t)std::numeric_limits::max()); if (lineType == cv::LINE_AA && _image.depth() != CV_8U) lineType = 8; - Mat image = _image.getMat(), hierarchy = _hierarchy.getMat(); + Mat image = _image.getMat(); + Mat_ hierarchy = _hierarchy.getMat(); - if (thickness >= 0) // contour lines + int i = 0, end = (int)ncontours; + if (contourIdx >= 0) { - double color_buf[4] {}; - scalarToRawData(color, color_buf, _image.type(), 0 ); - int i = 0, end = (int)ncontours; - if (contourIdx >= 0) + i = contourIdx; + end = i + 1; + } + std::vector indexesToFill; + if (hierarchy.empty() || maxLevel == 0) + { + indexesToFill.resize(end - i); + std::iota(indexesToFill.begin(), indexesToFill.end(), i); + } + else + { + std::stack indexes; + for (; i != end; ++i) { - i = contourIdx; - end = i + 1; + // either all from the top level or a single contour + if (hierarchy(i)[3] < 0 || contourIdx >= 0) + indexes.push(i); } - for (; i < end; ++i) + while (!indexes.empty()) + { + // get current element + const int cur = indexes.top(); + indexes.pop(); + + // check current element depth + int curLevel = -1; + int par = cur; + while (par >= 0) + { + par = hierarchy(par)[3]; // parent + ++curLevel; + } + if (curLevel <= maxLevel) + { + indexesToFill.push_back(cur); + } + + int next = hierarchy(cur)[2]; // first child + while (next > 0) + { + indexes.push(next); + next = hierarchy(next)[0]; // next sibling + } + } + } + std::vector contoursToFill; + contoursToFill.reserve(indexesToFill.size()); + for (const int& idx : indexesToFill) + contoursToFill.emplace_back(_contours.getMat(idx)); + + if (thickness < 0) + fillPoly(image, contoursToFill, color, lineType, 0, offset); + else + { + double color_buf[4]{}; + scalarToRawData(color, color_buf, _image.type(), 0); + for (const Mat& cnt : contoursToFill) { - Mat cnt = _contours.getMat(i); if (cnt.empty()) continue; const int npoints = cnt.checkVector(2, CV_32S); @@ -2505,61 +2554,6 @@ void cv::drawContours( InputOutputArray _image, InputArrayOfArrays _contours, } } } - else // filled polygons - { - int i = 0, end = (int)ncontours; - if (contourIdx >= 0) - { - i = contourIdx; - end = i + 1; - } - std::vector indexesToFill; - if (hierarchy.empty() || maxLevel == 0) - { - for (; i != end; ++i) - indexesToFill.push_back(i); - } - else - { - std::stack indexes; - for (; i != end; ++i) - { - // either all from the top level or a single contour - if (hierarchy.at(i)[3] < 0 || contourIdx >= 0) - indexes.push(i); - } - while (!indexes.empty()) - { - // get current element - const int cur = indexes.top(); - indexes.pop(); - - // check current element depth - int curLevel = -1; - int par = cur; - while (par >= 0) - { - par = hierarchy.at(par)[3]; // parent - ++curLevel; - } - if (curLevel <= maxLevel) - { - indexesToFill.push_back(cur); - } - - int next = hierarchy.at(cur)[2]; // first child - while (next > 0) - { - indexes.push(next); - next = hierarchy.at(next)[0]; // next sibling - } - } - } - std::vector contoursToFill; - for (const int & idx : indexesToFill) - contoursToFill.push_back(_contours.getMat(idx)); - fillPoly(image, contoursToFill, color, lineType, 0, offset); - } } diff --git a/modules/imgproc/src/precomp.hpp b/modules/imgproc/src/precomp.hpp index 33a921c78a..e0962fe0aa 100644 --- a/modules/imgproc/src/precomp.hpp +++ b/modules/imgproc/src/precomp.hpp @@ -62,6 +62,7 @@ #include #include #include +#include #define GET_OPTIMIZED(func) (func) diff --git a/modules/imgproc/test/test_contours.cpp b/modules/imgproc/test/test_contours.cpp index fbd3cabff8..5fb88dce32 100644 --- a/modules/imgproc/test/test_contours.cpp +++ b/modules/imgproc/test/test_contours.cpp @@ -446,9 +446,9 @@ static void d2xy(int n, int d, int *x, int *y) } } -TEST(Imgproc_FindContours, hilbert) +static Mat draw_hilbert(int n = 64, int scale = 10) { - int n = 64, n2 = n*n, scale = 10, w = (n + 2)*scale; + int n2 = n*n, w = (n + 2)*scale; Point ofs(scale, scale); Mat img(w, w, CV_8U); img.setTo(Scalar::all(0)); @@ -462,12 +462,19 @@ TEST(Imgproc_FindContours, hilbert) p = q; } dilate(img, img, Mat()); + return img; +} + +TEST(Imgproc_FindContours, hilbert) +{ + Mat img = draw_hilbert(); vector > contours; + + findContours(img, contours, noArray(), RETR_LIST, CHAIN_APPROX_NONE); + ASSERT_EQ(1, (int)contours.size()); + ASSERT_EQ(78632, (int)contours[0].size()); + findContours(img, contours, noArray(), RETR_LIST, CHAIN_APPROX_SIMPLE); - img.setTo(Scalar::all(0)); - - drawContours(img, contours, 0, Scalar::all(255), 1); - ASSERT_EQ(1, (int)contours.size()); ASSERT_EQ(9832, (int)contours[0].size()); } @@ -539,6 +546,38 @@ TEST(Imgproc_FindContours, regression_4363_shared_nbd) } } +TEST(Imgproc_DrawContours, regression_26264) +{ + Mat img = draw_hilbert(32); + img.push_back(~img); + + for (int i = 50; i < 200; i += 17) + { + rectangle(img, Rect(i, i, img.cols - (i*2), img.rows - (i*2)), Scalar(0), 7); + rectangle(img, Rect(i, i, img.cols - (i*2), img.rows - (i*2)), Scalar(255), 1); + } + + vector > contours; + vector hierarchy; + findContours(img, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE); + img.setTo(Scalar::all(0)); + Mat img1 = img.clone(); + Mat img2 = img.clone(); + Mat img3 = img.clone(); + + int idx = 0; + while (idx >= 0) + { + drawContours(img, contours, idx, Scalar::all(255), FILLED, LINE_8, hierarchy); + drawContours(img2, contours, idx, Scalar::all(255), 1, LINE_8, hierarchy); + idx = hierarchy[idx][0]; + } + + drawContours(img1, contours, -1, Scalar::all(255), FILLED, LINE_8, hierarchy); + drawContours(img3, contours, -1, Scalar::all(255), 1, LINE_8, hierarchy); + ASSERT_EQ(0, cvtest::norm(img, img1, NORM_INF)); + ASSERT_EQ(0, cvtest::norm(img2, img3, NORM_INF)); +} TEST(Imgproc_PointPolygonTest, regression_10222) {