OpenCV cannot access to UVC camera properties

I’m able to read a USB/UVC camera in python through
vc = cv2.VideoCapture(0)
rval, frame = vc.read()
etc.
but I cannot change properties through vc.set(…)
which always return False whatever the property is (gain, brightness… ).
However the application CameraController ( GitHub - itaybre/CameraController: 📷 Control USB Cameras from an app ) is fully able to do it when switching to manual controls.
This means that the camera is indeed fully UVC compatible and can have properties adjusted.
I tried forcing the API to be CAP_OPENCV_MJPEG, since the output format of the video, according to the manufacturer is MJPEG, but I get the message “ [ WARN:0@1960.759] global cap.cpp:344 open VIDEOIO(CV_MJPEG): backend is generally available but can’t be used to capture by index”.
Any help welcome.
Blues

that is for file reading/writing. OpenCV comes with its own MJPEG codec, and AVI muxer/demuxer.

if you want mjpeg from a UVC camera, set CAP_PROP_FOURCC. order matters. try setting this first or last in the list of set() calls.

speculation: the camera is in some kind of “auto adjust” mode and you’d have to disable this explicitly (again some CAP_PROP) before you can change those other values successfully.

Thanks for your help.

In fact applying your advices does not change really. Here follows an example of the code and the result

print(cv2.version)
vc = cv2.VideoCapture(0)

#print(vc.getBackendName())
print(vc.isOpened())
#rval, frame = vc.read()
time.sleep(1)

print(vc.set(cv2.CAP_PROP_AUTO_EXPOSURE, 1)) # no more auto mode
print(vc.get(cv2.CAP_PROP_FOURCC))
print(vc.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc(‘M’,‘J’,‘P’,‘G’)))
time.sleep(1)

print(vc.set(cv2.CAP_PROP_GAIN,4)) # manual mode
print(vc.set(cv2.CAP_PROP_FPS,10)) # manual mode
print(vc.set(cv2.CAP_PROP_CONTRAST,30)) # manual mode

4.10.0
True

[ WARN:0@9275.175] global cap_gstreamer.cpp:1173 isPipelinePlaying OpenCV | GStreamer warning: GStreamer: pipeline have not been created

False
0.0
False
False
True
False

Strangely the setting of FPS does work.
I guess that the warning is a clue but I’ml not able to interpret it.

ignore that warning. when you construct the instance with VideoCapture(0), opencv’s video i/o backends all get a try. some decline because they expect a string (file path, gstreamer pipeline, …), not a number. most decline silently, but some emit a message telling you why they don’t feel responsible. V4L (Linux) or DSHOW/MSMF (Windows) will take that number, as a device index, so your backend should be V4L/DSHOW/MSMF. see getBackendName().

which is it anyway? I didn’t see you say anything about your operating system or the camera.

the isOpened() returning False is the first clue. everything after that is wasted effort.

your camera isn’t actually there, or it’s on some other number, or it’s not actually a USB UVC device but something else, or some other application already has a hold on it.

| crackwitz Moderator
October 27 |

  • | - |

ignore that warning. when you construct the instance with VideoCapture(0), opencv’s video i/o backends all get a try. some decline because they expect a string (file path, gstreamer pipeline, …), not a number. most decline silently, but some emit a message telling you why they don’t feel responsible. V4L (Linux) or DSHOW/MSMF (Windows) will take that number, as a device index, so your backend should be V4L/DSHOW/MSMF. see getBackendName().

in fact it is AVFOUNDATION

which is it anyway? I didn’t see you say anything about your operating system or the camera.

Sorry for that :
Mac OSX Ventura 13.7.5, Apple M2 Max
Camera : chinese one, name IMX298, output format : YUY2/MJEPG

the isOpened() returning False is the first clue. everything after that is wasted effort.

No the False was related to print(vc.set(cv2.CAP_PROP_AUTO_EXPOSURE, 1)) not to print(vc.isOpened())
Here follows a more compact version :

print(cv2.version)
vc = cv2.VideoCapture(0)
print(vc.getBackendName())
print(vc.isOpened())
rval, frame = vc.read()
print(vc.set(cv2.CAP_PROP_AUTO_EXPOSURE, 1)) # no more auto mode
print(vc.set(cv2.CAP_PROP_GAIN,4)) #
print(vc.set(cv2.CAP_PROP_FPS,20)) #
print(vc.set(cv2.CAP_PROP_CONTRAST,30))

4.10.0
AVFOUNDATION
True
False
False
True
False

your camera isn’t actually there, or it’s on some other number, or it’s not actually a USB UVC device but something else, or some other application already has a hold on it.

It is indeed a UVC camera since I can control it with CameraController and, more recently, with uvc-util (https://github.com/jtfrey/uvc-util) that
allows to set all parameters , especially the ones I’m looking for : gain and integration time.

thanks for the advices

might be a case of the AVF backend needing fixes.

install the latest release of opencv. if this still happens on the latest release, then you should file an issue on opencv’s github.

I would try to replicate this but I don’t have any Apples here. do you happen to have, or be able to borrow, any other webcam/UVC device, and see how the set() calls react to it?

| crackwitz Moderator
October 29 |

  • | - |

might be a case of the AVF backend needing fixes.

install the latest release of opencv. if this still happens on the latest release, then you should file an issue on opencv’s github.

The very last release 4.12.0 and the previous one 4.11.0 are not compatible with my python 3.12, so the problem is still there.

I would try to replicate this but I don’t have any Apples here. do you happen to have, or be able to borrow, any other webcam/UVC device, and see how the set() calls react to it?

Yes I’ll certainly find one and make the test.

Thanks again

of course they are. why do you think they aren’t?

Because when I forced mamba to update the opencv package to 4.12.0 or to 4.11.0,
there has been an error when importing cv2 in my Jupyter notebook .

I agree that my remark on python 3.12 compatibility is more a guess than a firm statement …