0

This used to work:

cv2.rectangle(image, (top,left), (bottom,right), color=color_tuple, thickness=2)

where image is a nxmx3 array of np.uint8 values and color_tuple consisted of a 3 tuple of np.uint8 values, e.g. (2,56,135). Now it produces this error raised in my own code (not the Numpy or OpenCV code):

Exception has occurred: TypeError
Argument given by name ('color') and position (3)

Removing the names from the arguments:

cv2.rectangle(image, (top,left), (bottom,right), color_tuple, 2)

Produces this error:

TypeError: function takes exactly 4 arguments (2 given)

I believe both errors are related to the overridden rectangle function in openCV's source code where it looks for an image followed by a pair of tuples. If it can't find it, it tries to use an overridden function that accepts an image and a rectangle tuple. So the traceback is not representative of the error, but I can't figure out why the numpy types aren't accepted anymore. I tried np.int16, int (which casts it as a np.int64). I could only get it to run by casting the array as python native ints with the tolist() function.

color_tuple = tuple(np.array(np.random.random(size=3)*255, dtype=np.int).tolist())

What caused this? Are there other places OpenCV where numpy datatypes don't work?

Python: 3.6.9
OpenCV: 4.5.1
Numpy: 1.19.5
IDE: VSCode
DanGoodrick
  • 1,972
  • 3
  • 20
  • 43
  • 1
    try `np.int8`. OpenCV uses either float or `uint8` type for images – DerekG Apr 30 '21 at 18:39
  • In what version do you think it used to work? From the docs at https://docs.opencv.org/3.0.0/d6/d6e/group__imgproc__draw.html#ga07d2f74cadcf8e305e810ce8eed13bc9 as far back as 3.0.0, it was never `color=`. It was always just a tuple. – fmw42 Apr 30 '21 at 20:51

1 Answers1

1

According to this post, using tolist() is probably the right solution.

The issue is that the type of the elements of color_tuple is <class 'numpy.int32'>.
cv2.rectangle expects native python type - tuple with elements of type int.

Here is a code sample that reproduces the error:

import numpy as np
import cv2

image = np.zeros((300, 300, 3), np.uint8)  # Create mat with type uint8 

top, left, bottom, right = 10, 10, 100, 100

color_tuple = tuple(np.array(np.random.random(size=3)*255, dtype=np.int))

print(type(color_tuple[0]))  # <class 'numpy.int32'>

cv2.rectangle(image, (top, left), (bottom, right), color=color_tuple, thickness=2)

The above code prints <class 'numpy.int32'> and raises an exception:

Argument given by name ('color') and position (3)

The same code with .tolist():

color_tuple = tuple(np.array(np.random.random(size=3)*255, dtype=np.int).tolist())

print(type(color_tuple[0]))

The above code prints <class 'int'> without exceptions.


Apparently .tolist() converts the type to native int (NumPy array class implements the method .tolist() to do so).

  • l = list(np.array((1, 2, 3), np.int)) returns a list of numpy.int32 elements.
  • l = np.array((1, 2, 3), np.int).tolist() returns a list of int elements.

The difference of list and tolist() is described here.

Rotem
  • 13,441
  • 4
  • 19
  • 44