Fix fillPoly drawing over boundaries

pull/26187/head
inayd 2 months ago
parent f503890c2b
commit 93a882d2e2
  1. 27
      modules/imgproc/src/drawing.cpp
  2. 69
      modules/imgproc/test/test_drawing.cpp

@ -64,7 +64,7 @@ CollectPolyEdges( Mat& img, const Point2l* v, int npts,
int shift, Point offset=Point() );
static void
FillEdgeCollection( Mat& img, std::vector<PolyEdge>& edges, const void* color, int line_type);
FillEdgeCollection( Mat& img, std::vector<PolyEdge>& edges, const void* color );
static void
PolyLine( Mat& img, const Point2l* v, int npts, bool closed,
@ -1051,7 +1051,7 @@ EllipseEx( Mat& img, Point2l center, Size2l axes,
v.push_back(center);
std::vector<PolyEdge> edges;
CollectPolyEdges( img, &v[0], (int)v.size(), edges, color, line_type, XY_SHIFT );
FillEdgeCollection( img, edges, color, line_type );
FillEdgeCollection( img, edges, color );
}
}
@ -1299,15 +1299,11 @@ CollectPolyEdges( Mat& img, const Point2l* v, int count, std::vector<PolyEdge>&
if (t0.y != t1.y)
{
pt0c.y = t0.y; pt1c.y = t1.y;
pt0c.x = (int64)(t0.x) << XY_SHIFT;
pt1c.x = (int64)(t1.x) << XY_SHIFT;
}
}
else
{
pt0c.x += XY_ONE >> 1;
pt1c.x += XY_ONE >> 1;
}
pt0c.x = (int64)(t0.x) << XY_SHIFT;
pt1c.x = (int64)(t1.x) << XY_SHIFT;
}
else
{
@ -1349,7 +1345,7 @@ struct CmpEdges
/**************** helper macros and functions for sequence/contour processing ***********/
static void
FillEdgeCollection( Mat& img, std::vector<PolyEdge>& edges, const void* color, int line_type)
FillEdgeCollection( Mat& img, std::vector<PolyEdge>& edges, const void* color )
{
PolyEdge tmp;
int i, y, total = (int)edges.size();
@ -1358,12 +1354,7 @@ FillEdgeCollection( Mat& img, std::vector<PolyEdge>& edges, const void* color, i
int y_max = INT_MIN, y_min = INT_MAX;
int64 x_max = 0xFFFFFFFFFFFFFFFF, x_min = 0x7FFFFFFFFFFFFFFF;
int pix_size = (int)img.elemSize();
int delta;
if (line_type < cv::LINE_AA)
delta = 0;
else
delta = XY_ONE - 1;
int delta = XY_ONE - 1;
if( total < 2 )
return;
@ -2051,7 +2042,7 @@ void fillPoly( InputOutputArray _img, const Point** pts, const int* npts, int nc
}
}
FillEdgeCollection(img, edges, buf, line_type);
FillEdgeCollection(img, edges, buf);
}
void polylines( InputOutputArray _img, const Point* const* pts, const int* npts, int ncontours, bool isClosed,
@ -2690,7 +2681,7 @@ cvDrawContours( void* _img, CvSeq* contour,
}
if( thickness < 0 )
cv::FillEdgeCollection( img, edges, ext_buf, line_type);
cv::FillEdgeCollection( img, edges, ext_buf );
if( h_next && contour0 )
contour0->h_next = h_next;

@ -680,6 +680,75 @@ TEST(Drawing, fillpoly_circle)
EXPECT_LT(diff_fp3, 1.);
}
TEST(Drawing, fillpoly_contours)
{
const int imgSize = 50;
const int type = CV_8UC1;
const int shift = 0;
const Scalar cl = Scalar::all(255);
const cv::LineTypes lineType = LINE_8;
// check that contours of fillPoly and polylines match
{
cv::Mat img(imgSize, imgSize, type);
img = 0;
std::vector<std::vector<cv::Point>> polygonPoints{
{ {44, 27}, {7, 37}, {7, 19}, {38, 19} }
};
cv::fillPoly(img, polygonPoints, cl, lineType, shift);
cv::polylines(img, polygonPoints, true, 0, 1, lineType, shift);
{
cv::Mat labelImage(img.size(), CV_32S);
int labels = cv::connectedComponents(img, labelImage, 4);
EXPECT_EQ(2, labels) << "filling went over the border";
}
}
// check that line generated with fillPoly and polylines match
{
cv::Mat img1(imgSize, imgSize, type), img2(imgSize, imgSize, type);
img1 = 0;
img2 = 0;
std::vector<std::vector<cv::Point>> polygonPoints{
{ {44, 27}, {38, 19} }
};
cv::fillPoly(img1, polygonPoints, cl, lineType, shift);
cv::polylines(img2, polygonPoints, true, cl, 1, lineType, shift);
EXPECT_MAT_N_DIFF(img1, img2, 0);
}
}
TEST(Drawing, fillpoly_match_lines)
{
const int imgSize = 49;
const int type = CV_8UC1;
const int shift = 0;
const Scalar cl = Scalar::all(255);
const cv::LineTypes lineType = LINE_8;
cv::Mat img1(imgSize, imgSize, type), img2(imgSize, imgSize, type);
for (int x1 = 0; x1 < imgSize; x1 += imgSize / 2)
{
for (int y1 = 0; y1 < imgSize; y1 += imgSize / 2)
{
for (int x2 = 0; x2 < imgSize; x2++)
{
for (int y2 = 0; y2 < imgSize; y2++)
{
img1 = 0;
img2 = 0;
std::vector<std::vector<cv::Point>> polygonPoints{
{ {x1, y1}, {x2, y2} }
};
cv::fillPoly(img1, polygonPoints, cl, lineType, shift);
cv::polylines(img2, polygonPoints, true, cl, 1, lineType, shift);
EXPECT_MAT_N_DIFF(img1, img2, 0);
}
}
}
}
}
TEST(Drawing, fillpoly_fully)
{
unsigned imageWidth = 256;

Loading…
Cancel
Save