The behaviour of cv2.rectangle() for the overloaded method is not what I expected

There are two methods for cv2.rectangle(), one that needs 2 points to draw a rectangle(the top left and the bottom right) and another one in which you can use a Rect.

The behavior seems to be inconsistent, in the sense that if I want to draw a rectangle with the top left(2,2) and bottom right(7,7) using the first method I will get a different result than using a rect with x = 2, y=2, w = 5 and h=5.

I looked in the documentation and it’s specified that the bottom right point using the method with the rect param would be the bottom right of the rect - (1,1), but why it’s that?

2 Likes

can reproduce.

probably nobody has ever given this any thought, or thought to change it.

I can see some sense behind this behavior but I find it inconsistent as well.

the weird rectangle behavior has existed since at least 2010. here’s a git blame: opencv/modules/imgproc/src/drawing.cpp at 2610724ee00a014d206bc04d8969c935ca627630 · opencv/opencv · GitHub

many drawing functions are broken IMHO. line thickness inconsistent/arbitrary/wrong. coordinates treated inconsistently. a bunch of issues.

a proper fix would start with documentation, laying down some ground rules and principles, and then fixing all the APIs to be consistent with that.

a quick fix would be to work on a fix and make a pull request. they might discuss a pull request but it’s more likely to be accepted compared to a mere issue that might not get any work on it.

>>> canvas = np.zeros((10, 10), np.uint8); cv.rectangle(canvas, (2,2), (7,7), color=99)
array([[ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0, 99, 99, 99, 99, 99, 99,  0,  0],
       [ 0,  0, 99,  0,  0,  0,  0, 99,  0,  0],
       [ 0,  0, 99,  0,  0,  0,  0, 99,  0,  0],
       [ 0,  0, 99,  0,  0,  0,  0, 99,  0,  0],
       [ 0,  0, 99,  0,  0,  0,  0, 99,  0,  0],
       [ 0,  0, 99, 99, 99, 99, 99, 99,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0]], dtype=uint8)
>>> canvas = np.zeros((10, 10), np.uint8); cv.rectangle(canvas, (2,2, 5,5), color=99)
array([[ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0, 99, 99, 99, 99, 99,  0,  0,  0],
       [ 0,  0, 99,  0,  0,  0, 99,  0,  0,  0],
       [ 0,  0, 99,  0,  0,  0, 99,  0,  0,  0],
       [ 0,  0, 99,  0,  0,  0, 99,  0,  0,  0],
       [ 0,  0, 99, 99, 99, 99, 99,  0,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0]], dtype=uint8)

this is just insane:

>>> canvas = np.zeros((10, 10), np.uint8); cv.rectangle(canvas, (2,2), (7,7), color=99, thickness=2)
array([[ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0, 99, 99, 99, 99, 99, 99,  0,  0],
       [ 0, 99, 99, 99, 99, 99, 99, 99, 99,  0],
       [ 0, 99, 99, 99, 99, 99, 99, 99, 99,  0],
       [ 0, 99, 99, 99,  0,  0, 99, 99, 99,  0],
       [ 0, 99, 99, 99,  0,  0, 99, 99, 99,  0],
       [ 0, 99, 99, 99, 99, 99, 99, 99, 99,  0],
       [ 0, 99, 99, 99, 99, 99, 99, 99, 99,  0],
       [ 0,  0, 99, 99, 99, 99, 99, 99,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0]], dtype=uint8)
>>> canvas = np.zeros((10, 10), np.uint8); cv.rectangle(canvas, (2,2, 5, 5), color=99, thickness=2)
array([[ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0, 99, 99, 99, 99, 99,  0,  0,  0],
       [ 0, 99, 99, 99, 99, 99, 99, 99,  0,  0],
       [ 0, 99, 99, 99, 99, 99, 99, 99,  0,  0],
       [ 0, 99, 99, 99,  0, 99, 99, 99,  0,  0],
       [ 0, 99, 99, 99, 99, 99, 99, 99,  0,  0],
       [ 0, 99, 99, 99, 99, 99, 99, 99,  0,  0],
       [ 0,  0, 99, 99, 99, 99, 99,  0,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0]], dtype=uint8)
2 Likes