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:
christian committed 2026-10-14 18:55:23 +00:00
commit cc9e0786c2
189 files changed
+29792

No files matched your search

+146
View File
@@ -0,0 +1,146 @@
# Installation
<sub>[← zurück zum Überblick](../README.md) · [alle Kapitel](README.md)</sub>
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 *Kamera*seite, siehe
[pi/README.md](../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](#schnellstart-ohne-docker) weiter
unten. Und wer nur schauen will, wie es aussieht, braucht nicht einmal eine
Kamera — siehe [Ohne Kamera ausprobieren](#ohne-kamera-ausprobieren).
## Schnellstart mit Docker
Der kürzeste Weg — Sammlung und Erkennung auf einer Maschine, ohne venv, ohne
Modelle von Hand, ohne systemd:
```bash
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](../pi/README.md)** —
ein Raspberry Pi Zero W mit Kameramodul reicht. Alternativ ein ESP32-S3 mit
Kameramodul: **[esp32cam/README.md](../esp32cam/README.md)**, deutlich billiger
und mit externer Antenne, was der Bildrate mehr hilft als jede Auflösung.
```bash
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](#welcher-weg-ist-meiner): `docker-compose.yml` beim Hoster,
`docker-compose.detector.yml` zu Hause. Das Deployment der Sammlung steht in
[Betrieb](betrieb.md).
## Schnellstart ohne Docker
Voraussetzungen: Python 3.11+, rund 500 MB Platte, eine Kamera die MJPEG,
RTSP oder Einzelbilder liefert.
```bash
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:
```bash
./venv/bin/python -m detector watch --source "http://<kamera>:8080/stream"
```
### Ohne Kamera ausprobieren
```bash
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.