diff --git a/content/projekt/PimpedWebcam.md b/content/projekt/PimpedWebcam.md new file mode 100644 index 0000000..bf89c74 --- /dev/null +++ b/content/projekt/PimpedWebcam.md @@ -0,0 +1,179 @@ +--- +title: Pimp my webcam (stream) +author: kaqu +status: Aktiv +difficulty: einfach +time: ~1h +date: 2020-05-07 +image: /images/PimpedWebcam/webcam_modified.jpg +keywords: webcam, opencv, akvcam +--- + + +## Motivation ## +In unserer wöchentlichen Videokonferenz ('Corona') hat Kresse vor ca. 10 Tagen etwas über 'webcamoid' erzählt. +Das klang interessant! Gleich am nächsten Tag habe ich mir die Installation (auf Mint 19.3) vorgenommen, scheiterte aber +(nach erfolgreichem make) zunächst am 'make install' für akvcam mit einer obskuren Fehlermeldung +(file crypto irgendwas not found???). +Also wieder deinstalliert mit 'make uninstall', das klappte einwandfrei. Trotzdem gab ich zunächst auf ... +Am übernächsten Tag hatte ich mir vorgenommen, die Sache genauer zu untersuchen. Wie sich herausstellte, +war bis auf diese 'überflüssige' Fehlermeldung alles ok! + +Das Kernelmodul 'akvcam' installiert zwei zusätzliche - virtuelle - Video-Devices, eins zum Reinschreiben ('output'), +eins zum Auslesen ('capture'). Wenn man jetzt den originalen Webcam-Stream mit einem Programm entgegen nimmt +und ggf. verfremdet ('pimped') kann man diesen an den Videoport zum Reinschreiben übergeben und an den +Videoport zum Auslesen ('virtual camera') einen beliebigen Client für die Wiedergabe hängen! + +Streamflow also wie folgt: + +Webcam->/dev/video(x)->Bsp. 'webcamoid' u.ä.->/dev/video(n)->akvcam->/dev/video(n+1)->z.Bsp. Browser (Jitsi) + +Zum Testen nehme ich 'guvcview', danach kann man mit dem Browser (WebRTC) dieses virtuelle Gerät ebenfalls nutzen +(Nicht: Parallel!). Komplett störungsfrei funktioniert z.Bsp. Jitsi derzeit (5/2020) im Chromium-Browser, in Brave +geht nur die Kachelanzeige, im Firefox klappt es mal/mal nicht ... + +In der Ausgangskonstellation habe ich 'webcamoid' getestet. Nett (viele parametrierbare Effekte), aber irgendwie +sinnlos! Wie wäre es stattdessen mit eigenem 'Aufbrezeln' mittels OpenCV/Python? +In der Nutzungsanleitung zu 'akvcam' wird gezeigt, wie man (testweise) Streams an das Videodevice schicken kann, +d.h. so einen Stream müsste man nur selbst produzieren, ins Device schreiben - et voilà, ein selbstgebauter +'custom' Stream! + +Ein wenig Internet-Recherche ergab: Video Frames können aus OpenCV/Python über stdout als Bytes direkt ausgegeben +werden (ja, auch auf die Konsole ... ;). Damit stehen einfachen Manipulationen Tür und Tor offen! + +Hier mal die Resultate, zwecks Vergleich + +vorher: + + +und nachher: + + +Hint: Die Kamera war wohl abgeklebt ... + + +## Installationshinweise ## +1. Zunächst muß akvcam installiert werden (https://github.com/webcamoid/akvcam). Einfach mit git clonen oder +als ZIP runterladen (dann entpacken im eigenen Benutzerverzeichnis). +2. Verzeichnis umbenennen auf akvcam +3. cd ~/akvcam/src +4. make (Übersetzen sollte einwandfrei durchlaufen ...) +5. sudo make install (hier kommt die überflüssige Fehlermeldung) +6. sudo depmod -a +7. ls /lib/modules/$(uname -r)/extra/akvcam.ko* (Prüfen, ob im Zielverzeichnis angekommen ...) +8. sudo mkdir -p /etc/akvcam (Konfigurationsdatei erstellen) +9. sudo touch /etc/akvcam/config.ini +10. config.ini editieren (Daten siehe https://github.com/webcamoid/akvcam/blob/master/ports/ci/travis/config.ini) +11. sudo chmod -vf 600 /etc/akvcam/config.ini +12. ls /dev/video* (Bekannte Videoports des eigenen Rechners merken) +13. sudo modprobe videodev +14. sudo insmod akvcam.ko (Jetzt Kernelobject aktivieren) +15. ls /dev/video* (Neu hinzu gekommene - virtuelle - Videoports gehören zur akvcam) +16. cat /dev/urandom > /dev/video4 (White noise kann z.Bsp. mit 'guvcview' getestet werden) +17. cat /dev/video5 (Test: Stream von virtuellem Gerät auf Konsole ausgeben ...) +18. sudo apt install virtualenv (Falls für Python keine virtuellen Umgebung zur Verfügung stehen ...) +19. virtualenv cv --python="python3" (Ansonsten eins für OpenCV vorbereiten) +20. source cv/bin/activate (Aktivieren nicht vergessen!) +21. pip3 install opencv-python (Nur in die virtuelle Umgebung OpenCV installieren) +22. python3 -c "import cv2" (Und testen ...) + +## Programmaufteilung ## +Da ich die (virtuelle) Kamera nicht immer aktiv haben möchte (wer weiss, vielleicht war die 'crypto' +Fehlermeldung das letzte Röcheln des integrierten Bitcoin-Schürf-Clients ...), habe ich ein bash-Script +vorgesehen mit folgendem Ablauf: + +1. akvcam Kernelmodul aktivieren +2. 'cv' python environment aktivieren +3. Python Script laufen lassen mit Ausgabeumleitung an ersten virtuellen Videoport +4. Extern --> Webcam-Applikation (guvcview, browser etc.) an zweiten virtuellen Videoport +5. Extern --> Webcam-Applikation besser als erstes wieder stoppen ... +6. Benutzerabbruch im Script erfolgt mit Strg-C +7. akvcam (die virtuellen Kameras) werden wieder entladen (System wieder sauber!) + +virtcam.sh: + + echo "Installing video4 (output) / video5 (capture) virtual devices ..." + cd ~/akvcam/src + sudo modprobe videodev + sudo insmod akvcam.ko + echo "Starting 'stream modifier' application ..." + echo "Activating (cv) environment ..." + source ~/cv/bin/activate + cd ~/cv + ls /dev/video? + python3 funcam.py > /dev/video4 # video4 is output device -> video4 is capture + echo "Removing virtual (camera) devices ..." + sudo rmmod akvcam.ko + echo "Done." + +Die eigentliche Action erfolgt im Python-Script ('funcam.py'): + + import numpy as np + import datetime, time + import sys + import cv2 + + # Hint: print() to stderr (fh#2) as the actual video stream goes to stdout (fh#1)! + print("funcam started ...",file=sys.stderr) + + cap = cv2.VideoCapture(0) # TODO: You have to verify, if /dev/video0 is your actual webcam! + if not cap.isOpened(): # if not open already + cap.open() #make sure, we will have data + # Adjust channel resolution & use actual + cap.set(3, 640) + cap.set(4, 480) + + while(cap.isOpened()): + try: + ret, frame = cap.read() + if ret==True: + + frame4 = cv2.cvtColor(frame.copy(),cv2.COLOR_BGRA2RGB) # Correct color space + + # Now: The fun stuff! ------------------------------------------------------------------------------------------- + + # ... ... + + # As a sample, we display the current time + t = time.strftime("%H:%M:%S", time.localtime()) + cv2.putText(frame4, t, (505,472), (cv2.FONT_HERSHEY_DUPLEX), 1.4, (0, 0, 0), 4, cv2.LINE_AA) + + # End of fun stuff! --------------------------------------------------------------------------------------------- + + # Write raw output (pipe/redirect to video device externally!) + sys.stdout.buffer.write(frame4.tobytes()) + else: + break + except: + break + + cap.release() + print("\nfuncam terminated.",file=sys.stderr) + + +## Arbeitsablauf ## +1. Bash Script 'funcam.sh' laufen lassen (in Terminalfenster) +2. Client starten, für Videokonferenzen (z.Bsp. mit Jitsi) Browser mit passendem Link starten +3. ... Blabla, Bullshit ... Bingo! ... +4. Client beenden +5. Im Terminalfenster Script ordentlich beenden (mit Strg-C!) + +Und hier ein klein wenig 'Live' zum Anfixen mit einfachen Effekten: + + +## Was bleibt zu tun? ## +- Projekt auf unser git schmeissen +- Parametrierbarkeit herstellen (Koordinaten, Daten etc.) +- Modularisieren, Refactoring ... +- Virtuelle Webcam (video) automatisch ermitteln (im Bash-Script) +- Greenscreen zwecks Einblendung beliebiger Hintergründe ermöglichen +- Andere Auflösungen - insbesondere 1280x720 - möglich? +- ... whatever ... diff --git a/static/images/PimpedWebcam/webcam_blank.jpg b/static/images/PimpedWebcam/webcam_blank.jpg new file mode 100644 index 0000000..d85ec44 Binary files /dev/null and b/static/images/PimpedWebcam/webcam_blank.jpg differ diff --git a/static/images/PimpedWebcam/webcam_fun.webm b/static/images/PimpedWebcam/webcam_fun.webm new file mode 100644 index 0000000..31962a0 Binary files /dev/null and b/static/images/PimpedWebcam/webcam_fun.webm differ diff --git a/static/images/PimpedWebcam/webcam_modified.jpg b/static/images/PimpedWebcam/webcam_modified.jpg new file mode 100644 index 0000000..d22dbf7 Binary files /dev/null and b/static/images/PimpedWebcam/webcam_modified.jpg differ