mirror of
https://github.com/opencv/opencv.git
synced 2026-07-21 19:33:03 +04:00
Merge pull request #28051 from dkurt:minAreaRect_angle
Correct minAreaRect angle to be in range [-90, 0) #28051 ### Pull Request Readiness Checklist Box angle range over all imgproc tests is in interval `[-90, -0.0581199]` resolves https://github.com/opencv/opencv/issues/27667 resolves https://github.com/opencv/opencv/issues/19472 resolves https://github.com/opencv/opencv/issues/24436 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. - [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
@@ -1344,8 +1344,8 @@ public class ImgprocTest extends OpenCVTestCase {
|
||||
|
||||
RotatedRect rrect = Imgproc.minAreaRect(points);
|
||||
|
||||
assertEquals(new Size(5, 2), rrect.size);
|
||||
assertEquals(0., rrect.angle);
|
||||
assertEquals(new Size(2, 5), rrect.size);
|
||||
assertEquals(-90., rrect.angle);
|
||||
assertEquals(new Point(3.5, 2), rrect.center);
|
||||
}
|
||||
|
||||
|
||||
@@ -365,6 +365,7 @@ cv::RotatedRect cv::minAreaRect( InputArray _points )
|
||||
Mat hull;
|
||||
Point2f out[3];
|
||||
RotatedRect box;
|
||||
box.angle = -(float)CV_PI / 2; // default angle for box without rotation and single point
|
||||
|
||||
static const bool clockwise = false;
|
||||
convexHull(_points, hull, clockwise, true);
|
||||
@@ -384,19 +385,34 @@ cv::RotatedRect cv::minAreaRect( InputArray _points )
|
||||
rotatingCalipers( hpoints, n, clockwise ? -1.f : 1.f, CALIPERS_MINAREARECT, (float*)out );
|
||||
box.center.x = out[0].x + (out[1].x + out[2].x)*0.5f;
|
||||
box.center.y = out[0].y + (out[1].y + out[2].y)*0.5f;
|
||||
box.size.width = (float)std::sqrt((double)out[1].x*out[1].x + (double)out[1].y*out[1].y);
|
||||
box.size.height = (float)std::sqrt((double)out[2].x*out[2].x + (double)out[2].y*out[2].y);
|
||||
box.angle = (float)atan2( (double)out[1].y, (double)out[1].x );
|
||||
box.size.width = (float)std::sqrt((double)out[2].x*out[2].x + (double)out[2].y*out[2].y);
|
||||
box.size.height = (float)std::sqrt((double)out[1].x*out[1].x + (double)out[1].y*out[1].y);
|
||||
if (out[1].x == 0.f && out[1].y > 0.f)
|
||||
std::swap(box.size.width, box.size.height);
|
||||
else
|
||||
box.angle += (float)atan2( (double)out[1].y, (double)out[1].x );
|
||||
}
|
||||
else if( n == 2 )
|
||||
{
|
||||
box.center.x = (hpoints[0].x + hpoints[1].x)*0.5f;
|
||||
box.center.y = (hpoints[0].y + hpoints[1].y)*0.5f;
|
||||
double dx = hpoints[1].x - hpoints[0].x;
|
||||
double dy = hpoints[1].y - hpoints[0].y;
|
||||
box.size.width = (float)std::sqrt(dx*dx + dy*dy);
|
||||
box.size.height = 0;
|
||||
box.angle = (float)atan2( dy, dx );
|
||||
double dx = hpoints[0].x - hpoints[1].x;
|
||||
double dy = hpoints[0].y - hpoints[1].y;
|
||||
box.size.width = 0;
|
||||
box.size.height = (float)std::sqrt(dx*dx + dy*dy);
|
||||
if (dx == 0)
|
||||
{
|
||||
std::swap(box.size.width, box.size.height);
|
||||
}
|
||||
else if (dy < 0)
|
||||
{
|
||||
box.angle = (float)atan2( dy, dx );
|
||||
std::swap(box.size.width, box.size.height);
|
||||
}
|
||||
else if (dy > 0)
|
||||
{
|
||||
box.angle += (float)atan2( dy, dx );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -405,6 +421,8 @@ cv::RotatedRect cv::minAreaRect( InputArray _points )
|
||||
}
|
||||
|
||||
box.angle = (float)(box.angle*180/CV_PI);
|
||||
CV_DbgCheckGE(box.angle, -90.0f, "");
|
||||
CV_DbgCheckLT(box.angle, 0.0f, "");
|
||||
return box;
|
||||
}
|
||||
|
||||
|
||||
@@ -1265,6 +1265,24 @@ TEST(Imgproc_minAreaRect, reproducer_21482_small_values)
|
||||
EXPECT_EQ(rr.size.height, 1e-4f);
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<tuple<Point2f, Point2f, Point2f, Size2f, float>> minAreaRect_of_line;
|
||||
TEST_P(minAreaRect_of_line, accuracy)
|
||||
{
|
||||
Point2f p1 = get<0>(GetParam());
|
||||
Point2f p2 = get<1>(GetParam());
|
||||
RotatedRect out = minAreaRect(std::vector<Point2f>{p1, p2});
|
||||
EXPECT_EQ(out.center, get<2>(GetParam()));
|
||||
EXPECT_EQ(out.size, get<3>(GetParam()));
|
||||
EXPECT_NEAR(out.angle, get<4>(GetParam()), 1e-6);
|
||||
}
|
||||
INSTANTIATE_TEST_CASE_P(Imgproc, minAreaRect_of_line,
|
||||
testing::Values(
|
||||
std::make_tuple(Point2f(10, 15), Point2f(10, 25), Point2f(10, 20), Size2f(10, 0), -90.f),
|
||||
std::make_tuple(Point2f(450, 500), Point2f(508, 500), Point2f(479, 500), Size2f(0, 58), -90.f),
|
||||
std::make_tuple(Point2f(10, 20), Point2f(13, 16), Point2f(11.5, 18), Size2f(5, 0), -53.1301002f),
|
||||
std::make_tuple(Point2f(9, 19), Point2f(4, 7), Point2f(6.5, 13), Size2f(0, 13), -22.6198654f)
|
||||
));
|
||||
|
||||
}} // namespace
|
||||
|
||||
/* End of file. */
|
||||
|
||||
@@ -710,14 +710,14 @@ QUnit.test('test_rotatedRectangleIntersection', function(assert) {
|
||||
assert.deepEqual(intersectionType, cv.INTERSECT_FULL);
|
||||
intersectionPoints.convertTo(intersectionPoints, cv.CV_32S);
|
||||
let intersectionPointsData = intersectionPoints.data32S;
|
||||
assert.deepEqual(intersectionPointsData[0], 30);
|
||||
assert.deepEqual(intersectionPointsData[1], 40);
|
||||
assert.deepEqual(intersectionPointsData[2], 40);
|
||||
assert.deepEqual(intersectionPointsData[3], 30);
|
||||
assert.deepEqual(intersectionPointsData[4], 50);
|
||||
assert.deepEqual(intersectionPointsData[5], 40);
|
||||
assert.deepEqual(intersectionPointsData[6], 40);
|
||||
assert.deepEqual(intersectionPointsData[7], 50);
|
||||
assert.deepEqual(intersectionPointsData[0], 40);
|
||||
assert.deepEqual(intersectionPointsData[1], 50);
|
||||
assert.deepEqual(intersectionPointsData[2], 30);
|
||||
assert.deepEqual(intersectionPointsData[3], 40);
|
||||
assert.deepEqual(intersectionPointsData[4], 40);
|
||||
assert.deepEqual(intersectionPointsData[5], 30);
|
||||
assert.deepEqual(intersectionPointsData[6], 50);
|
||||
assert.deepEqual(intersectionPointsData[7], 40);
|
||||
|
||||
intersectionType = cv.rotatedRectangleIntersection(rr1, rr3, intersectionPoints);
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ class Hackathon244Tests(NewOpenCVTests):
|
||||
mc, mr = cv.minEnclosingCircle(a)
|
||||
|
||||
be0 = ((150.2511749267578, 150.77322387695312), (158.024658203125, 197.57696533203125), 37.57804489135742)
|
||||
br0 = ((161.2974090576172, 154.41793823242188), (207.7177734375, 199.2301483154297), 80.83544921875)
|
||||
br0 = ((161.2974090576172, 154.41793823242188), (199.2301483154297, 207.7177734375), -9.164555549621582)
|
||||
mc0, mr0 = (160.41790771484375, 144.55152893066406), 136.713500977
|
||||
|
||||
self.check_close_boxes(be, be0, 5, 15)
|
||||
|
||||
Reference in New Issue
Block a user