Eine Kamera am Vogelhaus, ein Rechner der erkennt wer da war — und eine Sammlung, die sich von allein fuellt. Zwei neuronale Netze: eines findet den Vogel im Bild, eines bestimmt die Art. 148 heimische Arten, auf Deutschland eingeschraenkt und neu normiert — ohne diese Einschraenkung wird aus einer Kohlmeise eine nordamerikanische Schwesterart. Daraus entsteht ein Sammelalbum: nummerierte Seiten, gefundene Arten in Farbe, fehlende als Schatten, dazu Erstfang, Punkte, Stufen und 15 Abzeichen. Laeuft vollstaendig auf eigener Hardware. Kein Cloud-Dienst, kein Konto, keine Telemetrie; die Bilder verlassen das eigene Netz nicht. Zwei getrennt deploybare Teile: die Sammlung als Django-Anwendung, die Erkennung als eigener Dienst. Der Erkennungs-Dienst fragt selbst an und braucht deshalb weder eine erreichbare Adresse noch einen offenen Port — er laeuft hinter einem gewoehnlichen Router. Dabei: Firmware fuer Raspberry Pi und ESP32-S3, Anbindung an Home Assistant ueber MQTT, Oberflaeche auf Deutsch und Englisch, Einstellungen je Kamera aus dem Browser, und ein Weg fuer Fotos von unterwegs. AGPL-3.0.
8.3 KiB
Die Kamera anschließen
← zurück zum Überblick · alle Kapitel
Vogelalbum braucht von der Kamera nur einen Stream. Hier steht, welche Formen davon gelesen werden, wie man die Schwellwerte einstellt und — die Frage, an der ein Aufbau wirklich scheitert — wie groß ein Vogel im Bild sein muss.
Der Aufbau der Kameraseite selbst steht getrennt: Raspberry Pi oder ESP32-S3.
Noch keine Kamera aufgebaut? Es gibt zwei fertige Kameraseiten, beide mit denselben Pfaden — der Detector merkt den Unterschied nicht:
- pi/README.md — Raspberry Pi mit Kameramodul, MJPEG-Server
als Dienst (
pi/vogelkamera.py). Die bessere Optik. - esp32cam/README.md — ESP32-S3 mit Kameramodul
(
esp32cam/). Ein Bruchteil des Preises, externe Antenne möglich, und/statusliefert Bildrate, Funkstärke und Temperatur, ohne den Stream anzufassen.
Beide Anleitungen nennen die drei Dinge, die man dabei einmal falsch macht — zweiter Zuschauer, Hitze im Kasten, Bildrate am Licht statt an der CPU.
Der Detector spricht MJPEG, RTSP, Einzelbild-URLs und Ordner:
# MJPEG (mjpg-streamer, motion, picamera2-Beispielserver)
python -m detector watch --source "http://kamera.local:8080/stream"
# Einzelbild im Sekundentakt — genügsamer, für einen Nistkasten meist genug
python -m detector watch --source "http://kamera.local/snapshot.jpg" --interval 1
# RTSP (braucht ffmpeg auf dem Host)
python -m detector watch --source "rtsp://kamera.local:8554/cam"
# Ordner mit Bildern, zum Ausprobieren ohne Kamera
python -m detector watch --source ./testbilder
Mit Anbindung an die Web-App:
python -m detector watch \
--source "http://kamera.local:8080/stream" \
--api http://127.0.0.1:8000 \
--token "$VOGELALBUM_TOKEN" \
--save-to /var/lib/vogelalbum/rohdaten
--save-to schreibt Bild und JSON zusätzlich auf Platte. Das kostet fast
nichts und ist später das Trainingsmaterial fürs eigene Modell.
Schwellwerte einstellen
Die Voreinstellungen passen zu unserer Kamera. An einer anderen gehören sie gemessen:
python -m detector tune --source "http://kamera.local:8080/stream"
Zeigt live den Anteil bewegter Pixel und die Bildhelligkeit. --motion-ratio
gehört knapp über den Ruhepegel — hoch genug, dass Wind und Lichtwechsel nicht
auslösen, niedrig genug für eine Blaumeise am Bildrand. Liegt der Ruhepegel
ohnehin hoch, ist --gate detector die bessere Wahl.
Das ist aber nur die Bewegungsschwelle. Ob die Kamera überhaupt an der
richtigen Stelle hängt, beantwortet detector karte
— und zwar bevor man Tage auf den ersten Vogel wartet.
Abschaltung bei Dunkelheit
Eine Kamera ohne Infrarot liefert nachts ein schwarzes Bild. Es durch zwei neuronale Netze zu schicken kostet Strom und bringt nichts, deshalb pausiert der Detector von selbst.
Entschieden wird über die Bildhelligkeit, nicht über Sonnenauf- und -untergang. Das braucht keine Koordinaten und misst genau das, worauf es ankommt: ob man etwas sieht. Ein Futterhaus unter einer Straßenlaterne bleibt nutzbar, ein zugewachsenes ist schon vor Sonnenuntergang zu dunkel.
Zwischen Abschalt- und Einschaltschwelle liegt bewusst Abstand — ohne diese Hysterese flattert die Entscheidung in der Dämmerung im Sekundentakt.
Eine Infrarotkamera liefert nachts ein graues, aber helles Bild und läuft
damit von selbst weiter. --nachtsicht ist nur nötig, wenn die Automatik
danebenliegt.
Gemessen im Betrieb: statt rund 40 % eines Kerns bleiben nachts 9 %, und die gehen fast vollständig für das Dekodieren des MJPEG-Stroms drauf.
Dauerprotokoll
Sechs Minuten zuschauen beantwortet die Frage „übersehen wir Vögel?" nur für diese sechs Minuten. Über Tage beantwortet sie ein Protokoll:
python -m detector watch --source ... --protokoll /var/lib/vogelalbum/protokoll.csv
Geschrieben werden zwei Sorten Zeilen:
- jede Erkennung ab
--protokoll-ab(Standard 0.08, weit unter der Betriebsschwelle von 0.4) — auch die, die für eine Sichtung nicht gereicht hat. Genau daran sieht man, ob die Schwelle zu hoch steht oder die Vögel schlicht zu klein im Bild sind. - ein Lebenszeichen je Viertelstunde, immer, auch wenn nichts passiert ist. Diese Zeilen sind die wichtigeren: Ein Protokoll, das nur bei Erfolg schreibt, sieht bei einem Ausfall genauso aus wie bei einem ruhigen Tag.
Wie groß muss ein Vogel im Bild sein
Gemessen, indem ein echter Vogelausschnitt in verschiedenen Größen in ein Bild derselben Kamera montiert wurde:
| Anteil am Bild | Detektor-Score | |
|---|---|---|
| 15 % | 0.93 | ✅ |
| 10 % | 0.77 | ✅ |
| 5 % | 0.77 | ✅ |
| 3 % | 0.23 | ❌ unter der Schwelle |
| 1 % | 0.07 | ❌ |
Die Grenze liegt bei rund 5 % der Bildfläche — bei 1280×720 also etwa 260×175 Pixel.
Aufschlussreich ist, was dabei nicht zusammenbricht: Die Artbestimmung liegt selbst bei 1 % Fläche noch bei 100 %. Der Engpass ist also nicht, die Art zu erkennen, sondern überhaupt zu merken, dass da ein Vogel ist. Für den Aufbau heißt das: näher heran schlägt höhere Auflösung.
Die 5 % sind allerdings kein fester Wert, sondern hängen am Hintergrund. Dieselbe Messung nach einem Umsetzen der Kamera — statt ruhigem Grund nun ein Baum im Wind hinter dem Futter — ergab erst ab 8 % eine zuverlässige Erkennung. Deshalb misst man an der eigenen Kamera nach, statt eine Zahl aus diesem README zu übernehmen. Genau dafür gibt es das nächste Kommando.
Hängt die Kamera richtig? (detector karte)
Die Größe ist nur die halbe Antwort. Die andere ist, wo im Bild der Vogel sitzt — und da gibt es Zonen, in denen der Detektor auch einen großen Vogel nicht findet.
python -m detector karte --source http://vogelhaus.local:8080/stream \
--vogel testdata/amsel.jpg --anteil 0.08 --ziel karte.jpg
Ein echtes Vogelfoto wird mit weicher Maske über ein Raster von Positionen in aktuelle Bilder der eigenen Kamera montiert und jedes Mal durch den Detektor geschickt. Heraus kommt eine Ampel über dem eigenen Kamerabild — grün erkannt, rot nicht — plus dieselbe Karte als Tabelle und ein Satz, was zu tun ist.
Das beantwortet vor dem ersten echten Besuch, ob die Kamera richtig hängt. Ohne diese Karte wartet man Tage auf eine leere Sammlung und weiß danach immer noch nicht, ob keine Vögel kamen oder ob sie an der falschen Stelle im Bild saßen.
Am Vogelhaus in Herzogenrath sah das so aus:
Fuss y x=0.18 x=0.32 x=0.46 x=0.60 x=0.74 x=0.88
0.55 OK 0.84 -- 0.44 OK 0.67 OK 0.67 OK 0.44 -- 0.44
0.65 OK 0.77 -- 0.44 OK 0.80 OK 0.56 -- 0.28 OK 0.62
0.75 OK 0.67 -- 0.38 OK 0.80 OK 0.72 -- 0.38 OK 0.56
0.85 OK 0.84 OK 0.67 OK 0.77 OK 0.84 OK 0.56 OK 0.72
0.95 -- 0.38 -- 0.16 -- 0.38 OK 0.62 -- 0.23 -- 0.20
Die unterste Reihe fällt fast geschlossen durch — und genau dort steht ein Vogel, der auf dem Futterbrett landet, wenn die Kamera flach darüber hinweg schaut. Derselbe Vogel in derselben Größe zehn Prozent höher im Bild: 0.84.
Daraus die Bauregel, die für jedes Futterhaus gilt: die Landefläche gehört in die untere Bildmitte, nicht an den unteren Bildrand. Kamera so weit nach unten neigen, bis unter dem Futter noch Bild übrig ist.
Nachsehen, was angekommen ist
Nach den ersten Tagen ist die Frage nicht „läuft es", sondern „sehen wir Vögel, und taugen die Bilder etwas". Dafür gibt es eine Auswertung der Rohdaten:
python -m detector report /var/lib/vogelalbum/rohdaten
python -m detector report /var/lib/vogelalbum/rohdaten --kontaktbogen bogen.jpg
Sie misst je Sichtung nach, statt zu schätzen: Schärfe (Varianz der Laplace-Antwort, unter ~50 sichtbar verwackelt), Fläche des Vogels im Bild und Helligkeit.
Die Fläche ist dabei der wichtigste Wert. Ein Vogel, der unter 3 % des Bildes einnimmt, ist ein Fleck — daran ändert kein Schwellwert etwas, da muss die Kamera näher heran oder enger eingestellt werden. Die Auswertung sagt das ausdrücklich, wenn es auf mehr als ein Drittel der Sichtungen zutrifft.
Der Kontaktbogen legt alle Ausschnitte als ein Bild nebeneinander. Ob die Qualität reicht, sieht man damit in zehn Sekunden statt in sechzig einzeln geöffneten Dateien.