Skip to content

Update rotatedRectangleIntersection function to calculate near to origin#19842

Merged
alalek merged 6 commits intoopencv:3.4from
gasparitiago:3.4
Jun 12, 2021
Merged

Update rotatedRectangleIntersection function to calculate near to origin#19842
alalek merged 6 commits intoopencv:3.4from
gasparitiago:3.4

Conversation

@gasparitiago
Copy link
Copy Markdown
Contributor

@gasparitiago gasparitiago commented Apr 2, 2021

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.

Original issue: #19824

Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on a code under GPL or other license that is incompatible with OpenCV
  • The PR is proposed to proper branch
  • There is reference to original bug report and related work
  • There is accuracy test, performance test and test data in opencv_extra repository, if applicable
    Patch to opencv_extra has the same branch name.
  • The feature is well documented and sample code can be built with the project CMake
force_builders=linux,docs

@gasparitiago gasparitiago changed the title In the function that sets the points of a RotatedRect, the types Change type used in points function from RotatedRect Apr 2, 2021
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.
@crackwitz
Copy link
Copy Markdown
Contributor

crackwitz commented Apr 3, 2021

does this actually make a difference? it only applies double precision to the calculation itself but the result is still just FP32.

the demo code uses values like 4002326. there is simply not enough precision to go around (6-7 digits).

>>> [cx, cy, w, h, angle] = np.float32([ 246805.033  , 4002326.94   ,      26.40587,       6.20026,     -62.10156])
>>> _angle = angle * pi / 180
>>> a = np.sin(_angle)*0.5
>>> b = np.cos(_angle)*0.5
>>> f = np.float32; cx - f(a)*h - f(b)*w; cy + f(b)*h - f(a)*w
246801.6
4002340.2
>>> f = np.float64; cx - f(a)*h - f(b)*w; cy + f(b)*h - f(a)*w
246801.59334828143
4002340.119037186

@gasparitiago
Copy link
Copy Markdown
Contributor Author

@crackwitz

does this actually make a difference?

Yes. When testing the code provided by @jbwintergest here: #19824:

import cv2 as cv
import numpy as np


def box(box):
    return ((box[0], box[1]), (box[2], box[3]), box[4])


box_1 = np.array([ 246805.033  , 4002326.94   ,      26.40587,       6.20026,     -62.10156])
box_2 = np.array([ 246805.122  , 4002326.59   ,      27.4821 ,       8.5361 ,     -56.33761])

try:
    print(cv.rotatedRectangleIntersection(box(box_1), box(box_2)))  # Assertion error
except Exception as e:
    print(e)

offset = (246805, 4002326, 0, 0, 0)

box_1 -= offset
box_2 -= offset

print(cv.rotatedRectangleIntersection(box(box_1), box(box_2)))  # that works

when the function rotatedRectangleIntersection, creates the pts1 and pts2 arrays and populate them, like this:

    Point2f pts1[4], pts2[4];
    ...
    rect1.points(pts1);
    rect2.points(pts2);

This is the content of rect1, rect2, pts1[0] and pts2[0] before and after this commit:

Before:

rect1.center.x
246805.03125
rect1.center.y
4002327

rect1.size.width
26.405870437622070312
rect1.size.height
6.200260162353515625

rect1.angle
-62.101558685302734375

rect2.center.x
246805.125
rect2.center.y
4002326.5

rect2.size.width
27.482099533081054688
rect2.size.height
8.5361003875732421875

rect2.angle
-56.33760833740234375

pts1[0].x pts1[0].y
246801.59375 4002340

pts2[0].x pts2[0].y
246801.0625 4002340.25

After:

rect1.center.x
246805.03125
rect1.center.y
4002327

rect1.size.width
26.405870437622070312
rect1.size.height
6.200260162353515625

rect1.angle
-62.101558685302734375

rect2.center.x
246805.125
rect2.center.y
4002326.5

rect2.size.width
27.482099533081054688
rect2.size.height
8.5361003875732421875

rect2.angle
-56.33760833740234375

pts1[0].x pts1[0].y
246801.59375 4002340.25

pts2[0].x pts2[0].y
246801.0625 4002340.25

When the function rotatedRectangleIntersection code considers if two points are the same or not, points that are too far away from the origin (high x or y) are considered overlapped in the before code.

@crackwitz
Copy link
Copy Markdown
Contributor

the only difference between your two texts is that pts1[0].y is completely integer in the first and has a .25 decimal part in the second:

image

the algorithm itself will likely need fixes, not just the Rect::points() method

@asenyaev
Copy link
Copy Markdown
Contributor

asenyaev commented Apr 8, 2021

jenkins cn please retry a build

@vpisarev
Copy link
Copy Markdown
Contributor

vpisarev commented Jun 6, 2021

@gasparitiago, thank you for the contribution! I wonder if you could also modify rotatedRectangleIntersection function to shift intersected rectangles closer to the coordinate origin (and then shift the intersection back)? This way we will get much more robust algorithm

@vpisarev vpisarev self-assigned this Jun 6, 2021
@gasparitiago
Copy link
Copy Markdown
Contributor Author

Hello @vpisarev, I'm doing it. When I finish I will update this PR and let you know.

To be honest I will need some help on how to test the solution.

@gasparitiago
Copy link
Copy Markdown
Contributor Author

@vpisarev can you take a look at my last commit?

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.
Copy link
Copy Markdown
Member

@alalek alalek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for update!

Copy link
Copy Markdown
Member

@alalek alalek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!
Please update PR's title and description before merge.

@gasparitiago gasparitiago changed the title Change type used in points function from RotatedRect Update rotatedRectangleIntersection function to calculate near to origin Jun 8, 2021
Copy link
Copy Markdown
Member

@alalek alalek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for contribution 👍

@alalek alalek merged commit 3cf4375 into opencv:3.4 Jun 12, 2021
@alalek alalek mentioned this pull request Jun 19, 2021
@alalek alalek mentioned this pull request Oct 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants