Bewegungsmelder mit AutoIt

Inzwischen haben die Amseln das zweite Gelege erfolgreich aufgezogen und die Jungtiere sind ausgeflogen. Kaum waren die Jungen weg, hat das Männchen schon wieder angefangen das Nest auszubessern. Bis zu fünf Mal am Tag kommt es vor dass eines der Tiere das Nest besucht. Die restliche Zeit passiert nichts. Trotzdem laufen nach wie vor der Online-Stream und die Videoaufnahme. Ich habe zwar Festplattenspeicher um theoretisch die nächsten zwei Monate aufnehmen zu können, jedoch müsste ich dann trotzdem händisch das Material sichten um zu sehen wann die Amseln wieder am Nest waren.

Ich möchte das Problem gerne mit einer Art „Bewegungsmelder“ lösen. Die Streaming-Software die ich letztes Jahr benutzt habe hatte eine solche Funktion. Die Software die ich jetzt verwende hat diese Funktion leider nicht. Da unter Windows der Zugriff auf eine Webcam exklusiv ist, kann ich auch nicht einfach die alte Software des Bewegungsmelders wegen „parallel“ laufen lassen. Dass Drittanbietersoftware die diese Schwäche umgeht nicht zu gebrauchen ist, habe ich ja schon in diesem Artikel erläutert.

Da ich ja sowieso schon AutoIt verwende um die ganzen Aufnahmen zu steuern habe ich mich auf die Suche nach einer Möglichkeit mit AutoIt gemacht. Eine einfache Lösung habe ich nicht gefunden, dafür jedoch die wegweisende Information wie prinzipiell ein Bewegungsmelder funktionieren könnte:

Man schießt zwei Fotos in kurzem Zeitabstand voneinander. Dann subtrahiert man die beiden Bilder. Danach zählt man die nicht schwarzen Pixel im resultierenden Bild. Der so entstandene Zahlenwert kann dann entsprechend interpretiert werden ob viel oder wenig Bewegung zwischen den beiden Fotos stattgefunden hat.

Also mit AutoIt direkt Bilder verarbeiten geht wohl nicht. Aber es existiert ja so ein nettes Tool namens Imagemagick. Damit kann man wunderbar arithmetische Operationen mit Bildern durchführen. Nach etwas experimentieren mit dem Befehl „convert“ bin ich recht bald auf den „compare“-Befehl gestoßen. Der macht eigentlich genau was ich haben wollte – aber nur wenn man ihn mit den richtigen Parametern füttert:


compare -fuzz 5% -highlight-color white -lowlight-color black -metric RMSE 1.png 2.png -compose src out.png

  • “fuzz 5%” führt dazu dass Pixel mit bis zu 5% Abweichung als identisch angesehen warden.
  • „highlight-color white“ färbt alle Pixel die in den beiden Bildern unterschiedlich sind weiß ein
  • „lowlight-color black“ färbt die anderen Pixel schwarz
  • „metric RMSE“ benutzt die Methode der quadratischen Mittelung
  • „1.png“ und „2.png“ sind die beiden Bilder die verglichen werden
  • „compose src“ macht die pixel tatsächlich voll schwarz und weiß, ansonsten scheint der Hintergrund des original Bildes leicht durch (default-Einstellung)
  • „out.png“ ist dann das S/W-Bild das wir haben wollen

Bei ruhigem Bild ohne Bewegung sieht das Ergebnis so aus:

out2

Und hier kann man mit etwas Fantasie noch das Gefieder eines Vogels erkennen:

out

Nun muss nur noch der Zahlenwert irgendwie in eine Variable des AutoIt-Skripts. Ich habe das über eine Abfrage von Stderr gelöst, da „compare“ sein Ergebnis dort hin ausgibt. Mit StringSplit habe ich die Zahl vor dem Komma extrahiert und kann diese zum Vergleich mit einem Schwellwert verwenden.

Func _func_bewegungsmelder()
; Das OBS Fenster in den Vordergrund holen
WinActivate("aktuell - Open Broadcaster Software v0.613b - 32bit")
; Einen Screenshot vom Bereich des Nestes machen
_ScreenCapture_Capture($workingDir & "1.png", $von_x, $von_y, $bis_x, $bis_y)
; eine halbe Sekunde warten
Sleep(500)
; einen zweiten Screenshot machen
_ScreenCapture_Capture($workingDir & "2.png", $von_x, $von_y, $bis_x, $bis_y)
; Aufruf von Imagemagick um die beiden Screenshots zu vergleichen. Das Ergebnis landet in out.png
Local $iPID = Run(@ComSpec & " /c " & '"' & $imageMagickExe & '"' & " -fuzz 5% -highlight-color white -lowlight-color black -metric RMSE 1.png 2.png -compose src out.png", $workingDir, @SW_HIDE, 2+4)
; Eine Sekunde Warten damit auch wirklich die Ausgabe von ImageMagick erfolgt ist
Sleep(1000)
; Ausgabe von ImageMagick speichern
Local $sOutput = StderrRead($iPID)
; String zerlegen ($Wert ist dadurch ein Array)
Local $Wert = StringSplit($sOutput, ".", $STR_NOCOUNT)
; Bei Werten größer 10 ist viel Bewegung im Bild
If $Wert[0] > $bewegungsmelderSchwellwert Then
; großen Screenshot erstellen
_ScreenCapture_Capture($workingDir & "Bewegungsmelder-Screenshots\" & @YEAR & "-" & @MON & "-" & @MDAY & "_" & @HOUR & "_" & @MIN & "_" & @SEC & "_Bewegungsmelder.jpg", 136, 43, 1784, 866)
EndIf
EndFunc

Mit dem Schwellwert, dem Zeitabstand zwischen den beiden Bildern und dem „fuzz“-Faktor von compare kann nun noch etwas gespielt werden. Nach 24 Stunden Testbetrieb hatte ich nur einen „Fehlalarm“ als die Webcam etwas „ruckartig“ die Helligkeit justierte. Außerdem triggerte das Skript auch auf eine Fliege 😀

Hier noch das Skript bei der Arbeit:

Die Goldrandlösung wäre nun auf Basis dieser Informationen automatisch das Videomaterial zu schneiden… und dann noch automatische Uploads zu youtube … mal sehen 🙂

Schreibe hier deinen Kommentar