Merge pull request #19842 from gasparitiago:3.4
authorTiago De Gaspari <gaspari.tiago@gmail.com>
Sat, 12 Jun 2021 20:28:54 +0000 (17:28 -0300)
committerGitHub <noreply@github.com>
Sat, 12 Jun 2021 20:28:54 +0000 (23:28 +0300)
Update rotatedRectangleIntersection function to calculate near to origin

* Change type used in points function from RotatedRect

In the function that sets the points of a RotatedRect, the types

should be double in order to keep the precision when dealing with
RotatedRects that are defined far from the origin.

This commit solves the problem in some assertions from
rotatedRectangleIntersection when dealing with rectangles far from
origin.

* added proper type casts

* Update rotatedRectangleIntersection function to calculate near to origin

This commit changes the rotatedRectangleIntersection function in order
to calculate the intersection of two rectangles considering that they
are shifted near the coordinates origin (0, 0).

This commit solves the problem in some assertions from
rotatedRectangleIntersection when dealing with rectangles far from
origin.

* Revert type changes in types.cpp and adequate code to c++98

* Revert unnecessary casts on types.cpp

Co-authored-by: Vadim Pisarevsky <vadim.pisarevsky@gmail.com>
modules/imgproc/src/intersection.cpp
modules/imgproc/test/test_intersection.cpp

index 3f74989..47d3f3f 100644 (file)
 namespace cv
 {
 
-int rotatedRectangleIntersection( const RotatedRect& rect1, const RotatedRect& rect2, OutputArray intersectingRegion )
+static int _rotatedRectangleIntersection( const RotatedRect& rect1, const RotatedRect& rect2, std::vector<Point2f> &intersection )
 {
     CV_INSTRUMENT_REGION();
 
     // L2 metric
     const float samePointEps = std::max(1e-16f, 1e-6f * (float)std::max(rect1.size.area(), rect2.size.area()));
 
-    if (rect1.size.empty() || rect2.size.empty())
-    {
-        intersectingRegion.release();
-        return INTERSECT_NONE;
-    }
-
     Point2f vec1[4], vec2[4];
     Point2f pts1[4], pts2[4];
 
-    std::vector <Point2f> intersection; intersection.reserve(24);
-
     rect1.points(pts1);
     rect2.points(pts2);
 
@@ -92,8 +84,6 @@ int rotatedRectangleIntersection( const RotatedRect& rect1, const RotatedRect& r
                 intersection[i] = pts1[i];
             }
 
-            Mat(intersection).copyTo(intersectingRegion);
-
             return INTERSECT_FULL;
         }
     }
@@ -300,7 +290,50 @@ int rotatedRectangleIntersection( const RotatedRect& rect1, const RotatedRect& r
     }
 
     intersection.resize(N);
-    Mat(intersection).copyTo(intersectingRegion);
+
+    return ret;
+}
+
+int rotatedRectangleIntersection( const RotatedRect& rect1, const RotatedRect& rect2, OutputArray intersectingRegion )
+{
+    CV_INSTRUMENT_REGION();
+
+    if (rect1.size.empty() || rect2.size.empty())
+    {
+        intersectingRegion.release();
+        return INTERSECT_NONE;
+    }
+
+    // Shift rectangles closer to origin (0, 0) to improve the calculation of the intesection region
+    // To do that, the average center of the rectangles is moved to the origin
+    const Point2f averageCenter = (rect1.center + rect2.center) / 2.0f;
+
+    RotatedRect shiftedRect1(rect1);
+    RotatedRect shiftedRect2(rect2);
+
+    // Move rectangles closer to origin
+    shiftedRect1.center -= averageCenter;
+    shiftedRect2.center -= averageCenter;
+
+    std::vector <Point2f> intersection; intersection.reserve(24);
+
+    const int ret = _rotatedRectangleIntersection(shiftedRect1, shiftedRect2, intersection);
+
+    // If return is not None, the intersection Points are shifted back to the original position
+    // and copied to the interesectingRegion
+    if (ret != INTERSECT_NONE)
+    {
+        for (size_t i = 0; i < intersection.size(); ++i)
+        {
+            intersection[i] += averageCenter;
+        }
+
+        Mat(intersection).copyTo(intersectingRegion);
+    }
+    else
+    {
+        intersectingRegion.release();
+    }
 
     return ret;
 }
index 7527dd9..c455c43 100644 (file)
@@ -391,4 +391,21 @@ TEST(Imgproc_RotatedRectangleIntersection, regression_18520)
     }
 }
 
+TEST(Imgproc_RotatedRectangleIntersection, regression_19824)
+{
+    RotatedRect r1(
+        Point2f(246805.033f, 4002326.94f),
+        Size2f(26.40587f, 6.20026f),
+        -62.10156f);
+    RotatedRect r2(
+        Point2f(246805.122f, 4002326.59f),
+        Size2f(27.4821f, 8.5361f),
+        -56.33761f);
+
+    std::vector<Point2f> intersections;
+    int interType = cv::rotatedRectangleIntersection(r1, r2, intersections);
+    EXPECT_EQ(INTERSECT_PARTIAL, interType);
+    EXPECT_LE(intersections.size(), (size_t)7);
+}
+
 }} // namespace