【问题标题】:Enumerate over cameras in Python在 Python 中枚举相机
【发布时间】:2018-09-28 15:37:05
【问题描述】:

我在用 Python 枚举多个操作系统上的相机时遇到了一些麻烦。

以下是我尝试过的一些方法:

import cv2 as cv
num = 0
while 1:
    cap = cv.VideoCapture(num)
    if cap.isOpened():
        # working capture
        num += 1
    else:
        break

使用 Opencv 的缺点是 Opencv 不提供任何友好的显示名称。此外,枚举相机很慢,因为您需要实际打开和关闭相机以检查它是否是有效的相机。

我也尝试过使用 PyPylon 和 pyuvc 等库。它们有效,但仅适用于特定品牌。

我对堆栈溢出进行了一些研究,有些人建议将 python 的 gstreamer 绑定作为可能的独立于操作系统的解决方案。这是我目前所拥有的。

import pgi
pgi.require_version("Gtk", "3.0")
pgi.require_version("Gst", "1.0")
pgi.require_version("GstVideo", "1.0")
from pgi.repository import Gtk, GObject, Gst, GstVideo

Gst.init("")
dm = Gst.DeviceMonitor()
dm.set_show_all_devices(True)

dm.start()

print("Displaying devices.")
for device in dm.get_devices():
    print(device.get_display_name())
print("Displaying providers.")
for provider in dm.get_providers():
    print(provider)

dm.stop()

这是我得到的输出:

Displaying devices.
papalook Microphone
DisplayPort
HDMI
Built-in Output
Built-in Microph
Displaying providers.
osxaudiodeviceprovider

出于某种原因,我没有收到任何网络摄像头,只有音频设备。 关于我做错了什么的任何想法? 我应该采取任何不同的方法吗? 谢谢。

【问题讨论】:

    标签: python opencv gstreamer python-gstreamer


    【解决方案1】:

    我最近遇到了这个问题,甚至没有意识到它有多难! 在这里分享我的解决方案,希望对某人有所帮助。

    正如已经指出的那样,以跨平台的方式做到这一点并不容易,我们仍然需要编写特定于平台的代码。 我的解决方案实际上是这里提供的一些方法的组合,所以让我们分解一下。

    1.获取相机的索引

    我们要解决的第一件事是有多少相机设备连接到计算机。 我们可以为此使用 OpenCV 以及上面已经提到的方法。

    2。 Linux

    Linux 将有关视频设备的信息存储在 /sys/class/video4linux 由于我们知道每个摄像头的索引,我们可以做这样的事情来获取额外的信息。

    cat /sys/class/video4linux/video1/name
    

    3。窗户

    Windows 通过Windows Runtime(也称为 WinRT)提供了许多有用的 API。 微软为此提供了Python library,要获取我们需要使用DevicesEnumeration API 的相机信息。

    4. macOS

    对于 MacO,我们可以使用与 Linux 类似的方法。似乎ioregsystem_profiler 命令可以提供相机名称信息。 不幸的是,我没有 MacOS 系统来测试这个,所以我留下了一个 TODO。如果有人可以尝试并分享它,那就太好了。

    这是我的代码。

    import asyncio
    import platform
    import subprocess
    
    import cv2
    
    if platform.system() == 'Windows':
        import winrt.windows.devices.enumeration as windows_devices
    
    VIDEO_DEVICES = 4
    
    
    class Camera:
    
        def __init__(self):
            self.cameras = []
    
        def get_camera_info(self) -> list:
            self.cameras = []
    
            camera_indexes = self.get_camera_indexes()
    
            if len(camera_indexes) == 0:
                return self.cameras
    
            self.cameras = self.add_camera_information(camera_indexes)
    
            return self.cameras
    
        def get_camera_indexes(self):
            index = 0
            camera_indexes = []
            max_numbers_of_cameras_to_check = 10
            while max_numbers_of_cameras_to_check > 0:
                capture = cv2.VideoCapture(index)
                if capture.read()[0]:
                    camera_indexes.append(index)
                    capture.release()
                index += 1
                max_numbers_of_cameras_to_check -= 1
            return camera_indexes
    
        # TODO add MacOS specific implementations
        def add_camera_information(self, camera_indexes: list) -> list:
            platform_name = platform.system()
            cameras = []
    
            if platform_name == 'Windows':
                cameras_info_windows = asyncio.run(self.get_camera_information_for_windows())
    
                for camera_index in camera_indexes:
                    camera_name = cameras_info_windows.get_at(camera_index).name.replace('\n', '')
                    cameras.append({'camera_index': camera_index, 'camera_name': camera_name})
    
                return cameras
    
            if platform_name == 'Linux':
                for camera_index in camera_indexes:
                    camera_name = subprocess.run(['cat', '/sys/class/video4linux/video{}/name'.format(camera_index)],
                                                 stdout=subprocess.PIPE).stdout.decode('utf-8')
                    camera_name = camera_name.replace('\n', '')
                    cameras.append({'camera_index': camera_index, 'camera_name': camera_name})
    
                return cameras
    
        async def get_camera_information_for_windows(self):
            return await windows_devices.DeviceInformation.find_all_async(VIDEO_DEVICES)
    
    
    camera = Camera()
    

    【讨论】:

      【解决方案2】:

      对于 Windows,您可以使用库 pygrabber,它是一个纯 Python 工具,可以从相机捕获照片并使用 DirectShow 和 OpenCV 进行简单的图像处理。它还枚举连接的网络摄像头,如下所示:

      from __future__ import print_function
      from pygrabber.dshow_graph import FilterGraph
      
      graph = FilterGraph()
      print(graph.get_input_devices())
      

      我已修改该库以在 Python 2 和 3 下工作。下载地址: https://github.com/bunkahle/pygrabber

      仅适用于 Python 3 的原始来源: https://github.com/andreaschiavinato/python_grabber

      【讨论】:

        猜你喜欢
        • 2015-08-08
        • 2011-05-03
        • 2021-05-25
        • 1970-01-01
        • 2015-09-20
        • 1970-01-01
        • 2020-09-30
        • 2013-08-26
        • 2013-10-01
        相关资源
        最近更新 更多