最近想写IM聊天室,需要了解一些基础,顺便打算把以前挖的坑给填了。
在去年有水一篇:《Python Opencv暴力获取所有相机》
这份代码是我前年写的,当时是项目需要,语言用的就是Python,由于当时就只知道Python中可以用OpenCV调用摄像头,并且网上千篇一律都是用OpenCV调用摄像头,我不排斥技术,我排斥的是这些文章重复率太高了,甚至里面存在bug,但是没人点出来。(这个bug指的是opencv调用摄像头后无法修改摄像头参数)
如果你用特殊的搜索方式,可能也查不到如何获取摄像头信息,除非你用全英文搜索。
还有个前置知识,摄像头是存在多种协议的,像笔记本一般使用的都是USB摄像头,这个就可以直接用OpenCV调用,但像GIGE网络摄像头,OpenCV就不兼容,并且我觉得OpenCV调用摄像头稳定性很差,但我们追求能用就行,不那么讲究。
我运行的环境都是在Windows10+Python3.7下,并且使用的库也是Windows特有,关于其他操作就不清楚了。
pip install wmi
WMI可以获取Windows系统的硬件信息(硬盘分区、使用情况,内存大小,CPU型号)、当前运行的进程、自启动程序及位置、系统的版本等。
import wmi
info = wmi.WMI()
wql = "Select * From Win32_USBControllerDevice"
for item in info.query(wql):
a = item.Dependent.PNPClass
b = item.Dependent.Name.upper()
if (a.upper() == 'MEDIA' or a.upper() == 'CAMERA') and 'AUDIO' not in b:
print(item.Dependent)
打印信息:
获取这么多信息,缺点很明显就是慢。
通过select语法,可以从进程、驱动中筛选符合的信息。
但是这个库也存在问题,我的笔记本获取到重复的摄像头,但也不排除是我操作有问题。
代码参考来源
这个是C#的库,以前做C#连接摄像头的时候有用到过,功能可以看百度百科AForge。
优点(可能还有别的,暂时没发现):
pip install pythonnet
python执行代码,os.getcwd 就是你的python运行目录,要把上面提到的库拷贝到该目录下的lib文件夹中。
import clr # pip install pythonnet
import sys
import os
# 加载当前文件路径,这样才能使用clr.AddReference
sys.path.append(os.getcwd() + '\lib')
clr.AddReference("AForge")
clr.AddReference("AForge.Video.DirectShow")
from AForge.Video.DirectShow import *
videoDevices = FilterInfoCollection(FilterCategory.VideoInputDevice)
for item in videoDevices:
print(item.Name)
print(item.MonikerString)
videoSource = VideoCaptureDevice(item.MonikerString)
for cap in videoSource.VideoCapabilities:
print(cap.FrameSize, cap.FrameRate)
获取速度非常快。
你可能要问,我只需要"AForge.Video.DirectShow.dll",为什么还要加载"AForge.dll",答案就是pythonnet还有很多bug,有时候检测命名空间会有问题,能运行是好事,报错就要找不停的找缺什么文件。
(如果你的dll文件一起的目录下有.pdb文件,记得要一起拷贝过去)
设置中修改基础分辨率和输出分辨率,基础分辨率>=输出分辨率
基础分辨率是主机分辨率,越大电脑越卡。
输出分辨率是接收方接收到的分辨率,越小越模糊。
启动虚拟摄像头,如果是捕获显示器可能会出现接收失败的情况,这个就需要点击激活视频采集设备,等接受成功就可以取消激活。
我的笔记本上使用4k虚拟摄像头。
没什么好讲的,就是开启前要确保OBS的虚拟摄像头是关闭的,否则会因为冲突无法开启。
pip install pyvirtualcam
import pyvirtualcam
import numpy as np
with pyvirtualcam.Camera(width=1280, height=720, fps=30) as cam:
print(f'Using virtual camera: {cam.device}')
frame = np.zeros((cam.height, cam.width, 3), np.uint8)
while True:
frame[:] = cam.frames_sent % 255
cam.send(frame)
cam.sleep_until_next_frame()
Python的话,像ffmpeg也能够调用摄像头,但是我没有研究过如何用它调用摄像头,留个坑。
C++和C#还有其他能够调用摄像头的库,并且获取摄像头信息,可以用类似第二个方法一样实现。
GIGE摄像头连接,我有用过海康威视和basler相机的库,都是用C#连接。目前是没有这两种相机所以没法测试,basler的pylon库貌似只能兼容自家相机,海康威视的MVS库能兼容basler的但是摄像头参数名称不一样,所以如果做通用的可以考虑只使用海康威视的库。
如果读者知道其他Py连接摄像头的库,可以在评论区留言,或许我之后会写个Demo。