You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python Tkinter中获取摄像头名称(含虚拟摄像头)并实现选看画面?

解决摄像头名称枚举与实时画面显示问题

OpenCV本身无法直接获取摄像头的设备名称,要识别包括虚拟摄像头在内的所有设备并获取其名称,可借助Windows的DirectShow接口,通过pywin32库封装调用(无需直接编写Windows API代码)。以下是完整实现方案:

1. 安装依赖库

执行以下命令安装所需包:

pip install pywin32 opencv-python

2. 完整实现代码

import cv2
import tkinter as tk
from tkinter import ttk
import win32com.client

# 枚举所有摄像头(包括虚拟摄像头)并获取名称
def enumerate_cameras():
    camera_dict = {}
    # 初始化DirectShow设备枚举器
    enumerator = win32com.client.Dispatch("SystemDeviceEnum")
    video_category = enumerator.CreateClassEnumerator("{860BB310-5D01-11D0-BD3B-00A0C911CE86}", 0)
    
    if video_category is None:
        return camera_dict
    
    # 遍历所有视频输入设备
    while True:
        try:
            device = video_category.Next()
            friendly_name = device.Name
            # 获取设备路径(用于OpenCV打开)
            moniker = device.Moniker
            prop_bag = moniker.BindToStorage(None, None, "{55272A00-42CB-11CE-8135-00AA004BB851}")
            device_path = prop_bag.Read("DevicePath")
            
            # 测试设备是否可打开(排除不可用的设备)
            cap = cv2.VideoCapture(device_path, cv2.CAP_DSHOW)
            if cap.isOpened():
                cap.release()
                camera_dict[friendly_name] = device_path
        except StopIteration:
            break
    return camera_dict

# 更新摄像头画面
def update_frame(cap, label):
    ret, frame = cap.read()
    if ret:
        # 转换颜色空间:OpenCV是BGR,Tkinter需要RGB
        frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        # 转成Tkinter可用的PhotoImage
        img = tk.PhotoImage(width=frame_rgb.shape[1], height=frame_rgb.shape[0])
        img.put(data=frame_rgb.tobytes(), format="RGB")
        label.config(image=img)
        label.image = img  # 保留引用避免被垃圾回收
    # 每隔10ms更新一次
    label.after(10, update_frame, cap, label)

# 选择摄像头后的回调函数
def on_camera_selected(event):
    selected_name = camera_menu.get()
    device_path = cameras[selected_name]
    
    # 关闭之前的摄像头(如果存在)
    if hasattr(on_camera_selected, 'cap'):
        on_camera_selected.cap.release()
    
    # 打开选中的摄像头
    on_camera_selected.cap = cv2.VideoCapture(device_path, cv2.CAP_DSHOW)
    # 启动画面更新
    update_frame(on_camera_selected.cap, video_label)

# 初始化Tkinter窗口
root = tk.Tk()
root.title("摄像头实时画面")
root.geometry("640x520")

# 枚举摄像头
cameras = enumerate_cameras()
if not cameras:
    tk.Label(root, text="未检测到任何摄像头").pack(pady=20)
    root.mainloop()
    exit()

# 创建下拉菜单
camera_menu = ttk.Combobox(root, values=list(cameras.keys()), state="readonly")
camera_menu.current(0)
camera_menu.pack(pady=10)
camera_menu.bind("<<ComboboxSelected>>", on_camera_selected)

# 用于显示视频的标签
video_label = tk.Label(root)
video_label.pack()

# 初始化显示第一个摄像头的画面
initial_path = cameras[list(cameras.keys())[0]]
on_camera_selected.cap = cv2.VideoCapture(initial_path, cv2.CAP_DSHOW)
update_frame(on_camera_selected.cap, video_label)

root.mainloop()

# 程序结束时释放摄像头
if hasattr(on_camera_selected, 'cap'):
    on_camera_selected.cap.release()

代码说明

  • 枚举摄像头:通过win32com.client调用DirectShow枚举器,筛选视频输入设备,获取设备的友好名称和设备路径,并用OpenCV测试设备是否可用。
  • 下拉菜单:使用ttk.Combobox创建下拉选择框,绑定选择事件以切换摄像头。
  • 实时画面显示:将OpenCV捕获的BGR帧转换为RGB格式,转为Tkinter的PhotoImage后显示,通过after方法定时更新画面。
  • 设备兼容性:使用cv2.CAP_DSHOW作为OpenCV的捕获后端,更好地支持虚拟摄像头。

内容的提问来源于stack exchange,提问作者333pwn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 20:12:03