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 3f749896a42c8d2339ebae3cb6a1a20887fc89c6..47d3f3f457b5ebf80c10887b669e1d02274cb00d 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 7527dd9a22cc2abd3404fe0a92be4f0596197f0f..c455c439fce113ca44d8ac01672e11edfc22eeca 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