Aus Raspberry Pi Geek 10/2017

Nistkästen mit der Pi-Cam ins Internet bringen (Seite 3)

Kamera

Zum Aufzeichnen der Aktivitäten der nistenden Vögel kommt die Raspberry-Pi-Kamera in der IR-Version zum Einsatz. Diese haben Sie bereits bei der initialen Einrichtung des Systems aktiviert, nun fehlt noch die softwareseitige Unterstützung. Für das Projekt kommt Python zum Einsatz: Dafür gibt es mit Picamera [6] bereits eine leistungsfähige Bibliothek, die sich über den Python-Paketmanager Pip installieren lässt (Listing 5). Auch eine minimalistische Bildveränderungserkennung lässt sich in Python gut umsetzen.

Listing 5

 

$ sudo apt install python-pip
$ sudo pip install picamera

Damit sich die Vögelchen nicht durch die rote LED der Kamera gestört fühlen, schalten Sie diese aus. Das erfordert den Eintrag disable_camera_led=1 in der Datei /boot/config.txt und einen anschließenden Neustart.

Für einen ersten Test übertragen Sie nun den Inhalt aus Listing 6 in eine leere Datei, etwa in meisentest.py. Das kleine Programm nimmt lediglich ein Bild auf und speichert es auf der RAM-Disk. Zudem gibt es die aktuelle Zeit in Form eines Timestamps aus. Sie machen das Programm mit chmod +x meisentest.py ausführbar und rufen es dann mit ./meisentest.py auf. Das System sollte die neue Aufnahme nach einem ls /mnt/ramdisk auflisten.

Listing 6

 

#!/usr/bin/python
# meisentest.py
# Erster Test
import picamera
import time
# Voreinstellungen
WIDTH=320
HEIGHT=240
FONTSIZE=20
# Kamera initialisieren
camera = picamera.PiCamera()
camera.vflip = False
camera.hflip = False
camera.brightness = 60
camera.resolution = (WIDTH,HEIGHT)
localpicname = '/mnt/ramdisk/meisencam.jpg'
camera.capture(localpicname)
zeitstempel = time.strftime("%Y%d%m-%H%M%S")
print (zeitstempel)
camera.close()

Bewegungserkennung

Um nun zu erkennen, ob sich aktuell eine Meise im Nistkasten befindet, greift das Projekt auf einen simplen Algorithmus zurück. Zunächst sichert es das letzte Bild (Bildalt) und nimmt ein neues (Bildneu) auf. Anschließend wandelt es beide Aufnahmen in Grauwerte um und reduziert die Pixelzahl beider Bilder auf 4 x 3 Pixel.

Es folgt das Ermitteln einer Kennzahl, für die das Programm über alle jeweils 12 Bildpunkte die Differenz der Helligkeitswerte (Bildpunktneu – Bildpunktalt) berechnet und die Beträge aufsummiert. Fällt die Kennzahl größer aus, als ein Schwellwert, liegt eine Bildveränderung vor. Dann übermittelt das Program einen Merker an einen Webservice.

Für komplexe Pixeloperationen in Python gilt die quelloffene Bilderkennungsbibliothek OpenCV [7] als Mittel der Wahl. Weil dabei aber die Lernkurve recht steil ausfällt, kommt stattdessen die Python Image Library oder kurz PIL [8] zum Einsatz, die Sie über die Paketverwaltung einrichten (Listing 7). Ausführliche Tipps zum Umgang mit PIL liefert beispielsweise das deutschsprachige Blog Rustimation [9].

Listing 7

 

§ sudo apt install python-imaging

Den Python-Quelltext für unsere Meisencam inklusive des Hochladens des Bilds mit einem Webservice finden Sie in Listing 8. Der Schwellwert von 35 wurde vor dem Bezug des Nistkastens durch ein Meisenpaar experimentell ermittelt. Dazu hielten wir verschieden große Gegenstände ins Einflugloch, die unterschiedlich hohe Kennzahlen erzeugten.

Die Wahl des Schwellwerts geschah dann nach Augenmaß, sodass die Software erst bei größeren Unterschieden im Bild reagiert. Beim Nachbauen müssen Sie wahrscheinlich selbst einen brauchbaren Wert ermitteln, da andere Rahmenbedingungen (etwa dunkleres Holz oder anderes Licht) neue Schwellwerte nötig machen.

Listing 8

 

#!/usr/bin/python
# meisencam.py
# Bildveraenderungserkennung mit PIL
import picamera
import time
from time import sleep
import requests
from PIL import Image
# Voreinstellungen
WIDTH=320
HEIGHT=240
FONTSIZE=20
SCHWELLWERT=35
# Kamera initialisieren
camera = picamera.PiCamera()
camera.vflip = False
camera.hflip = False
camera.brightness = 60
camera.resolution = (WIDTH,HEIGHT)
camera.iso = 400
camera.shutter_speed = 25000
camera.awb_mode = 'cloudy'
localpicname = '/mnt/ramdisk/meisencam.jpg'
zeitstempel = time.strftime("%Y%m%d-%H%M%S")
camera.annotate_text = zeitstempel
sleep (2)
camera.capture(localpicname)
print (zeitstempel)
camera.close()
# Kennzahl fuer die Bildveraenderung ermitteln
# Bilder in Objekte laden
localaltname='/mnt/ramdisk/meisencamalt.jpg'
bildneu=Image.open(localpicname)
# Falls Raspi neu gestartet, existiert das alte Bild nicht
# Hilfsweise fuer einen Durchlauf das neue nehmen
try:
  bildalt=Image.open(localaltname)
except IOError:
  bildalt=bildneu
# altes Bild durch aktuelles Bild ersetzen
bildneu.save(localaltname)
# Bilder in Grauwerte umrechnen
bildneu=bildneu.convert("L")
bildalt=bildalt.convert("L")
# Bilder stark verkleinern
breite=4
hoehe=3
size=[breite,hoehe]
bildneu=bildneu.resize(size)
bildalt=bildalt.resize(size)
# In einer Schleife Kennzahl ermitteln
x=0
y=0
kennzahl=0
while (x<breite):
  while (y<hoehe):
  hneu = bildneu.getpixel((x,y))
  halt = bildalt.getpixel((x,y))
  kennzahl=kennzahl+abs(hneu-halt)
  y=y+1
  x=x+1
kennzahl=kennzahl/hoehe/breite
print ("Kennzahl: " + str(kennzahl))
if (kennzahl>SCHWELLWERT):
  mode=1
else:
  mode=0
print ("Modus: " + str(mode))
# Auf den Webspace hochladen
# Webservice-Aufruf ohne Bildveraenderung:
url = 'http://meisencam.cbrell.de/meisencamWS.php'
# Webservice-Aufruf bei Bildveraenderung
if (mode==1):
  url = 'http://meisencam.cbrell.de/meisencamWS.php?mode=1'
files = {'file': open(localpicname, 'rb')}
r = requests.post(url, files=files)
print(r)
# Log schreiben
f = file('/mnt/ramdisk/meisencam.log','a')
ausgabe = zeitstempel + ';' + str(kennzahl) + ';' + str(mode) + ';' + r.text + $
f.write(ausgabe)
f.close()

Die Einstellungen für die Kamera – insbesondere der ISO-Wert, die Belichtungszeit in Mikrosekunden und der Farbabgleich – werden fest eingestellt. Lässt man die Kamera die Werte selbst automatisch ermitteln, kommen insbesondere mit dem Infrarot-Kameramodul sehr unterschiedliche Varianten heraus. Die Bildveränderungserkennung spricht dann an, obwohl sich im Meisenkasten eigentlich nichts tut.

Bilder hochladen

Bei dem Webservice, der das Bild entgegennimmt und auf dem Webserver speichert, handelt es sich um ein einfaches PHP-Skript mit dem Namen meisencamWS.php (Listing 9). Die Programmiersprache PHP stellt nahezu jeder Webspace-Anbieter zur Verfügung, in der Regel genügt ein kleines Webhosting-Paket für wenige Euro monatlich.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 9 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
RASPBERRY PI GEEK KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Raspberry Pi Geek bei Google Play Readly Logo
Nach oben