Skip to content

Commit b385767

Browse files
committed
Update drawing.cpp and test_contours.cpp
1 parent 7be5181 commit b385767

File tree

3 files changed

+104
-70
lines changed

3 files changed

+104
-70
lines changed

modules/imgproc/src/drawing.cpp

Lines changed: 59 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2477,21 +2477,70 @@ void cv::drawContours( InputOutputArray _image, InputArrayOfArrays _contours,
24772477
CV_Assert(ncontours <= (size_t)std::numeric_limits<int>::max());
24782478
if (lineType == cv::LINE_AA && _image.depth() != CV_8U)
24792479
lineType = 8;
2480-
Mat image = _image.getMat(), hierarchy = _hierarchy.getMat();
2480+
Mat image = _image.getMat();
2481+
Mat_<Vec4i> hierarchy = _hierarchy.getMat();
24812482

2482-
if (thickness >= 0) // contour lines
2483+
int i = 0, end = (int)ncontours;
2484+
if (contourIdx >= 0)
24832485
{
2484-
double color_buf[4] {};
2485-
scalarToRawData(color, color_buf, _image.type(), 0 );
2486-
int i = 0, end = (int)ncontours;
2487-
if (contourIdx >= 0)
2486+
i = contourIdx;
2487+
end = i + 1;
2488+
}
2489+
std::vector<int> indexesToFill;
2490+
if (hierarchy.empty() || maxLevel == 0)
2491+
{
2492+
indexesToFill.resize(end - i);
2493+
std::iota(indexesToFill.begin(), indexesToFill.end(), i);
2494+
}
2495+
else
2496+
{
2497+
std::stack<int> indexes;
2498+
for (; i != end; ++i)
24882499
{
2489-
i = contourIdx;
2490-
end = i + 1;
2500+
// either all from the top level or a single contour
2501+
if (hierarchy(i)[3] < 0 || contourIdx >= 0)
2502+
indexes.push(i);
2503+
}
2504+
while (!indexes.empty())
2505+
{
2506+
// get current element
2507+
const int cur = indexes.top();
2508+
indexes.pop();
2509+
2510+
// check current element depth
2511+
int curLevel = -1;
2512+
int par = cur;
2513+
while (par >= 0)
2514+
{
2515+
par = hierarchy(par)[3]; // parent
2516+
++curLevel;
2517+
}
2518+
if (curLevel <= maxLevel)
2519+
{
2520+
indexesToFill.push_back(cur);
2521+
}
2522+
2523+
int next = hierarchy(cur)[2]; // first child
2524+
while (next > 0)
2525+
{
2526+
indexes.push(next);
2527+
next = hierarchy(next)[0]; // next sibling
2528+
}
24912529
}
2492-
for (; i < end; ++i)
2530+
}
2531+
std::vector<Mat> contoursToFill;
2532+
contoursToFill.reserve(indexesToFill.size());
2533+
for (const int& idx : indexesToFill)
2534+
contoursToFill.emplace_back(_contours.getMat(idx));
2535+
2536+
if (thickness < 0)
2537+
fillPoly(image, contoursToFill, color, lineType, 0, offset);
2538+
else
2539+
{
2540+
double color_buf[4]{};
2541+
scalarToRawData(color, color_buf, _image.type(), 0);
2542+
for (const Mat& cnt : contoursToFill)
24932543
{
2494-
Mat cnt = _contours.getMat(i);
24952544
if (cnt.empty())
24962545
continue;
24972546
const int npoints = cnt.checkVector(2, CV_32S);
@@ -2505,61 +2554,6 @@ void cv::drawContours( InputOutputArray _image, InputArrayOfArrays _contours,
25052554
}
25062555
}
25072556
}
2508-
else // filled polygons
2509-
{
2510-
int i = 0, end = (int)ncontours;
2511-
if (contourIdx >= 0)
2512-
{
2513-
i = contourIdx;
2514-
end = i + 1;
2515-
}
2516-
std::vector<int> indexesToFill;
2517-
if (hierarchy.empty() || maxLevel == 0)
2518-
{
2519-
for (; i != end; ++i)
2520-
indexesToFill.push_back(i);
2521-
}
2522-
else
2523-
{
2524-
std::stack<int> indexes;
2525-
for (; i != end; ++i)
2526-
{
2527-
// either all from the top level or a single contour
2528-
if (hierarchy.at<Vec4i>(i)[3] < 0 || contourIdx >= 0)
2529-
indexes.push(i);
2530-
}
2531-
while (!indexes.empty())
2532-
{
2533-
// get current element
2534-
const int cur = indexes.top();
2535-
indexes.pop();
2536-
2537-
// check current element depth
2538-
int curLevel = -1;
2539-
int par = cur;
2540-
while (par >= 0)
2541-
{
2542-
par = hierarchy.at<Vec4i>(par)[3]; // parent
2543-
++curLevel;
2544-
}
2545-
if (curLevel <= maxLevel)
2546-
{
2547-
indexesToFill.push_back(cur);
2548-
}
2549-
2550-
int next = hierarchy.at<Vec4i>(cur)[2]; // first child
2551-
while (next > 0)
2552-
{
2553-
indexes.push(next);
2554-
next = hierarchy.at<Vec4i>(next)[0]; // next sibling
2555-
}
2556-
}
2557-
}
2558-
std::vector<Mat> contoursToFill;
2559-
for (const int & idx : indexesToFill)
2560-
contoursToFill.push_back(_contours.getMat(idx));
2561-
fillPoly(image, contoursToFill, color, lineType, 0, offset);
2562-
}
25632557
}
25642558

25652559

modules/imgproc/src/precomp.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
#include <limits.h>
6363
#include <float.h>
6464
#include <stack>
65+
#include <numeric>
6566

6667
#define GET_OPTIMIZED(func) (func)
6768

modules/imgproc/test/test_contours.cpp

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -446,9 +446,9 @@ static void d2xy(int n, int d, int *x, int *y)
446446
}
447447
}
448448

449-
TEST(Imgproc_FindContours, hilbert)
449+
static Mat draw_hilbert(int n = 64, int scale = 10)
450450
{
451-
int n = 64, n2 = n*n, scale = 10, w = (n + 2)*scale;
451+
int n2 = n*n, w = (n + 2)*scale;
452452
Point ofs(scale, scale);
453453
Mat img(w, w, CV_8U);
454454
img.setTo(Scalar::all(0));
@@ -462,12 +462,19 @@ TEST(Imgproc_FindContours, hilbert)
462462
p = q;
463463
}
464464
dilate(img, img, Mat());
465+
return img;
466+
}
467+
468+
TEST(Imgproc_FindContours, hilbert)
469+
{
470+
Mat img = draw_hilbert();
465471
vector<vector<Point> > contours;
466-
findContours(img, contours, noArray(), RETR_LIST, CHAIN_APPROX_SIMPLE);
467-
img.setTo(Scalar::all(0));
468472

469-
drawContours(img, contours, 0, Scalar::all(255), 1);
473+
findContours(img, contours, noArray(), RETR_LIST, CHAIN_APPROX_NONE);
474+
ASSERT_EQ(1, (int)contours.size());
475+
ASSERT_EQ(78632, (int)contours[0].size());
470476

477+
findContours(img, contours, noArray(), RETR_LIST, CHAIN_APPROX_SIMPLE);
471478
ASSERT_EQ(1, (int)contours.size());
472479
ASSERT_EQ(9832, (int)contours[0].size());
473480
}
@@ -539,6 +546,38 @@ TEST(Imgproc_FindContours, regression_4363_shared_nbd)
539546
}
540547
}
541548

549+
TEST(Imgproc_DrawContours, regression_26264)
550+
{
551+
Mat img = draw_hilbert(32);
552+
img.push_back(~img);
553+
554+
for (int i = 50; i < 200; i += 17)
555+
{
556+
rectangle(img, Rect(i, i, img.cols - (i*2), img.rows - (i*2)), Scalar(0), 7);
557+
rectangle(img, Rect(i, i, img.cols - (i*2), img.rows - (i*2)), Scalar(255), 1);
558+
}
559+
560+
vector<vector<Point> > contours;
561+
vector<Vec4i> hierarchy;
562+
findContours(img, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
563+
img.setTo(Scalar::all(0));
564+
Mat img1 = img.clone();
565+
Mat img2 = img.clone();
566+
Mat img3 = img.clone();
567+
568+
int idx = 0;
569+
while (idx >= 0)
570+
{
571+
drawContours(img, contours, idx, Scalar::all(255), FILLED, LINE_8, hierarchy);
572+
drawContours(img2, contours, idx, Scalar::all(255), 1, LINE_8, hierarchy);
573+
idx = hierarchy[idx][0];
574+
}
575+
576+
drawContours(img1, contours, -1, Scalar::all(255), FILLED, LINE_8, hierarchy);
577+
drawContours(img3, contours, -1, Scalar::all(255), 1, LINE_8, hierarchy);
578+
ASSERT_EQ(0, cvtest::norm(img, img1, NORM_INF));
579+
ASSERT_EQ(0, cvtest::norm(img2, img3, NORM_INF));
580+
}
542581

543582
TEST(Imgproc_PointPolygonTest, regression_10222)
544583
{

0 commit comments

Comments
 (0)