Antialiased polygon fill doesn't respect area borders
I want to draw a quadrilateral which vertices doesn't coincide with pixel boundaries. The simplest case is a square with all 4 vertices located exactly in the middle of pixels. Here is my code doing it:
cv::Point2f A(5.5,2.5), B(6.5, 2.5), C(6.5,3.5), D(5.5, 3.5);
cv::Point points[4] = {A, B, C, D};
const cv::Point *contours[1] = {points};
int lengths[1] = {4};
cv::Mat p(10, 10, CV_8U, cv::Scalar(0));
cv::fillPoly(p, contours, lengths, 1, cv::Scalar(100), CV_AA, 0);
std::cout << p << std::endl;
In the output image I expected 4 pixels with the value of 25%, i.e. total value of 100 (because the area of the square is exactly 1). But the real output looks like this:
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 19, 100, 22, 0, 0;
0, 0, 0, 0, 0, 36, 100, 40, 0, 0;
0, 0, 0, 0, 0, 20, 83, 22, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Is this a bug in the library or do I use it in a wrong way? And how to draw a simple 1x1 antialiased square?
UPDATE: After removing CV_AA flag the output of
cv::fillPoly(p, contours, lengths, 1, cv::Scalar(100));
looks like this:
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 100, 0, 0, 0;
0, 0, 0, 0, 0, 0, 100, 0, 0, 0;
0, 0, 0, 0, 0, 0, 100, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
I think that is filling with degradation, because of the CV_AA flag. But I do not understand why the (2,6) pixel is 100, too.
I updated the posting: without CV_AA flag I have 3 full (100%) pixels instead of expected four pixels at 25% each.
cv::fillPoly(p, contours, lengths, 0, cv::Scalar(100));
? Normally, the first index is 0, not 1.1) Yes, I run debug version, should it be any difference?
2) I don't understand your item "2": of course I set 4th parameter of cv::fillPoly(...) to 1, not to 0, because the documentation says: "ncontours – Number of contours that bind the filled region", and I have ONE contour, not ZERO contours.
3) I removed ".5" from all the coordinates: cv::Point2f A(5,2), B(6, 2), C(6,3), D(5, 3); The result differs a bit, but still a very wrong one: 0, 10, 10, 0 // 10, 100, 100, 12 // 10, 85, 87, 12 // 0, 12, 12, 0 //