在打开时从OpenCV中的两个摄像头捕获视频

2024-04-20 10:28:23 发布

您现在位置:Python中文网/ 问答频道 /正文

如何使用Python API使用OpenCV一次(或几乎)从两个或多个摄像头捕获视频?

我有三个摄像头,都可以进行视频流,分别位于/dev/video0、/dev/video1和/dev/video2。

tutorial为例,从单个相机捕获图像很简单:

import cv2
cap0 = cv2.VideoCapture(0)
ret0, frame0 = cap0.read()
cv2.imshow('frame', frame0)
cv2.waitKey()

这个很好用。

但是,如果我尝试初始化第二个相机,尝试从中read()返回无:

import cv2
cap0 = cv2.VideoCapture(0)
cap1 = cv2.VideoCapture(1)
ret0, frame0 = cap0.read()
assert ret0 # succeeds
ret1, frame1 = cap1.read()
assert ret1 # fails?!

为了确保我没有意外地给OpenCV一个糟糕的相机索引,我分别测试了每个相机索引,它们都是自己工作的。e、 g

import cv2
#cap0 = cv2.VideoCapture(0)
cap1 = cv2.VideoCapture(1)
#ret0, frame0 = cap0.read()
#assert ret0
ret1, frame1 = cap1.read()
assert ret1 # now it works?!

我做错什么了?

编辑:我的硬件是运行Ubuntu的Macbook Pro。专门在Macbooks上研究这个问题,我发现其他人也遇到了这个问题,无论是在OSX上还是在不同类型的相机上。如果我访问iSight,代码中的两个调用都将失败。


Tags: devimportapireadassertcv2opencv摄像头
3条回答

我使用了“imutils”并阅读了图片上的网络摄像头显示。

import imutils

捕捉视频帧

--- WebCam1

cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH,300) cap.set(cv2.CAP_PROP_FRAME_HEIGHT,300)

--- WebCam2

cap1 = cv2.VideoCapture(1) cap1.set(cv2.CAP_PROP_FRAME_WIDTH,300) cap1.set(cv2.CAP_PROP_FRAME_HEIGHT,300)

--- WebCam3

cap2 = cv2.VideoCapture(2) cap2.set(cv2.CAP_PROP_FRAME_WIDTH,300) cap2.set(cv2.CAP_PROP_FRAME_HEIGHT,300)

--- WebCame4

cap3 = cv2.VideoCapture(3) cap3.set(cv2.CAP_PROP_FRAME_WIDTH,300) cap3.set(cv2.CAP_PROP_FRAME_HEIGHT,300)

我创建函数read_frame()send parameter about Image.fromarray and display

def read_frame(): webCameShow(cap.read(),display1) webCameShow(cap1.read(),display2) webCameShow(cap2.read(),display6) webCameShow(cap3.read(),display7)
window.after(10, read_frame)

最终功能是在“imageFrame”上显示视频

def webCameShow(N,Display): _, frameXX = N cv2imageXX = cv2.cvtColor(frameXX, cv2.COLOR_BGR2RGBA) imgXX = Image.fromarray(cv2imageXX) #imgtkXX = ImageTk.PhotoImage(image=imgXX) Display.imgtk = imgtkXX Display.configure(image=imgtkXX)

例如。 4-webcam

Youtube网站: Youtube

使用OPENCV和两个标准的USB摄像头,我可以使用多线程来完成这项工作。本质上,定义一个打开opencv窗口和VideoCapture元素的函数。然后,创建两个线程,并将camera ID和window name作为输入。

import cv2
import threading

class camThread(threading.Thread):
    def __init__(self, previewName, camID):
        threading.Thread.__init__(self)
        self.previewName = previewName
        self.camID = camID
    def run(self):
        print "Starting " + self.previewName
        camPreview(self.previewName, self.camID)

def camPreview(previewName, camID):
    cv2.namedWindow(previewName)
    cam = cv2.VideoCapture(camID)
    if cam.isOpened():  # try to get the first frame
        rval, frame = cam.read()
    else:
        rval = False

    while rval:
        cv2.imshow(previewName, frame)
        rval, frame = cam.read()
        key = cv2.waitKey(20)
        if key == 27:  # exit on ESC
            break
    cv2.destroyWindow(previewName)

# Create two threads as follows
thread1 = camThread("Camera 1", 1)
thread2 = camThread("Camera 2", 2)
thread1.start()
thread2.start()

学习如何在python中线程的绝佳资源:https://www.tutorialspoint.com/python/python_multithreading.htm

是的,你肯定受到USB带宽的限制。尝试在完全恢复时从两个设备读取数据时,可能会出现错误:

libv4l2: error turning on stream: No space left on device
VIDIOC_STREAMON: No space left on device
Traceback (most recent call last):
  File "p.py", line 7, in <module>
    assert ret1 # fails?!
AssertionError

当你把分辨率降低到160x120时:

import cv2
cap0 = cv2.VideoCapture(0)
cap0.set(3,160)
cap0.set(4,120)
cap1 = cv2.VideoCapture(1)
cap1.set(3,160)
cap1.set(4,120)
ret0, frame0 = cap0.read()
assert ret0 # succeeds
ret1, frame1 = cap1.read()
assert ret1 # fails?!

现在它似乎起作用了!我打赌你的两个摄像头都连接在同一个USB卡上。您可以运行lsusb命令来确定,它应该指示如下内容:

Bus 001 Device 006: ID 046d:081b Logitech, Inc. Webcam C310
Bus 001 Device 004: ID 0409:005a NEC Corp. HighSpeed Hub
Bus 001 Device 007: ID 046d:0990 Logitech, Inc. QuickCam Pro 9000
Bus 001 Device 005: ID 0409:005a NEC Corp. HighSpeed Hub
Bus 001 Device 003: ID 0409:005a NEC Corp. HighSpeed Hub
Bus 001 Device 002: ID 1058:0401 Western Digital Technologies, Inc. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

(注意同一总线上的两个摄像头。)如果可能,您可以将另一个USB卡添加到计算机以获得更多带宽。我以前这样做是为了在一台机器上运行多个完全分辨率的摄像机。虽然这是一个塔式工作站,有可用的主板插槽,不幸的是,你可能没有在MacBook笔记本电脑上的选择。

相关问题 更多 >