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.
6.4 KiB
Installation
← zurück zum Überblick · alle Kapitel
Zwei Wege zum selben Ziel. Mit Docker braucht es einen Befehl und keine Python-Umgebung; ohne Docker sieht man mehr und kann einzelne Teile austauschen.
Welcher Weg ist meiner?
Vogelalbum besteht aus zwei Teilen, die getrennt laufen können: der Sammlung (Django, zeigt Arten, XP und Abzeichen) und der Erkennung (schaut in die Kamera und meldet Sichtungen). Daraus ergeben sich drei sinnvolle Aufbauten — und für jeden gibt es genau eine Datei:
| Dein Fall | Datei | Was läuft |
|---|---|---|
| Eine Kamera im Garten, ein Rechner im Keller. Der Normalfall, und der richtige Anfang. | docker-compose.heim.yml |
Sammlung und Erkennung auf einer Maschine |
| Die Sammlung soll öffentlich erreichbar sein, die Kamera bleibt zu Hause. | docker-compose.yml |
nur die Sammlung, mit nginx für die Fotos |
| Der Rechner mit Sicht auf die Kamera liefert an eine Sammlung woanders. | docker-compose.detector.yml |
nur die Erkennung |
Die letzten beiden gehören zusammen: Sie sind dieselbe Anlage, aufgeteilt auf zwei Orte. So läuft auch https://vogelalbum.gaertner.onl — Sammlung bei einem Hoster, Erkennung im Heimnetz.
🔑 Nach außen muss dafür kein Port offen sein. Die Verbindung geht nur in eine Richtung: Die Erkennung meldet ausgehend an die Sammlung, die Sammlung erreicht die Kamera nie. Kein Portforwarding, kein Tunnel, kein DynDNS.
⚠️ Wo die Erkennung laufen kann: ai-edge-litert gibt es als fertiges
Wheel für x86_64 und arm64. Ein Pi Zero trägt sie nicht — dem fehlt
nicht das Wheel, sondern die Rechenleistung; er ist die Kameraseite, siehe
pi/README.md.
Getestet auf
Zwei Geräte, wie sie in vielen Hausnetzen stehen. Beide mit dem Schnellstart oben eingerichtet, aus einem frischen Klon und mit leerem Build-Zwischenspeicher:
| Intel N100 | Raspberry Pi 4 Model B | |
|---|---|---|
| 16 GB, Debian, x86_64 | 4 GB, Ubuntu 26.04, aarch64 | |
| Images bauen (einmalig) | 69 s | 467 s (knapp 8 min) |
| Sammlung erreichbar nach | 5 s | 49 s |
| Ein Bild bestimmen | ~30 ms | 42 ms (Median aus 18 Messungen, 35–53 ms) |
| Arbeitsspeicher im Betrieb | — | 1,1 von 3,7 GB |
| Temperatur unter Last | — | 54 °C, keine Drosselung |
🔑 Der Pi 4 langweilt sich dabei. Bei 4 Bildern pro Sekunde und
--classify-every=2 stehen rund 500 ms je bestimmtem Bild zur Verfügung —
er braucht 42. Er könnte also jedes Bild bestimmen statt jedes zweite und wäre
immer noch bei einem Sechstel. Dass ARM hier so gut mithält, liegt an den
int8-quantisierten Modellen; gerechnet hatten wir mit einem Vielfachen.
Der Preis auf dem Pi sind die acht Minuten Bauzeit und die knappe Minute bis zur ersten Seite. Beides fällt genau einmal an.
⚠️ Ungetestet: Raspberry Pi 5 (sollte schneller sein), Pi 4 mit nur 2 GB,
und 32-Bit-Systeme (dort gibt es kein ai-edge-litert-Wheel — Raspberry Pi OS
muss die 64-Bit-Ausgabe sein). Rückmeldungen zu anderer Hardware sind
willkommen, gern als Issue.
Wer gar kein Docker will: ohne Docker weiter unten. Und wer nur schauen will, wie es aussieht, braucht nicht einmal eine Kamera — siehe Ohne Kamera ausprobieren.
Schnellstart mit Docker
Der kürzeste Weg — Sammlung und Erkennung auf einer Maschine, ohne venv, ohne Modelle von Hand, ohne systemd:
git clone https://gitea.gaertner.onl/christian/vogelalbum.git && cd vogelalbum
cp .env.beispiel .env # VOGELALBUM_SOURCE und ein Token eintragen
docker compose -f docker-compose.heim.yml up -d
Der erste Start baut beide Images (rund eine Minute) und legt den Artenkatalog an: 148 Arten mit Steckbriefen und 15 Abzeichen. Die Sammlung steht danach sofort; die Referenzfotos aus Wikipedia holt der Container im Hintergrund nach und tropfen über die nächsten Minuten ein.
Danach läuft die Sammlung auf http://localhost:8000 und der Detector schaut
in die Kamera. Zwei Zeilen in der .env müssen stimmen:
| Variable | was rein muss |
|---|---|
VOGELALBUM_SOURCE |
Stream-URL der Kamera, z.B. http://vogelkamera.local:8080/stream |
VOGELALBUM_INGEST_TOKEN |
ein selbst ausgedachtes Geheimnis, openssl rand -base64 32 |
Alles andere hat brauchbare Vorgaben; den Django-SECRET_KEY erzeugt der
Container beim ersten Start selbst und legt ihn aufs Volume.
Noch keine Kamera? Die Kameraseite steht in pi/README.md — ein Raspberry Pi Zero W mit Kameramodul reicht. Alternativ ein ESP32-S3 mit Kameramodul: esp32cam/README.md, deutlich billiger und mit externer Antenne, was der Bildrate mehr hilft als jede Auflösung.
docker compose -f docker-compose.heim.yml logs -f detector # was sieht er?
docker compose -f docker-compose.heim.yml down # anhalten
Sammlung und Rohbilder liegen in Docker-Volumes und überleben ein
up --build. Wer die Sammlung öffentlich hosten und nur die Erkennung zu
Hause laufen lassen will, nimmt die beiden anderen Dateien aus der
Tabelle oben: docker-compose.yml beim Hoster,
docker-compose.detector.yml zu Hause. Das Deployment der Sammlung steht in
Betrieb.
Schnellstart ohne Docker
Voraussetzungen: Python 3.11+, rund 500 MB Platte, eine Kamera die MJPEG, RTSP oder Einzelbilder liefert.
git clone https://gitea.gaertner.onl/christian/vogelalbum.git && cd vogelalbum
python3 -m venv venv
./venv/bin/pip install -r requirements-detector.txt -r requirements-web.txt
./scripts/fetch_models.sh # ~10 MB, liegen nicht im Repo
./scripts/fetch_testdata.sh # drei Beispielfotos, optional
cd web
../venv/bin/python manage.py migrate
../venv/bin/python manage.py seed_dex # 148 Arten, 15 Abzeichen
../venv/bin/python manage.py fetch_reference_images # Wikipedia-Fotos, ~5 min
../venv/bin/python manage.py runserver 0.0.0.0:8000
Dann in einem zweiten Terminal:
./venv/bin/python -m detector watch --source "http://<kamera>:8080/stream"
Ohne Kamera ausprobieren
cd web
../venv/bin/python manage.py demo_data # 21 Tage Beispieldaten
../venv/bin/python manage.py demo_data --clear
Die Demo-Sichtungen benutzen die Wikipedia-Referenzfotos, sind also klar als
Attrappe erkennbar. Vor dem Echtbetrieb --clear laufen lassen, sonst
mischen sich Demo- und Kameradaten.