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

时间:2012-03-20 05:29:28

标签: opencv webcam v4l2

我正在尝试使用Ubuntu 11.10上的OpenCV 2.1同时传输来自3台Logitech Webcam Pro 900设备的图像。 uvcvideo驱动程序会加载这些。

捕获两个设备工作正常,但有三个我遇到了第三个空间错误:

libv4l2: error turning on stream: No space left on device

我似乎遇到了这个问题: http://renoirsrants.blogspot.com.au/2011/07/multiple-webcams-on-zoneminder.html并且我试图做怪癖= 128(或几乎任何其他任何二次幂值)技巧但无济于事。我还尝试了另一台带有两个USB 2.0集线器的机器,并将两个摄像头连接到一个,第三个摄像头连接到第二个,这导致了同样的问题。我大致如下初始化(使用N个摄像头,因此结果实际上放入STL向量):

cv::VideoCapture cap0(0); //(0,1,2..)

并尝试以循环方式捕获所有摄像机

cap0.retrieve(frame0);

这适用于N = 2台相机。当我设置N = 3时,第三个窗口打开但没有图像出现,控制台被垃圾邮件充满了V4L2错误。同样,当我设置N = 2,并尝试打开第三个摄像头时说干酪(简单的网络摄像头捕获应用程序),这也不起作用。

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

思想?

7 个答案:

答案 0 :(得分:9)

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

然而,我正在阅读未压缩的帧。一旦我将格式切换到MJPEG,数据就足够小了,我可以从三个摄像头读取。我使用libjpeg来解码MJPEG流。

我还没有研究如何使用OpenCV更改图像格式,但我知道它需要MJPEG来适应所有数据。

在我切换到MJPEG之前,我花了很多时间尝试一次访问一个摄像头,在切换到下一个帧之前流式传输一个帧。不推荐!

答案 1 :(得分:9)

我也有这个问题并且有一个解决方案,让我可以使用mjpeg压缩捕获640x480的2个摄像头。我正在使用Creative“Live Cam Sync HD VF0770”,它错误地报告了其带宽要求。 quirks = 128 fix适用于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

压缩时强制带宽为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

在2个不同的窗口中使用压缩运行gucview两次以进行测试

guvcview --device=/dev/video1 --format=mjpg --size=640x480
guvcview --device=/dev/video2 --format=mjpg --size=640x480
祝你好运! -Acorn

答案 2 :(得分:6)

最有可能是视频捕获设备的驱动程序报告了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

以下是可能的解决方案:

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

答案 3 :(得分:4)

可以构建OpenCV以使用 v4l libv4l ,并且只有v4l版本支持压缩格式,而libv4l版本仅支持OpenCV 2.4的一种未压缩格式。 11。 (有关v4l的信息,请参阅autosetup_capture_mode_v4l2(),有关libv4l的信息,请参阅line 692后面的代码。)OpenCV 3.0.0在这方面的改进不超过2.4.11;它仍然只支持libv4l的未压缩格式。

由于您的错误提及libv4l2,您似乎在您的情况下将libv4l版本和OpenCV捕获为未压缩。要构建v4l版本的OpenCV,您的cmake命令应包含

-D WITH_LIBV4L=OFF

(我默认为WITH_LIBV4L启用了。)

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

对于预留了超出所需USB带宽的网络摄像头,例如footnote [13]UVC driver page的用户,FIX_BANDWIDTH quirk可以提供帮助。但这个怪癖只适用于未压缩的格式(除非你在Acorn做了内核破解的答案)。在我的情况下(Ubuntu 14.04,许多微软LifeCam电影院在320x240),当我使用libv4l版本的OpenCV(ASMedia USB主机控制器上的四个LifeCams运行良好)但是对于v4l版本 - 我确认使用它时,这个怪癖起作用了MJPEG - 我试图从第二个LifeCam捕获时出现VIDIOC_STREAMON: No space left on device错误! (对于同一台机器,英特尔和威盛主机控制器做得更好,每个都使用两个LifeCams for v4l; LifeCam保留了48%的USB 2.0带宽。)

答案 4 :(得分:1)

这对我来说很有魅力

sudo rmmod uvcvideo

sudo modprobe uvcvideo quirks = 128

每次重启都会重置。如果这样做,请创建以下文件: sudo vi /etc/modprobe.d/uvcvideo.conf 包含这一行: 选项uvcvideo quirks = 128

检查此链接 http://renoirsrants.blogspot.in/2011/07/multiple-webcams-on-zoneminder.html

答案 5 :(得分:0)

我发现的最有用的事情之一是你在捕获初始化之间进行Sleep(ms)调用。这使我能够同时检索两个网络摄像头捕获。

答案 6 :(得分:0)

使用在Ubuntu 18.04上通用的内核4.15.0-34,以及使用gstreamer / v4l支持编译的OpenCV 3.4,我能够使用动力集线器在MUSB压缩的情况下在python上使用MJPG压缩在单个USB端口上流3x720p(使用2xC922和1xC920摄像机-不需要10fps的帧率即可工作):

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)