von.wert schrieb:
Manches kann man vielleicht auf anderem Wege in Software erreichen (das, was seahawk1986 mit Tricksen meint), aber mindestens umständlicher und zeitaufwendiger. Ob das in Verbindung mit Zoom funktioniert, ist eine ganz andere Frage.
Dank vorhandener Abstraktionen ist ein Prototyp recht schnell fertig (wenn man da weiter optimieren will, kann man natürlich viel Zeit versenken) - ich habe das für einen ersten Versuch so gemacht:
sudo apt install v4l2loopback-dkms python3-opencv python3-venv python3-wheel v4l-utils
mkdir ~/replace_webcam_bg
cd ~/replace_webcam_bg
python3 -m venv .venv --system-site-packages
. .venv/bin/activate
pip install -U pip
pip install -U pyfakewebcam
Jetzt aktivieren wir das Modul für die virtuelle Webcam und lassen es ein Device anlegen:
sudo modprobe v4l2loopback devices=1
Damit sollte es jetzt neben der Webcam ein Loopback-Device geben, also sollte man z.B. sowas sehen können:
$ v4l2-ctl --list-devices
Dummy video device (0x0000) (platform:v4l2loopback-000):
/dev/video2
VirtualBox Webcam - USB2.0 HD U (usb-0000:00:1f.4-1):
/dev/video0
/dev/video1
/dev/media0
Damit ist die Webcam /dev/video0 und die virtuelle Webcam /dev/video2. Damit man mit Benutzerrechten auf die Kamera zugreifen darf, muss der Nutzer Mitglied in der Gruppe video
sein.
Wir suchen uns außerdem noch ein Hintergrundbild aus und legen das als background.jpg ab - z.B.:
wget https://fanart.tv/fanart/movies/583/moviebackground/monty-pythons-life-of-brian-5a927a38c9b8f.jpg -O background.jpg
Jetzt brauchen wir ein Python-Skript background_removal.py, das die Webcam ausliest, die Differenz zu einem Referenzbild als Maske berechnet und einen Hintergrund platziert und die Daten weiterreicht - in misbah4064/backgroundRemoval gibt es eine brauchbare Vorlage, die mit kleinen Anpassungen ein statische Hintergrundbild statt einem Video nutzt und das Bild für die virtuelle Webcam rausschreibt:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 | #!/usr/bin/env python3
# Background Removal using Python and OpenCV. Replacing the background with an image
import cv2
import pyfakewebcam
import numpy as np
WEBCAM_NUM = 0
VIRTUAL_CAM = '/dev/video2'
def resize(dst,img):
width = img.shape[1]
height = img.shape[0]
dim = (width, height)
resized = cv2.resize(dst, dim, interpolation = cv2.INTER_AREA)
return resized
video = cv2.VideoCapture(WEBCAM_NUM)
video.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
video.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
success, ref_img = video.read()
flag = 0
camera = pyfakewebcam.FakeWebcam(VIRTUAL_CAM, 640, 480)
bg = cv2.imread('background.jpg')
bg = resize(bg,ref_img)
while(1):
success, img = video.read()
if flag==0:
ref_img = img
# create a mask
diff1=cv2.subtract(img,ref_img)
diff2=cv2.subtract(ref_img,img)
diff = diff1+diff2
diff[abs(diff)<13.0]=0
gray = cv2.cvtColor(diff.astype(np.uint8), cv2.COLOR_BGR2GRAY)
gray[np.abs(gray) < 10] = 0
fgmask = gray.astype(np.uint8)
fgmask[fgmask>0]=255
#invert the mask
fgmask_inv = cv2.bitwise_not(fgmask)
#use the masks to extract the relevant parts from FG and BG
fgimg = cv2.bitwise_and(img,img,mask = fgmask)
bgimg = cv2.bitwise_and(bg,bg,mask = fgmask_inv)
#combine both the BG and the FG images
dst = cv2.add(bgimg,fgimg)
cv2.imshow('Background Removal',dst)
#write image to virtual cam
camera.schedule_frame(cv2.cvtColor(dst, cv2.COLOR_BGR2RGB))
key = cv2.waitKey(5) & 0xFF
if ord('q') == key:
break
elif ord('d') == key:
flag = 1
print("Background Captured")
elif ord('r') == key:
flag = 0
print("Ready to Capture new Background")
cv2.destroyAllWindows()
video.release()
|
Dann das Skript starten:
~/replace_webcam_bg/.venv/bin/python3 background_removal.py
Der Hintergrund sollte möglichst einfarbig sein (dann fallen kleine Wackler und Positionsänderungen der Webcam nicht auf) und einen hohen Kontrast zu Kopf und Kleidung bieten - eine dunkle Wolldecke ist da für Mitteleuropäer im Winter keine schlechte Wahl. Die Ausleuchtung sollte möglichst konstant sein (am besten wie bei Greenscreen-Aufnahmen generell Vordergrund und Hintergrund getrennt ausleuchten, und das am besten von zwei Seiten, um Schattenwürfe zu vermeiden - https://www.lighting-academy.com/index.php?id=838 für Anregungen, wie man das mit Dingen umsetzen kann, die man vielleicht sogar schon im Haushalt hat.
Beim Starten des Skripts macht das Programm ein Bild, das als Referenzbild zur Differenzberechnung dient - man sollte also aus dem Bild der Webcam treten, bevor man das Programm startet. Mit
R kann man nur das Hintergrundbild darstellen lassen, mit
D kann man das aktuelle Bild von der Webcam als neues Referenzbild festlegen (z.B. nützlich, wenn sich die Beleuchtung oder der Hintergrund geändert hat). Mit
Q kann man das Skript beenden.
Wenn das Skript läuft den Zoom-Client starten und die virtuelle Webcam auswählen (die normale Webcam lässt sich nicht nutzen, solange das Skript läuft)