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
@@ -0,0 +1,161 @@
|
||||
<div align="center">
|
||||
|
||||
# Vogelalbum
|
||||
|
||||
**Eine Kamera am Vogelhaus, ein Rechner der erkennt wer da war — und eine
|
||||
Sammlung, die sich von allein füllt.**
|
||||
|
||||
[](LICENSE)
|
||||
[](docs/installation.md)
|
||||
[](#was-es-macht)
|
||||
[](docs/erkennung.md)
|
||||
|
||||
**[→ Live ansehen: vogelalbum.gaertner.onl](https://vogelalbum.gaertner.onl)**
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
> **In English:** Vogelalbum identifies garden birds from a camera stream and turns
|
||||
> the sightings into a collectible album that fills itself. It runs entirely on
|
||||
> your own hardware — no cloud, no third-party services. The interface speaks
|
||||
> German and English; the source code and its comments are German.
|
||||
|
||||
---
|
||||
|
||||
## Was es macht
|
||||
|
||||
Eine Kamera schaut aufs Futterhaus. Alles andere passiert von selbst:
|
||||
|
||||
- 🔍 **Erkennt die Art** — zwei neuronale Netze, eines findet den Vogel im Bild,
|
||||
eines bestimmt ihn. Gemessen: 43 von 44 Arten richtig, keine falsch bestimmt.
|
||||
- 🎴 **Sammelt** — jede neue Art ist ein Erstfang. 148 Arten, 15 Abzeichen, XP
|
||||
und Level. Das ist der Teil, für den Kinder wiederkommen.
|
||||
- 🏠 **Bleibt zu Hause** — kein Cloud-Dienst, keine Telemetrie, kein Konto. Die
|
||||
Erkennung läuft auf deiner Hardware, die Bilder verlassen dein Netz nicht.
|
||||
- 🔌 **Nimmt jede Kamera** — MJPEG, RTSP, Einzelbilder oder ein Ordner. Ein
|
||||
Raspberry Pi Zero genügt, ein ESP32-S3 für 17 € auch.
|
||||
- 🥔 **Läuft auf kleiner Hardware** — gemessen auf einem Raspberry Pi 4:
|
||||
42 ms je bestimmtem Vogel, 1,1 GB Arbeitsspeicher. Zahlen für beide
|
||||
getesteten Geräte in [docs/installation.md](docs/installation.md#getestet-auf).
|
||||
- 📱 **Auch ohne Kamera** — Handyfotos lassen sich hochladen und werden genauso
|
||||
bestimmt.
|
||||
- 🏡 **Spricht mit Home Assistant** — über MQTT, mit Autodiscovery.
|
||||
|
||||
<div align="center">
|
||||
<img src="docs/startseite.png" width="49%" alt="Die Startseite">
|
||||
<img src="docs/abzeichen.png" width="49%" alt="Die Abzeichen">
|
||||
</div>
|
||||
|
||||
## Schnellstart
|
||||
|
||||
Sammlung und Erkennung auf einer Maschine, ohne venv und ohne Modelle von Hand:
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
Die Sammlung läuft danach auf <http://localhost:8000>. 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` |
|
||||
|
||||
**Noch keine Kamera?** Es geht auch ohne — `manage.py demo_data` füllt die
|
||||
Sammlung mit 21 Tagen Beispieldaten. Der Aufbau einer Kameraseite steht in
|
||||
[pi/README.md](pi/README.md) (Raspberry Pi) oder
|
||||
[esp32cam/README.md](esp32cam/README.md) (ESP32-S3, billiger).
|
||||
|
||||
Ohne Docker, Schritt für Schritt: **[docs/installation.md](docs/installation.md)**.
|
||||
|
||||
## Wie es aufgebaut ist
|
||||
|
||||
Zwei Teile, die unabhängig voneinander laufen und getrennt deploybar sind:
|
||||
|
||||
```
|
||||
Heimnetz │ Internet
|
||||
│
|
||||
Kamera 1 ──MJPEG──▶ ┌──────────┐ │
|
||||
Kamera 2 ──MJPEG──▶ │ detector │ ──POST────────▶ Django ──▶ Browser
|
||||
Kamera n ──MJPEG──▶ │ │ Bearer │
|
||||
└────┬─────┘ │
|
||||
└──▶ Rohbilder │
|
||||
(Training) │
|
||||
```
|
||||
|
||||
**Die Verbindung geht nur in eine Richtung.** Der Detector meldet ausgehend an
|
||||
`/api/sightings/`; die Web-App muss weder Kamera noch Erkennungs-Host jemals
|
||||
erreichen. Damit muss im Heimnetz kein einziger Port nach außen offen sein —
|
||||
kein Portforwarding, kein Tunnel, keine dynamische DNS. Genau deshalb kann die
|
||||
Sammlung öffentlich stehen, während die Kameras es nicht sind.
|
||||
|
||||
Warum überhaupt getrennt? Ein Raspberry Pi Zero kann streamen, aber nicht
|
||||
rechnen. Umgekehrt kennt die Web-App weder numpy noch LiteRT, was ihren
|
||||
Container klein hält.
|
||||
|
||||
## Dokumentation
|
||||
|
||||
| Kapitel | worum es geht |
|
||||
|---|---|
|
||||
| **[Installation](docs/installation.md)** | mit und ohne Docker, Schritt für Schritt |
|
||||
| **[Die Kamera anschließen](docs/kamera.md)** | Stream-Formate, Schwellwerte — und wie groß ein Vogel im Bild sein muss |
|
||||
| **[Wie die Erkennung funktioniert](docs/erkennung.md)** | drei Stufen, der Artenfilter, was das Modell nicht kann |
|
||||
| **[Wie gut ist das wirklich](docs/genauigkeit.md)** | gemessene Zahlen, und was im Feld tatsächlich passiert ist |
|
||||
| **[Einstellungen](docs/einstellungen.md)** | alle Variablen, und was stattdessen im Admin geht |
|
||||
| **[Betrieb](docs/betrieb.md)** | mehrere Kameras, Live-Bild, Deployment |
|
||||
| **[Entwicklung](docs/entwicklung.md)** | Tests, Übersetzungen, Artenkatalog erweitern |
|
||||
| **[Datenquellen und Lizenzen](docs/datenquellen.md)** | woher Modelle und Fotos kommen |
|
||||
|
||||
Die Kameraseiten haben eigene Anleitungen: **[pi/](pi/README.md)** und
|
||||
**[esp32cam/](esp32cam/README.md)**.
|
||||
|
||||
## Was es (noch) nicht kann
|
||||
|
||||
Ehrlicher als eine Merkmalsliste:
|
||||
|
||||
- ⚠️ **Der Katalog ist mitteleuropäisch.** 148 in Deutschland vorkommende Arten;
|
||||
der Klassifikator rechnet seine Wahrscheinlichkeiten auf genau diese Liste
|
||||
um. Das Modell selbst kennt rund 965 Arten weltweit — die Begrenzung ist der
|
||||
Katalog, nicht die Erkennung. Die Region ist umschaltbar
|
||||
(`VOGELALBUM_REGION`), es fehlen nur die Artenlisten anderer Regionen. Das ist
|
||||
reine Datenarbeit und ein guter erster Beitrag.
|
||||
- **Acht heimische Arten kennt das Modell nicht** und ordnet sie Verwandten zu
|
||||
(Sumpf-, Weiden-, Haubenmeise, Gartenbaumläufer, Kleinspecht, Bluthänfling,
|
||||
Kernbeißer, Waldkauz). Details in [docs/erkennung.md](docs/erkennung.md).
|
||||
- **Der Aufbau entscheidet mehr als die Software.** Ein Vogel braucht 5–8 % der
|
||||
Bildfläche, sonst findet ihn niemand. `python -m detector karte` misst das
|
||||
vorher, statt es hinterher zu lernen — siehe [docs/kamera.md](docs/kamera.md).
|
||||
|
||||
## Mitmachen
|
||||
|
||||
Fehler, Ideen und Code sind willkommen. Die Spielregeln — und die
|
||||
Rechteeinräumung, die für die Doppellizenzierung nötig ist — stehen in
|
||||
**[CONTRIBUTING.md](CONTRIBUTING.md)**. Eine Sicherheitslücke bitte nicht als
|
||||
Issue, sondern nach **[SECURITY.md](SECURITY.md)**.
|
||||
|
||||
Was sich wann geändert hat: **[CHANGELOG.md](CHANGELOG.md)**.
|
||||
|
||||
## Lizenz
|
||||
|
||||
**GNU Affero General Public License 3.0** ([LICENSE](LICENSE)). Benutzen,
|
||||
verändern und weitergeben ist erlaubt; wer eine veränderte Fassung als Dienst
|
||||
über ein Netz anbietet, muss deren Quelltext zugänglich machen. Für den Betrieb
|
||||
im eigenen Garten ändert das nichts. Kommerzielle Nutzung ohne Offenlegung ist
|
||||
über eine gesonderte Lizenz möglich: <webmaster@gaertner.onl>.
|
||||
|
||||
Modelle (Apache 2.0) und Referenzfotos aus Wikimedia Commons (meist CC BY-SA)
|
||||
behalten ihre eigenen Lizenzen — Einzelheiten in
|
||||
[docs/datenquellen.md](docs/datenquellen.md).
|
||||
|
||||
---
|
||||
|
||||
<div align="center">
|
||||
<sub>Kein Bild dieses Projekts verlässt das eigene Netz, außer man deployt die
|
||||
Web-App selbst irgendwohin. Es gibt keine Telemetrie und keine Aufrufe an
|
||||
Dritte außer den ausdrücklich angestoßenen Downloads von Modellen und
|
||||
Referenzfotos.</sub>
|
||||
</div>
|
||||
Reference in new issue
Block a user