ISSUE:
Unable to open a stream (cv.VideoCapture()) from the USB capture device using a non-V4L2 API backend
I want 640x480 resolution in any workable format
I can only get 480x320
SETUP:
Ras-pi4, Raspian Billseye 5.15.32-v7l+, openCV 4.6.0, Python 3.9.2.
easierCAP video capture USB device, driver: uvcvideo 5.15.32
FACTS:
-
device in question is /dev/video0
Bus 001 Device 003: ID 534d:0021 MacroSilicon MS210x Video Grabber [EasierCAP]
It will open and work fine as backend V4L2 at 480x320 resolution -
USB device “easierCAP” has the following formats available:
$ v4l2-ctl --list-formats-ext
.ioctl: VIDIOC_ENUM_FMT
Type: Video CaptureSize: Discrete 480x320 Interval: Discrete 0.040s (25.000 fps) Size: Discrete 640x480 Interval: Discrete 0.040s (25.000 fps) Interval: Discrete 0.050s (20.000 fps) Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.100s (10.000 fps) Size: Discrete 720x480 Interval: Discrete 0.040s (25.000 fps) Interval: Discrete 0.050s (20.000 fps) Interval: Discrete 0.067s (15.000 fps) Interval: Discrete 0.100s (10.000 fps)
Size: Discrete 480x320 Interval: Discrete 0.040s (25.000 fps)
-
v4l2-ctl can set the device to 640x480, MJPG capture, which is what I want:
$ v4l2-ctl -V
Format Video Capture:
Width/Height : 640/480
Pixel Format : ‘MJPG’ (Motion-JPEG)
Field : None
Bytes per Line : 0
Size Image : 614400
Colorspace : sRGB
Transfer Function : Rec. 709
YCbCr/HSV Encoding: ITU-R 601
Quantization : Default (maps to Full Range)
Flags : -
qv4l2 shows the same as #3 above and can capture the 640 MJPG stream.
qv4l2 can also set the device to any of the formats listed in #2, and can capture fine.
THE PROBLEM:
I run the following code:
import cv2 as cv
device= '/dev/video0'
api= cv.CAP_OPENCV_MJPEG
cap = cv.VideoCapture(device, api)
print("cap.getBackendName = {}".format(cap.getBackendName()))
""" prints 'V4L2' """
ret, frame=cap.read()
print("Frame actual is {}x{}".format(str(frame.shape[1]), str(frame.shape[0])))
""" prints 'Frame actual is 480x320' """
!! Not what I want.
Back in the shell I look at the device setup again and it has changed to 480x320 in YUYV format:
$ v4l2-ctl -V
Format Video Capture:
Width/Height : 480/320
Pixel Format : ‘YUYV’ (YUYV 4:2:2)
Field : None
Bytes per Line : 960
Size Image : 307200
Colorspace : sRGB
Transfer Function : Rec. 709
YCbCr/HSV Encoding: ITU-R 601
Quantization : Default (maps to Limited Range)
Flags :
From this I conclude cv.VideoCapture is simply opening the device with the V4L2 backend, ignoring my MJPEG request.
I HAVE TRIED:
- Every API listed in the cv::VideoCaptureAPIs enumerations.
- Verifying the API is available:
print("stream backendS = " +str(cv.videoio_registry.getStreamBackends()))
prints ‘stream backendS = (1900, 1800, 2300, 200, 2000, 2200)’
NOTE: cv.CAP_OPENCV_MJPEG = 2200
NOTE: cv.CAP_V4L2 = 200 - after creating the capture object cap, I release it and then open again using cap.open(device, api) just to see if that might trick it into working. No good…
MY THINKING:
I can’t blame the device and driver given that v4l2-ctl and qv4l2 seems to handle the device correctly.
I blame something funny in openCV VideoCapture(). It does not seem to want to open any of the MJPG formats.
Any input is welcome. Many thanks,
Jeff C.