Hi,
I’m currently working on computing iou on rotated rectangles, and I’m encountering an assertion error when executing rotatedRectangleIntersection
:
cv2.error: OpenCV(4.2.0) /io/opencv/modules/imgproc/src/intersection.cpp:271: error: (-215:Assertion failed) fabs(normL2Sqr<float>(intersection[minI] - intersection[minJ]) - minD) < 1e-6 in function 'rotatedRectangleIntersection'
The rotated rectangles passed on to the function:
((2.46805033e+05, 4.00232694e+06), (2.64058744e+01, 6.20025761e+00), -6.21015556e+01)
((2.46805122e+05, 4.00232659e+06), (2.74820953e+01, 8.53610030e+00), -5.63376146e+01)
After plotting them, I noticed that some of box A’s corners are nearly blended with box B’s sides, maybe this confuses the algorithm (heavy doubts)
Reading the intersection.cpp file didn’t bring much information other than ptDistRemap
(?) might be “corrupted”.
EDIT: the function runs fine one several rotated rect couples before raising an assertion on those 2.
Didn’t find much topics on the internet of people encountering the same assertion, any clue would be helpful !
Thanks !
hi,
A minimal code will help to reproduce assertion
Indeed
import cv2
import numpy as np
def compute_overlap_oriented_bbox(box, query_box):
"""
Args:
box: (5) ndarray of float
query_box: (5) ndarray of float
Notes:
boxes should be in (x, y, w, h, theta) format
Returns:
overlap: overlap between box and query_box
"""
area1 = box[2] * box[3]
area2 = query_box[2] * query_box[3]
rect_1 = ((box[0], box[1]), (box[2], box[3]), box[4])
rect_2 = ((query_box[0], query_box[1]), (query_box[2], query_box[3]), query_box[4])
inter_points = cv2.rotatedRectangleIntersection(rect_1, rect_2)[1] # <-- crashes here
if inter_points is not None:
order_points = cv2.convexHull(inter_points, returnPoints=True)
inter_area = cv2.contourArea(order_points)
iou = inter_area *1.0 / (area1 + area2 - inter_area)
return iou
else:
return 0.0
box_1 = np.array([2.46805033e+05, 4.00232694e+06, 2.64058744e+01, 6.20025761e+00, -6.21015556e+01])
box_2 = np.array([2.46805122e+05, 4.00232659e+06, 2.74820953e+01, 8.53610030e+00, -5.63376146e+01])
iou = compute_overlap_oriented_bbox(box_1, box_2)
print(iou)
1 Like
Here is a picture of the 2 guilty rectangles
I stripped it down some more. I can reproduce it.
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)))
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
I’d say (1) it’s not designed for very “out there” values (2) it’s calculating some type of error based on this assumption
worth an issue on the github! no matter if you can figure out what the implementation does or not.
the implementation shouldn’t be doing this kind of check at all. it shouldn’t rely on some arbitrary, hardcoded “epsilon”.
1 Like
Thanks for investigating !
It might be a solution to offset the rectangles closer to the (0, 0) before calculating the iou.
I’ll open an issue on github (that was my idea at first, but wanted to check out the forum first)
EDIT: GitHub issue
2 Likes
This is happening because of the types used by the function RotatedRect::points(Point2f pt[])
.
I opened a pull request to solve the issue: Change type used in points function from RotatedRect by gasparitiago · Pull Request #19842 · opencv/opencv · GitHub
May be I’m wrong but I don’t think that a good way to solve this issue. Wait and see reviewer advice
the math happens inside the function, doesn’t affect the API, so I’d say this is okay.
however it doesn’t do much. results are still just FP32. for center coordinates this far away from the origin, results will suck no matter what.