OpenCV setting VideoCap property to CAP_PROP_CONVERT_RGB generates weird boolean argument error

Viewed 2189

I am using OpenCV to read in a live video stream from a USB webcam using:

cap = cv2.VideoCapture(1)

When trying to set the properties of VideoCapture() I pass in the argument CV_CAP_PROP_CONVERT_RGB with a boolean flag, as such:

cap.set(cv2.CAP_PROP_CONVERT_RGB, False)

According to the documentation, all should be good:

CV_CAP_PROP_CONVERT_RGB Boolean flags indicating whether images should be converted to RGB. link

But I am getting the following error:

TypeError: Argument 'value' must be double, not bool

Am I totally misunderstanding the OpenCV documentation?

2 Answers

Figured it out. It's an open bug with OpenCV. Seems to be either an issue on ARM or an issue with OpenCV 4.3.

On OpenCV 4.2 / x86_64 / Python 3.7

>>> import cv2
>>> cap = cv2.VideoCapture(0)
>>> cap.set(cv2.CAP_PROP_CONVERT_RGB, False)
True
>>> cap.set(cv2.CAP_PROP_CONVERT_RGB, 1)
True
>>> cap.set(cv2.CAP_PROP_CONVERT_RGB, 0)
True

However using False on OpenCV 4.3/aarch64/Python 3.7 now causes a TypeError.

Shoutout to jveitchmichaelis (git)

I'm not sure why no one upvoted your question, or acted like you were insane when you posted this, but this is indeed an undocumented breaking issue, and clearly in the past using bool worked.

The solution is not to downgrade your OpenCV bindings for Python, this is expected behavior, the proper solution is to input 1.0 and 0.0 for true and false for the appropriate property value. Using doubles as bools is expected behavior in this case.

Background

Here is a separate issue that also talks about this. https://github.com/opencv/opencv/issues/11398.

Now, as with most of these oddities when it comes to OpenCV's strange changes to its Python API, we've got to go back and look at the C++ api.

The C++ API looks almost identical to the python one: https://docs.opencv.org/4.0.0/d8/dfe/classcv_1_1VideoCapture.html#a8c6d8c2d37505b5ca61ffd4bb54e9a7c

virtual bool cv::VideoCapture::set  (   int     propId,
                                        double  value 
                                    )   

Notice this is OpenCV 4.0, this API interface in fact goes all the way back to when these options were first implemented in the VideoCapture class in OpenCV. In fact, this was (and still is) the way the C++ interface was used while OpenCV 4.2 version of the Python API was active, which accepted bools.

Now this might seem strange, why would such a function not accept bools in the first place? Well some of these properties actually aren't flags, but accept or return actual non boolean values ie:

cv2.CAP_PROP_ZOOM
cv2.CAP_PROP_FRAME_WIDTH 

etc...

Now why aren't separate functions used for each input type (bool, double, int etc...)? It reduces the API surface area, and as a maintaner you only have to deal with one spot to set values, and not have to provide errors for the wrong type of input for different enums (though, these are arguably not good reasons to have this kind of API). You see this pattern with a lot of OpenCV functions, heck even the CV_ type enum values for cv::Mat works like this (which have been replaced by raw numpy arrays for the most part in the python API).

Now, why was the functionality for set changed to the C++ api's functionality for the Python API? The maintainers for python bindings for OpenCV have been trying to maintain parity and consistency with the C++ API for a while now, trying to make it so if you look up a python tutorial on OpenCV, it will work with the C++ version, and vice versa, the two APIs used to differ quite a bit. Today this has largely been accomplished, though there are a few rough spots like here, where the Python API was more lax in what it accepted than the C++ equivalent.

Related