Webcambilder einlesen und bearbeiten mit Python und OpenCV
Mit Python Webcambilder einlesen und bearbeiten, das ist einfacher als man denkt. Wer die Python-Kurse in den vergangenen Ausgaben von freiesMagazin verfolgt hat, dem wird es leicht fallen, die nachfolgend gezeigten Beispiele nachzuvollziehen und für die eigenen Bedürfnisse anzupassen und zu verbessern. Zunächst soll gezeigt werden, wie man ein Livebild am Bildschirm ausgibt. Anschließend folgt dann ein kleines Programm für die Videoüberwachung, das immer dann den Videostream abspeichert, wenn im Bild eine Bewegung festgestellt wird. Genutzt wird bei beiden Beispielen eine Programmbibliothek, mit der man viel mehr tun kann, als nur Webcambilder aufzeichnen: OpenCV.
Einleitung
OpenCV (Open Source Computer Vision) ist eine von Intel ins Leben gerufene Programmbibliothek, die Funktionen zum Einlesen von Kamerabildern für die Livebild-Manipulation, sowie für Objekterkennung und Objektverfolgung enthält. Über 2000 verschiedene, optimierte Algorithmen sind inzwischen verfügbar. Geschrieben wurde OpenCV in C und C++, aber es gibt auch eine Schnittstelle zu Python, welche die Programmierung besonders einfach und übersichtlich macht. Ein Abstecher auf die OpenCV-Projektseite lohnt sich auf jeden Fall. Auch auf YouTube findet man Beispielvideos, welche die Möglichkeiten von OpenCV eindrucksvoll demonstrieren.
Vorbereitung
Zunächst muss man das Paket python-opencv
über die Paketverwaltung installieren. Eigene Versuche haben gezeigt, dass es bei Version 2.0 des OpenCV-Moduls, das noch in den Paketquellen von Ubuntu 10.04 LTS enthalten ist, zu einem Fehler beim Import des cv
-Moduls kommt (»ImportError: No module named cv«). Eine Lösung des Problems ist in der OpenCV-Installationsanleitung beschrieben. Ab Ubuntu 10.10 gibt es keine Probleme mehr.
Livebild am Bildschirm anzeigen
Das folgende kleine Programm öffnet ein Fenster am Bildschirm und gibt das aktuelle Livebild aus. Durch Drücken der Taste »Q« wird das Programm wieder beendet.
#! /usr/bin/python # -*- coding: utf-8 -*- # Livebild ausgeben # Autor: Wolfgang Wagner # Datum: 18.05.2011 import cv KAMERA_NR = 0 cam = cv.CaptureFromCAM(KAMERA_NR) taste = 0 while taste <> ord("q"): bild = cv.QueryFrame(cam) cv.ShowImage("Livebild", bild) taste = cv.WaitKey(2)
Das Programm beginnt mit dem Import des OpenCV-Moduls in der Zeile import cv
. Danach erfolgt die Initialisierung der Webcam mit cam = cv.CaptureFromCAM(KAMERA_NR)
. Als nächstes kommt eine Schleife, die solange durchlaufen wird, bis die Variable taste
den Code des Zeichens q
enthält. Mit bild = cv.QueryFrame(cam)
holt man den aktuellen Frame (das aktuelle Bild) aus dem Videostream und mit cv.ShowImage("Livebild", bild)
gibt man dieses Bild in einem eigenen Fenster aus. Mit taste = cv.WaitKey(2) % 256
wird zwei Millisekunden gewartet und dann das untere Byte des zurückgegebenen Codes an die Variable taste
übergeben. Die zwei Millisekunden Wartezeit sind notwendig, um eine Aktualisierung der Bildschirmausgabe zu ermöglichen.
Videoüberwachung
Das erste Programmbeispiel soll nun zu einer einfachen Videoüberwachung ausgebaut werden. Dazu wandert die Hauptroutine des Programms in eine eigene Funktion. Hinzu kommen noch eine Funktion für die Generierung eines Dateinamens (um das aufgenommene Video abspeichern zu können) und eine Funktion für die Auswertung von Parametern, die dem Programm beim Start eventuell mitgegeben worden sind.
Imports
Am Programmanfang werden zusätzlich zum Modul cv
noch die Funktion localtime
für die Abfrage von Datum und Uhrzeit und die Funktion argv
für das Auslesen der Programmparameter importiert:
import cv from time import localtime from sys import argv
Funktion Dateiname
Durch den Aufruf der Funktion localtime
erhält man die aktuelle Uhrzeit. Aus den ersten sechs Elementen des zurückgegebenen Tupels wird dann der Ausgabestring zusammengesetzt:
- Jahr [4-stellig]
- Monat [1..12]
- Tag [1..31]
- Stunde [0..31]
- Minute [0..59]
- Sekunde [0..61]
- Wochentag [0..6, 0=Montag]
- Tag des Jahres [1..366]
- Status der Sommerzeit [0,1,-1]
def Dateiname(): '''Erstellt einen Dateinamen aus Datum und Uhrzeit''' zeit = localtime() s = "%04i-%02i-%02i-%02i-%02i-%02i.avi" % \ (zeit[0],zeit[1],zeit[2],zeit[3],zeit[4],zeit[5]) return s
Funktion ParameterLesen
Die Funktion ParameterLesen
wertet die beim Programmstart mitgegebenen Parameter aus. Als Ergebnis gibt sie ein Dictionary zurück, das die einzelnen Programmparameter enthält. Wurden keine Parameter angegeben, enthält das Dictionary die voreingestellten Werte. Bei einer Falscheingabe wird ein Infotext ausgegeben und die Funktion liefert 0
zurück. Eine Prüfung der eingegebenen Werte findet nicht statt. Man könnte beispielsweise einen ungültigen Pfad eingeben oder auch einen Text, wenn eine Zahl erwartet wird und würde damit das Programm zu Absturz bringen. Hier wäre also noch Platz für Verbesserungen. Zum Testen des Programms dürfte diese einfache Routine aber ausreichend sein.
def ParameterLesen(): '''Wertet die eingegebenen Parameter aus''' INFOTEXT = """Falsche Parametereingabe Aufruf: Videoueberwachung.py [OPTION] <WERT> [OPTION] <WERT>... Moegliche Optionen:" -p Ausgabepfad (Vorgabe: ./) -knr Nummer der Kamera, die erste gefundene Kamera hat die Nummer 0 (Vorgabe: 0) -ts Schwellwert der Threshold-Funktion (gueltig: 0 bis 255, Vorgabe: 50) -tm Maximalwert der Threshold-Funktion (gueltig: 0 bis 255, Vorgabe: 255) -start Durchschnittlicher Pixelwert, bei dem die Aufnahme startet (gueltig: 0.0 bis 255.0, Vorgabe: 0.1 -stop Durchschnittlicher Pixelwert, bei dem die Aufnahme gestoppt wird (gueltig: 0.0 bis 255.0, Vorgabe: 0.01 -bbs Bilder bis Stop: Wird bbs Bilder lang keine Bewegung mehr fest- gestellt, stoppt die Aufnahme (gueltig: 1 bis n, Vorgabe: 40) """ VORGABE = {'-p' : "./", '-knr' : "0",'-ts' : "50", \ '-tm' : "255",'-start' : "0.1", '-stop' : "0.01", \ '-bbs' : "40"} Parameter = VORGABE.copy() if len(argv) < 2: for i in xrange(1,len(argv)-1,2): if Parameter.has_key(argv[i]): Parameter[argv[i]] = argv[i+1] else: print INFOTEXT return 0 return Parameter else: return VORGABE
Zu erwähnen wäre hier der Aufruf Parameter = VORGABE.copy()
, mit dem vom Vorgabe-Dictionary eine Kopie erstellt wird. Die einfache Zuweisung Parameter = VORGABE
ist hier nicht möglich, denn sie erzeugt nur eine Kopie des Zeigers auf die Daten und nicht eine Kopie der Daten selbst. Änderungen an der Kopie hätten auch eine Änderung am Original zur Folge.
Ausgewertet wird die Variable argv
, in der nach dem Programmstart alle Eingabeparameter aufgelistet sind. Als erstes Element ist immer der Programmname abgelegt, deshalb beginnt die Auswertung erst beim zweiten Element.