Capturing multiple webcams (uvcvideo) with OpenCV on Linux
I am trying to simultaneously stream the images from 3 Logitech Webcam Pro 900 devices using OpenCV 2.1 on Ubuntu 11.10. The uvcvideo driver gets loaded for these.
Capturing two devices works fine, however with three I run into the out of space error for the third:
libv4l2: error turning on stream: No space left on device
I seem to be running into this issue: http://renoirsrants.blogspot.com.au/2011/07/multiple-webcams-on-zoneminder.html and I have attempted to do the quirks=128 (or pretty much any other power-of-two value) trick but to no avail. I also tried on another machine with two USB 2.0 hubs and connecting two cameras to one and the third camera to the second, which resulted into the same problem. I am initializing roughly as follows (using N cameras so the result is actually put into an STL vector):
cv::VideoCapture cap0(0); //(0,1,2..)
and attempting to capture all the cameras in a loop as
cap0.retrieve(frame0);
This works fine for N=2 cameras. When I set N=3 the third window opens but no image appears and the console is spammed full of V4L2 errors. Similarly, when I set N=2, and attempt to open the third camera in say Cheese (simple webcam capture application), this doesn't work either.
Now comes the big but: After trying guvcview by starting three instances of that, I was able to view three cameras at once (with no problems in terms of frame rate or related), so it does not seem to be a hardware issue. I figure there is some property that I should set, but I'm not sure what that is. I have looked into MJPEG (which these cameras seem to support), but haven't succeeded into setting this property, or detect in which mode (yuyv?) they are running if I start them from OpenCV.
Thoughts?
I had this exact problem, using three logitech quickcam pro 9000 cameras (using ubuntu). I could read from two, but not three. In my case, I wasn't using opencv, but was accessing the cameras through V4L2 directly, using memory-mapped IO. Simply put, there was not enough USB bandwidth to allocate three buffers.
I was reading in the uncompressed frames, however. As soon as I switched the format to MJPEG, the data was small enough, and I could read from the three cameras. I used libjpeg to decode the MJPEG stream.
I haven't looked into how to change the image format using OpenCV, but I do know that it needs to be MJPEG to fit all that data.
Before I switched to MJPEG, I spent a lot of time trying to access each camera one at a time, streaming a single frame before switching to the next. Not recommended!
I had this problem too and have a solution that lets me capture 2 cameras at 640x480 with mjpeg compression. I am using a Creative "Live Cam Sync HD VF0770" which incorrectly reports its bandwidth requirements. The quirks=128 fix works for 320x240 uncompressed video. But for compressed (mjpg) format the quirks=128 does not work (it does nothing for compressed formats).
To fix this I modified the uvc driver as follows:
download the kernel sources
mkdir -p ~/Software/kernel-git
cd ~/Software/kernel-git
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
git checkout v3.2
# NOTE: `uname -r` shows me my current kernel is 3.2.0-60-generic
# For a different kernel use a different tag
copy uvc dir:
mkdir -p ~/Software/uvcvideo_driver
cd ~/Software/uvcvideo_driver
#cp -a ~/Software/kernel-git/linux/drivers/media/usb/uvc .
cp ~/Software/kernel-git/linux/drivers/media/video/uvc .
modify Makefile
cd ~/Software/uvcvideo_driver/uvc
vi Makefile
obj-m += aauvcvideo.o
aauvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o
uvc_status.o uvc_isight.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Force bandwith to 0x400 when compressed.
cd ~/Software/uvcvideo_driver/uvc
vw uvc_video.c
Find the uvc_fixup_video_ctrl() function. At the end of the function add:
if (format->flags & UVC_FMT_FLAG_COMPRESSED) {
ctrl->dwMaxPayloadTransferSize = 0x400;
}
build the aauvcvideo module:
make
remove old module and insert new one:
sudo rmmod uvcvideo
sudo insmod ./aauvcvideo.ko quirks=128
run gucview twice with compression in 2 different windows to test
guvcview --device=/dev/video1 --format=mjpg --size=640x480
guvcview --device=/dev/video2 --format=mjpg --size=640x480
Good luck! -Acorn
Most likely there is USB bandwidth contention reported by the driver of the video capture device. Check if the pixel format is YUYV, which happens to be uncompressed. On the contrary, if the pixel format is MJPG (compressed), it is possible to have multiple devices on the same USB channel.
v4l2-ctl -d /dev/video0 --list-formats
The output would be something like below:
ioctl: VIDIOC_ENUM_FMT
Index : 0
Type : Video Capture
Pixel Format: 'YUYV'
Name : 16bpp YUY2, 4:2:2, packed
The following are the possible solutions:
上一篇: 捕捉摄像头图像到内存