Raspberry Web-Cam          

von Frank Behlich        

Elektronik-Labor  Projekte  Mikrocontroller  Raspberry     





Eine Raspberry-Cam ist teuer und nicht unbedingt nötig, da Python und seine Zusatz-Bibliotheken eigentlich alles möglich machen. Das Modul OpenCv ist mächtig und mit diesem kann auch eine Web-Cam etc. ausgelesen werden. Ich zeige die Anwendung von der Kommandozeile aus und in einer Tkinter-Gui. Für die Kommandozeile langt das OpenCv-Modul. Für eine Tkinter-Gui werden zwei
weitere Pakete benötigt:

Fehlende Pakete werden mit dem Paketmanager "apt-get" installiert - eine Internetverbindung ist Voraussetzung !
 _______________________________________________________________________________________                                                                                           |                                                                                       |
|Benötigte Pakete: |
|sudo apt-get install python-opencv --> für Ausgabe Kommandozeile und Tkinter |
|sudo apt-get install python-imaging-tk --> Tkinter |
|sudo apt-get install python-imaging --> Tkinter |
|_______________________________________________________________________________________|

Falls die Installation geklappt hat, kann man schauen, ob die Kamera erkannt wurde. Auf der Kommandozeile kann man mit "lsusb" die angeschlossenen und erkannten USB-Geräte auslesen.
 _____________________________________________________________________________
| |
|lsusb-Ausgabe meines Raspberry: |
|Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. |
|Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub |
|Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. |
|Bus 001 Device 008: ID 0ac8:303b Z-Star Microelectronics Corp. ZC0303 Webcam |
|Bus 001 Device 007: ID 046d:c52b Logitech, Inc. Unifying Receiver |
|_______________________________________________________________________________________|

Ich habe schon alle möglichen Webcam's angeschlossen und jede wurde erkannt und konnte ausgelesen werden. Meine gezeigte ist ein älteres "Billigmodell" und hat sogar Infrarot-LED's und ein Micro. Damit könnte man ein "Babyschlafvideofon" machen. Mal sehen ob, ich es vor dem achtzehnten Geburtstag meiner Kinder hin bekomme :-). Die Auflösung der unterschiedlichen Cam's sind natürlich für ein verzögerungsfreies Bild ausschlaggebend und somit ist eine ältere bzw. preiswertere Kamera von Vorteil, da es so auf dem Raspberry flüssiger läuft. Dies lässt sich natürlich auch durch die Auflösung und Wiederholrate anpassen.


Start von der Kommandozeile

#! /usr/bin/env python
# -*- coding: utf-8

import cv2

cap = cv2.VideoCapture(-1)
while(True):
retval, frame = cap.read()
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()

Nun sollte ein Fenster aufgehen und bei geringer Auflösung der Kamera ein ruckelfreies Bild erscheinen. Da ich meinen Raspberry über ssh und xrdp laufen lasse, könnte man schon fast von einer Videoüberwachung über das Netz sprechen.



Hier überwache ich die Puppe meiner Tochter - die scheint auch nicht zu schlafen !


Umsetzung in einer Tkinter-Gui

#web_cam_cv2_tk.py Webcam mit opencv2 und tkinter
#! /usr/bin/env python
# -*- coding: utf-8

import Tkinter as tk
from PIL import Image, ImageTk
import cv2

WIDTH = 320
HEIGHT = 240
CAM = -1

class Cam(tk.Label):

UPDATE_TIME = 10
PROPID_WIDTH = 3
PROPID_HEIGHT = 4

def __init__(self, root, width, height, cam):
tk.Label.__init__(self, root)
self.root = root
self.width = width
self.height = height
self.cam = cv2.VideoCapture(CAM)

def run(self):
if self.cam.isOpened():
self.tk_image = ImageTk.PhotoImage(image = self.resize_image(
Image.fromstring("RGB", (int(self.cam.get(self.PROPID_WIDTH)),
int(self.cam.get(self.PROPID_HEIGHT))), self.cam.read()[1], "raw", "BGR")))
self.config(image = self.tk_image)
else:
self.config(width=20, height=5,
text = "NO CAM", font="Arial 20")
self.after(self.UPDATE_TIME, self.run)

def resize_image(self, img):
img_width, img_height = img.size
if self.height >= self.width:
img_height = img_height * self.width // img_width
img_width = self.width
else:
img_width = img_width * self.height // img_height
img_height = self.height
return img.resize((img_width, img_height))

def release(self):
self.cam.release()
self.root.destroy()

if __name__ == '__main__':

root = tk.Tk()
cam = Cam(root, WIDTH, HEIGHT, CAM)
cam.pack()
cam.run()
root.title("WEB-CAM")
root.protocol("WM_DELETE_WINDOW", cam.release)
root.mainloop()


Nachtrag: Zeitraffer von Frank Behlich

Hier ein Script zur Zeitrafferaufnahme mit der Raspberry-WebCam. Beim Laufen des Programmes wird eine abspielbare Datei erstellt ("out.avi").

# stop_motion_cam_raspberry.py --> Zeitrafferaufnahmen
#! /usr/bin/env python
# -*- coding: utf-8
import time
from datetime import timedelta, datetime
import numpy as np
import cv2

stop_time = datetime.now() + timedelta(minutes=10) # bei 10min = ca 25sec
cam = cv2.VideoCapture(-1) # hours u. seconds auch moeglich
writer = cv2.VideoWriter("out.avi", 4, 24, (int(cam.get(3)),
int(cam.get(4))))
old_frame = []
if cam.isOpened():
try:
while datetime.now() < stop_time:
time.sleep(1)
new_frame = cam.read()[1]
if np.array_equal(old_frame, new_frame):
raise RuntimeError("cam disconnected")
writer.write(new_frame)
old_frame = new_frame
except KeyboardInterrupt:
print "capture stopped"
except RuntimeError as error:
print error
else:
print "capture finished"
finally:
cam.release()
writer.release()
else:
print "no cam"


Nachtrag 12.11.15: Hier ein kleines Video vom Sonnenaufgang, aufgenommen mit einer alten Webcam und dem Raspberry.




Sonnenaufgang.avi


Raspberry Web-Cam als Bewegungsmelder von Frank Behlich

Ganz ohne äußere Beschaltung lässt sich der Raspberry zur Raumüberwachung nutzen. Das Script ist auf Basis des Zeitrafferscriptes und speichert bei der Erkennung einer Bewegung ein Bild der derzeitigen Überwachungssituation. Man sollte vor dem Einsatz mit der Variable („SENSITIVITY“) herumspielen und seine Kamera auf das verbundene  Überwachungsszenario einstellen. Der Zeitintervall („UPDATE_INTERVALL“) der Endlosschleife ist natürlich auch eine Größe mit der sich die Empfindlichkeit des „Bewegungsmelder“ erhöhen lässt, doch hierbei muss auf die Leistungsfähigkeit des Raspberry geachtet werden, denn die Speicherung und der Vergleich der „Frames“ benötigt einiges an Leistung.

Beim ersten Start des Scriptes ist es ratsam das Speichern der Bilder auszukommentieren und erst nach ausgiebigen Testen der eigene Gegebenheiten es wieder zuzulassen. Bei falscher Einstellung kommen einige Bilder zusammen!! Der Befehl  „print „detected““ zeigt die Treffer an und lässt sich natürlich erweitern („print „detected“, changes), damit die Feinjustierung einfacher wird.

Die Raspian Version muss „Jessie“ sein, denn sonst ist Python nicht aktuell und Numpy wirft eine Fehlermeldung. In dem folgenden Script werden die Bilder in dem Ordner „detected“ gespeichert. Dieser muss natürlich vorher angelegt sein!!

Der Bewegungsmelder hat seine Grenzen, denn bei sich schnell ändernden Lichtverhältnissen wird er natürlich auch ansprechen und bei Dunkelheit reagiert er nur auf die Änderung der Helligkeit im Raum. Hier könnte eine Infrarotkamera Abhilfe schaffen. Ich habe einige Situationen durchgespielt, doch es gibt zu viele individuelle Faktoren, um sie wirklich alle  aufzuführen. Jeder sollte es für seine Beobachtungssituation/Kamera/Lichtverhältnisse etc. ausprobieren.

Die eigentliche Arbeit im Script übernimmt „Numpy“ → http://www.numpy.org/.

Es werden immer  der aktuelle und der vorhergehende „Frames“ verglichen. Die Änderungen sind ein Zeichen für eine Bewegung/Änderung der Lichtverhältnisse etc. und werden ab einer gewissen Größe zur Auslösung einer Bedingung genutzt (Zeile 28-31). Bei jedem Start des Scriptes werden 3-4 Aufnahmen gemacht, da evtl. die Kamera eine eigene Initialisierung  durchläuft und so die ersten Bilder voneinander abweichen Dies wird durch die Variable „INIT_STEPS“  verhindert. Das Script läuft den eingestellten Wert durch und wird prüft in dieser Zeit nicht auf Abweichungen.

Download als Zip:  motion_detection.py

_____________________________________Code_______________________________________
#! /usr/bin/env python
# -*- coding: utf-8

import time
import datetime
import numpy as np
from itertools import count
import cv2

SENSITIVITY = 150000
INIT_STEPS = 10
UPDATE_INTERVAL = 0.5
FOLDER = "detected"
cam = cv2.VideoCapture(-1)
counter = 0
init_counter = count()

if cam.isOpened():
try:
while True:
time.sleep(UPDATE_INTERVAL)
frame_1 = cam.read()[-1]
frame_2 = cam.read()[-1]
changes = 0
if np.array_equal(frame_1, frame_2):
raise RuntimeError("cam disconnected")
for old, new in zip(frame_1, frame_2):
changes += np.isclose(old, new).sum()
if counter == INIT_STEPS:
if changes < SENSITIVITY:
print "detected"
cv2.imwrite("{0}/{1:%d%b%Y_%H_%M_%S.%f}.png".format(
FOLDER, datetime.datetime.utcnow()), frame_2)
else:
counter = init_counter.next()
except KeyboardInterrupt:
print "capture stopped"
except RuntimeError as error:
print error
else:
print "capture finished"
finally:
cam.release()
else:
print "no cam"
_____________________________________Code__________________________________________



Elektronik-Labor  Projekte  Mikrocontroller  Raspberry