Bewegungserkennung per Webcam
Für ein kleines Projekt stand gerade vor der Aufgabe, Standbilder per Webcam aufzunehmen und zu speichern – aber nur, wenn sich etwas vor der Linse bewegt.
Das klingt zunächst reichlich kompliziert, aber mit den richtigen Werkzeugen ist es tatsächlich verblüffend einfach. Die Werkzeuge der Wahl sind:
- Python – Eine populäre Skriptsprache
- OpenCV – Eine Funktionsbibliothek für Bild-, Videobearbeitung, Mustererkennung u.ä.
Den rechten Weg wies mir Matthias Stein mit seinem Artikel “Motion detection using a webcam, Python, OpenCV and Differential Images“. Die Bewegungserkennung funktioniert so, dass drei kurz nacheinender aufgenommene Bilder übereinandergelegt werden und daraus ein Differenzbild errechnet wird. Dort wo sich nichts verändert hat, ist das Differenzbild schwarz. Stellen, die sich verändert haben, werden weiß. Das führt zu recht eigenwilligen, geisterhaften Bildern, wie man in dem Beispielvideo auf Youtube sehen kann.
Die Lösung
Die Methode musste ich nun nur noch etwas ergänzen. Aus dem Differenzbild errechnet die OpenCV Methode countNonZero die Anzahl, der weißen Pixel. Falls dieser Wert oberhalb eines gesetzten Schwellwertes (sinnvollen Wert ausprobieren) liegt, soll das Bild gespeichert werden. Jetzt muss man nur noch dafür sorgen, dass das Ursprungsbild in Farbe vorliegt und nur zur Differenzberechnung in Schwarz/Weiss gewandelt wird. Et voilá…
Für die interessierten ist hier der Code:
#! /usr/bin/python import time import cv2 def diffImg(t0, t1, t2): d1 = cv2.absdiff(t2, t1) d2 = cv2.absdiff(t1, t0) return cv2.bitwise_and(d1, d2) print "Start Capturing" cam = cv2.VideoCapture(0) # Threshold for minimum movement threshold = 130000 targetdir = './' winName = "MovementIndicator" cv2.namedWindow(winName, cv2.CV_WINDOW_AUTOSIZE) # Read three images first: colorimg = cam.read()[1] t_minus = cv2.cvtColor(colorimg, cv2.COLOR_RGB2GRAY) t = cv2.cvtColor(colorimg, cv2.COLOR_RGB2GRAY) t_plus = cv2.cvtColor(colorimg, cv2.COLOR_RGB2GRAY) start = time.time() while True: dimg=diffImg(t_minus, t, t_plus) cv2.imshow( winName, dimg ) # save picture, when movement above threshold print cv2.countNonZero(dimg) if cv2.countNonZero(dimg) > threshold: timestamp = round(time.time() - start) filename = targetdir + str(timestamp) + ".jpg" cv2.imwrite(filename, colorimg) # Read next image colorimg = cam.read()[1] t_minus = t t = t_plus t_plus = cv2.cvtColor(colorimg, cv2.COLOR_RGB2GRAY)