列出可用的摄像头 OpenCV/Python

17

我有多个网络摄像头连接到我的电脑,我想根据它们的信息(名称、分辨率等)选择其中一个摄像头。是否有一种方法可以列出计算机上所有可用的摄像头,而不是尝试在cv2.VideoCapture()中使用所有索引?


https://dev59.com/D5Hea4cB1Zd3GeqPvukF - rohit prakash
3个回答

27
回答你的问题,你可以使用 while 循环:
import cv2


def list_ports():
    """
    Test the ports and returns a tuple with the available ports 
    and the ones that are working.
    """
    is_working = True
    dev_port = 0
    working_ports = []
    available_ports = []
    while is_working:
        camera = cv2.VideoCapture(dev_port)
        if not camera.isOpened():
            is_working = False
            print("Port %s is not working." %dev_port)
        else:
            is_reading, img = camera.read()
            w = camera.get(3)
            h = camera.get(4)
            if is_reading:
                print("Port %s is working and reads images (%s x %s)" %(dev_port,h,w))
                working_ports.append(dev_port)
            else:
                print("Port %s for camera ( %s x %s) is present but does not reads." %(dev_port,h,w))
                available_ports.append(dev_port)
        dev_port +=1
    return available_ports,working_ports

这个方案在你的代码中实现起来很容易。

版本 2

正如 @ketza 所指出的,有些情况下工作端口不是连续的,这个版本将在退出 while 循环之前测试至少 5 个不工作的端口:

import cv2
    
    
def list_ports():
    """
    Test the ports and returns a tuple with the available ports and the ones that are working.
    """
    non_working_ports = []
    dev_port = 0
    working_ports = []
    available_ports = []
    while len(non_working_ports) < 6: # if there are more than 5 non working ports stop the testing. 
        camera = cv2.VideoCapture(dev_port)
        if not camera.isOpened():
            non_working_ports.append(dev_port)
            print("Port %s is not working." %dev_port)
        else:
            is_reading, img = camera.read()
            w = camera.get(3)
            h = camera.get(4)
            if is_reading:
                print("Port %s is working and reads images (%s x %s)" %(dev_port,h,w))
                working_ports.append(dev_port)
            else:
                print("Port %s for camera ( %s x %s) is present but does not reads." %(dev_port,h,w))
                available_ports.append(dev_port)
        dev_port +=1
    return available_ports,working_ports,non_working_ports

4
我认为这个比被选中的答案更有用,因为它是用Python编写的。谢谢。 - Jonathan Wilson
1
我曾经遇到这样一种情况,即端口0和端口2上都有可用的摄像头,但是端口1上没有。答案中的while循环会在发现端口1不起作用后退出。我只是将while循环替换为一个for循环,最大端口号为任意值(10),以便查看所有内容。 - ketza
1
@ketza,感谢您的反馈,我已经更新了答案。 - G M

6
答案是否定的。OpenCV没有一种方法可以列出系统上可用的视频捕获设备。如果您查看代码,您会看到目前OpenCV如何处理不存在的无效设备索引。例如,在MacOS上,这里是代码
if ( cameraNum < 0 || devices.count <= NSUInteger(cameraNum) ) {
    fprintf(stderr, "OpenCV: out device of bound (0-%ld): %d\n", devices.count-1, cameraNum);
    [localpool drain];
    return 0;
}

你看到devices.count返回可用设备的数量,但OpenCV没有将其返回给用户的方法。
Windows相关代码在这里
if ((unsigned)m_deviceID >= m_devices.Get()->Size)
{
    OutputDebugStringA("Video::initGrabber - no video device found\n");
    return false;
}

再次强调,没有函数可以将m_devices.Get()->Size返回给用户。Linux代码有点复杂。

如果您正在从代码构建OpenCV,则可以添加一个返回可用设备数量的函数。或者更好的是,向OpenCV提交拉取请求并附上您的补丁。


1
嗯...我想知道AVFoundation是否以与“ffmpeg”相同的顺序枚举OpenCV设备。https://stackoverflow.com/a/46768069/2836621 - Mark Setchell
@MarkSetchell,应该是相同的顺序,只有一个区别。ffmpeg 列出了视频和混合设备:https://github.com/FFmpeg/FFmpeg/blob/master/libavdevice/avfoundation.m#L703-L704 opencv 只枚举视频设备。但两者都使用 AVCaptureDevice 的相同方法,因此视频设备的顺序必须相同。 - fireant

4

首先安装包:

pip install pygrabber==0.1

代码 #

from pygrabber.dshow_graph import FilterGraph

graph = FilterGraph()

print(graph.get_input_devices())# list of camera device 

try:
    device =graph.get_input_devices().index("name camera that I want to use it ")

except ValueError as e:

    device = graph.get_input_devices().index("Integrated Webcam")#use default camera if the name of the camera that I want to use is not in my list

vid=cv2.VideoCapture(device)

4
如果不明显的话,pygrabber仅适用于Windows操作系统。 - Francis Laclé

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接