在Linux上使用OpenCV捕获多个网络摄像头(uvcvideo)

在Linux上使用OpenCV捕获多个网络摄像头(uvcvideo),opencv,webcam,v4l2,Opencv,Webcam,V4l2,我正在尝试使用Ubuntu11.10上的OpenCV 2.1同时从3台Logitech Webcam Pro 900设备上传输图像。将加载uvcvideo驱动程序以执行这些操作 捕获两个设备可以正常工作,但是如果有三个设备,我会遇到第三个设备的空间不足错误: libv4l2: error turning on stream: No space left on device 我似乎遇到了这个问题: 我曾尝试过使用怪癖=128(或几乎任何其他二值幂)技巧,但没有效果。我还尝试在另一台有两个USB

我正在尝试使用Ubuntu11.10上的OpenCV 2.1同时从3台Logitech Webcam Pro 900设备上传输图像。将加载uvcvideo驱动程序以执行这些操作

捕获两个设备可以正常工作,但是如果有三个设备,我会遇到第三个设备的空间不足错误:

libv4l2: error turning on stream: No space left on device
我似乎遇到了这个问题: 我曾尝试过使用怪癖=128(或几乎任何其他二值幂)技巧,但没有效果。我还尝试在另一台有两个USB 2.0集线器的机器上,将两个摄像头连接到一个摄像头上,将第三个摄像头连接到第二个摄像头上,这导致了相同的问题。我大致如下初始化(使用N个摄像头,因此结果实际上被放入STL向量中):

并试图在一个循环中捕获所有摄像机

cap0.retrieve(frame0);
这适用于N=2个摄像头。当我设置N=3时,第三个窗口打开,但没有显示任何图像,并且控制台中充斥着V4L2错误。类似地,当我设置N=2,并尝试在say Cheese(简单网络摄像头捕获应用程序)中打开第三个摄像头时,这也不起作用

现在大问题来了,但是:通过启动三个实例尝试guvcview后,我能够同时查看三个摄像头(在帧速率或相关方面没有问题),因此这似乎不是硬件问题。我想我应该设置一些属性,但我不确定那是什么。我已经查看了MJPEG(这些相机似乎支持它),但是没有成功设置这个属性,或者如果我从OpenCV启动它们,也没有检测到它们在哪个模式下运行(yuyv?)


想法?

我使用三台罗技quickcam pro 9000摄像头(使用ubuntu)时遇到了这个问题。我能读两本,但不能读三本。在我的例子中,我没有使用opencv,而是通过V4L2直接访问摄像头,使用内存映射IO。简单地说,没有足够的USB带宽来分配三个缓冲区

然而,我是在未压缩的帧中阅读的。当我将格式切换到MJPEG时,数据就足够小了,我可以从三个摄像头读取数据。我使用libjpeg对MJPEG流进行解码

我还没有研究过如何使用OpenCV更改图像格式,但我知道需要对其进行修改以适应所有数据


在我切换到MJPEG之前,我花了很多时间试图一次一个地访问每个摄像头,在切换到下一个之前流一帧。不推荐

我发现的最有用的事情之一是,如果在捕获初始化之间打一个睡眠(ms)电话。这使我能够毫无问题地同时检索两个网络摄像头捕获。

很可能是视频捕获设备的驱动程序报告了USB带宽争用。检查像素格式是否为YUYV,这恰好是未压缩的。相反,如果像素格式为MJPG(压缩),则可能在同一USB通道上有多个设备

v4l2-ctl -d /dev/video0 --list-formats
输出如下所示:

ioctl: VIDIOC_ENUM_FMT
    Index       : 0
    Type        : Video Capture
    Pixel Format: 'YUYV'
    Name        : 16bpp YUY2, 4:2:2, packed
以下是可能的解决方案:

  • 使用来自不同制造商的捕获设备,以便加载的驱动程序不同。通常,处理多个设备的同一驱动程序需要有效地处理带宽
  • 使用PCI USB扩展卡(如果可用)连接第二个USB视频捕获设备。当我尝试连接加载了驱动程序cx231xx的AVerMedia DVD EZMaker 7时,这种解决方法对我来说非常有效

  • 我也有这个问题,我有一个解决方案,让我用mjpeg压缩,以640x480的速度拍摄两个摄像头。我使用的是一个创造性的“实时摄像头同步高清VF0770”,它错误地报告了它的带宽要求。quirks=128修复程序适用于320x240未压缩视频。但是对于压缩(mjpg)格式,quirks=128不起作用(对于压缩格式它不起作用)

    为了解决这个问题,我修改了uvc驱动程序,如下所示:

    下载内核源代码

    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
    
    复制uvc目录:

    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 .
    
    修改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
    
    压缩时将bandwith强制设置为0x400

    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;
          }
    
    构建aauvcvideo模块:

    make
    
    卸下旧模块并插入新模块:

    sudo rmmod uvcvideo
    sudo insmod ./aauvcvideo.ko quirks=128
    
    在两个不同的窗口中运行gucview两次并进行压缩以进行测试

    guvcview --device=/dev/video1 --format=mjpg --size=640x480
    guvcview --device=/dev/video2 --format=mjpg --size=640x480
    
    祝你好运!
    -橡子这对我来说很有魅力

    sudo rmmod uvcvideo

    sudo modprobe uvcvideo怪癖=128

    这将在每次重新启动时重置。如果可行,请创建以下文件: sudo vi/etc/modprobe.d/uvcvideo.conf 包含以下行: 选项uvcvideo怪癖=128

    检查此链接

    OpenCV可以构建为使用v4llibv4l,并且只有v4l版本支持压缩格式,而libv4l版本只支持OpenCV 2.4.11的一种未压缩格式。(参见v4l和libv4l的以下代码。)OpenCV 3.0.0在这里没有比2.4.11改进很多;它仍然只支持libv4l的未压缩格式

    由于您的错误提到了
    libv4l2
    ,因此在您的案例中,似乎已捕获到未压缩的libv4l版本和OpenCV。要构建OpenCV的v4l版本,cmake命令应该包含

    -D WITH_LIBV4L=OFF
    
    WITH_LIBV4L
    已默认为我启用。)

    关于带宽和USB的说明。USB 2.0(几乎所有网络摄像头都使用)的带宽为480 Mbit/s。以30 fps和24位/像素的速度进行的640x480未压缩速度约为221 Mbit/s,因此使用未压缩的网络摄像头可以快速使用USB 2.0带宽。每个USB主机控制器的速度为480 Mbit/s,请参见如何列出它们。(USB集线器不添加主机控制器,主板上的几个USB端口通常连接到同一个主机控制器。连接到主机控制器的所有设备和集线器共享带宽。)

    对于保留的USB带宽超过其需要的网络摄像头(例如,在上的网络摄像头),FIX_带宽会有所帮助。但是这种怪癖只适用于未压缩的格式(除非您在Acorn的答案中进行内核破解)。在我的例子中(Ubuntu 14.04,许多微型机)
    -D WITH_LIBV4L=OFF
    
    def open_cam_usb(dev, width, height):
        gst_str = (
            "v4l2src device=/dev/video{} ! "
            "image/jpeg,widh=(int){},height=(int){},framerate=10/1,"
            "format=(string)RGB ! "
            "jpegdec ! videoconvert ! appsink"
        ).format(dev, width, height)
        return cv2.VideoCapture(gst_str, cv2.CAP_GSTREAMER)