PY虚拟摄像头
评论 2 热度 752
昨日收到通知,以后上网课可能要开摄像头了...
为了应付一下,打算搞个虚拟摄像头。最开始试了试e2eSoft VCam,有水印,破解不了。然后试了OBS Studio,感觉还行,可以通过滤镜把摄像头弄得很模糊,其他功能也很强大,不过我还想模拟卡顿或者其他效果。最后是用UnityCapture+pyvirtualcam+CV2实现了。
流程
首先是下载UnityCapture,解压并运行Install/Install.bat
然后通过pip安装一些库
pip install opencv-python
pip install pyvirtualcam
pip install numpy
然后新建一个py文件,写入如下代码。
import pyvirtualcam
import numpy as np
import cv2
usevidpath = r"C:\Users\Administrator\Desktop\forcam.mp4"
usecam = 1
class Blocker:
def __init__(self, maxloop, proba_range) -> None:
self.cnt = 1
self.maxindex = 0
self.maxloop = maxloop
self.inloop = False
self.proba_range = proba_range
def execute(self):
if not self.inloop:
proba = np.random.uniform(self.proba_range[0], self.proba_range[1])
if np.random.random() < proba:
self.inloop = True
return 1
return 0
self.cnt += 1
if self.cnt > self.maxloop[self.maxindex]:
self.cnt = 1
self.inloop = False
self.maxindex += 1
if self.maxindex >= len(self.maxloop):
self.maxindex = 0
return 0
return 1
campBlocker = Blocker([8, 0, 4, 9, 0, 4, 4], [0.02, 0.09])
def camprocess():
global cam, frame, lastframe, campBlocker
if frame is None:
cam.send(lastframe)
return
if campBlocker.execute():
frame = lastframe
frame = cv2.resize(frame, (35, 35))
else:
lastframe = frame
frame = cv2.resize(frame, (50, 50))
frame = cv2.resize(frame, (cam.width, cam.height))
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
cam.send(frame)
def vidprocess():
global cam, frame
if frame is None:
return
frame = cv2.resize(frame, (cam.width, cam.height))
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# frame = cv2.flip(frame, 1)
cam.send(frame)
def switchcap():
global usecam, cap
usecam *= -1
print("usecam:", usecam)
if usecam == 1:
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
else:
cap.release()
cap = cv2.VideoCapture(usevidpath)
with pyvirtualcam.Camera(width=320, height=240, fps=5) as cam:
print(f'Using virtual camera: {cam.device}')
if usecam == 1:
cap = cv2.VideoCapture(0)
else:
cap = cv2.VideoCapture(usevidpath)
emptycap = np.zeros((cam.height, cam.width, 3), dtype=np.uint8)
lastframe = emptycap
while True:
sucess, frame = cap.read()
if usecam == 1:
camprocess()
else:
if sucess:
vidprocess()
else:
cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
sucess, frame = cap.read()
# 一键切换录像/视频
if not sucess:
cam.send(emptycap)
frame = emptycap
cv2.imshow('vcam', frame[:,:, [2, 1, 0]])
key = cv2.waitKey(50) & 0xFF
if key == ord('#'):
switchcap()
cam.sleep_until_next_frame()
说明:
- 运行该py文件,默认是会打开摄像头的,并会弹出一个名称为vcam的窗口。在该窗口内部按下'#' (shift+3)即可切换成播放提前录制的视频,再按下又会切换回摄像头。
- 如果视频读取不到,默认会显示黑屏。
- 可在第73行找到
width=320, height=240, fps=5
,修改虚拟摄像头的图像宽高和fps。 - 第5行的
usevidpath
为需要循环播放的视频的路径,该视频的fps最好要与虚拟摄像头的fps一致。 - 在函数
camprocess
内部可对摄像头抓取的图像进行操作。默认只有模糊图像+模拟卡顿
最后使用时,运行py文件,打开会议/上课软件,在设置处选用Unity video capture作为摄像头即可。
橙梓 Windows 10 · Google Chrome
记得我面试的时候就是用到虚拟摄像头,不过我是搞的多机位加过渡
#251 2022-03-19 17:28 回复
Luuljh Windows 10 · FireFox
蛮高级的哇(′Д`)
#252 2022-03-23 17:26 回复