Vogelalbum 1.0.0
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.
This commit is contained in:
commit
c11fe9ab04
189 files changed
+29806
No files matched your search
+200
@@ -0,0 +1,200 @@
|
||||
# Die Kamera anschließen
|
||||
|
||||
<sub>[← zurück zum Überblick](../README.md) · [alle Kapitel](README.md)</sub>
|
||||
|
||||
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](../pi/README.md) oder [ESP32-S3](../esp32cam/README.md).
|
||||
|
||||
**Noch keine Kamera aufgebaut?** Es gibt zwei fertige Kameraseiten, beide mit
|
||||
denselben Pfaden — der Detector merkt den Unterschied nicht:
|
||||
|
||||
- **[pi/README.md](../pi/README.md)** — Raspberry Pi mit Kameramodul, MJPEG-Server
|
||||
als Dienst (`pi/vogelkamera.py`). Die bessere Optik.
|
||||
- **[esp32cam/README.md](../esp32cam/README.md)** — ESP32-S3 mit Kameramodul
|
||||
(`esp32cam/`). Ein Bruchteil des Preises, externe Antenne möglich, und
|
||||
`/status` liefert 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:
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
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:
|
||||
|
||||
```bash
|
||||
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`](#hängt-die-kamera-richtig-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:
|
||||
|
||||
```bash
|
||||
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.
|
||||
|
||||
```bash
|
||||
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:
|
||||
|
||||
```bash
|
||||
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.
|
||||
Reference in new issue
Block a user