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-15 14:30:02 +00:00
commit c11fe9ab04
189 files changed
+29806

No files matched your search

+335
View File
@@ -0,0 +1,335 @@
"""Der erweiterte Artenkatalog.
``species_de.py`` enthält die 44 Arten, die realistisch am Futterhaus sitzen —
mit Erzähltext, Verwechslungsliste und allem. Hier stehen die übrigen rund
100 Arten, die in Deutschland regelmäßig vorkommen und die das Modell kennt.
Bewusst nur Strukturdaten, kein Fließtext. Ein Steckbrief für den
Purpurreiher, der nie vor der Kamera landen wird, ist verschwendete Mühe —
er wächst nach, sobald eine Art zum ersten Mal auftaucht. Die Oberfläche
kommt mit fehlendem Text zurecht.
Die Seltenheit misst, wie wahrscheinlich eine Art **vor dieser Kamera**
erscheint, nicht ihre Bestandslage. Der Kiebitz ist deutschlandweit weit
häufiger als der Steinkauz — an einem Futterhaus sieht man trotzdem eher den
Kauz. Damit die Sammlung dadurch nicht in einem Meer aus Wasservögeln
untergeht, hat jede Art zusätzlich einen ``lebensraum``, nach dem sich
filtern lässt.
"""
from __future__ import annotations
from dataclasses import dataclass
# Lebensraum — die Achse, nach der die Sammlung sinnvoll teilbar ist.
HABITATS = {
"garten": ("Garten & Siedlung", "Gardens & settlements"),
"wald": ("Wald", "Woodland"),
"offenland": ("Feld & Wiese", "Fields & meadows"),
"wasser": ("Wasser & Ufer", "Water & shoreline"),
"gebirge": ("Gebirge", "Mountains"),
}
# Ergänzende Typen für die Gruppen, die im Garten nicht vorkommen.
EXTRA_TYPES = {
"schreitvogel": ("Schreitvogel", "#6b8f8a", "#f0f6f5"),
"ente": ("Ente", "#3f7d9e", "#eef7fb"),
"gans": ("Gans", "#8d9aa6", "#151b20"),
"moewe": ("Möwe", "#7fa8c9", "#101c26"),
"watvogel": ("Watvogel", "#b3966b", "#241c0e"),
"taucher": ("Taucher", "#4a7a8c", "#eef6f9"),
"ralle": ("Ralle", "#5f6b5a", "#eef2ec"),
"lerche": ("Lerche", "#c2a878", "#241d0d"),
"wuerger": ("Würger", "#9a6f8f", "#f7eef5"),
"huhn": ("Hühnervogel", "#a4703f", "#f8efe6"),
"exot": ("Exot", "#22a3a3", "#f0ffff"),
}
EXTRA_TYPE_NAMES_EN = {
"schreitvogel": "Wader (long-legged)",
"ente": "Duck",
"gans": "Goose",
"moewe": "Gull",
"watvogel": "Shorebird",
"taucher": "Grebe",
"ralle": "Rail",
"lerche": "Lark",
"wuerger": "Shrike",
"huhn": "Gamebird",
"exot": "Exotic",
}
@dataclass(frozen=True)
class Extra:
slug: str
german: str
scientific: str
english: str
typ: str
rarity: str
size_cm: str
gewicht_g: float
spannweite_cm: float
zug: str
lebensraum: str
def _(slug, german, scientific, english, typ, rarity, size, gewicht, spann, zug, hab):
return Extra(slug, german, scientific, english, typ, rarity,
f"{size} cm", gewicht, spann, zug, hab)
# fmt: off
EXTRA: list[Extra] = [
# ---------- Finken und Ammern ----------
_("bergfink", "Bergfink", "Fringilla montifringilla", "Brambling",
"fink", "selten", 15, 24, 26, "zug", "garten"),
_("bluthaenfling", "Bluthänfling", "Carduelis cannabina", "Eurasian Linnet",
"fink", "selten", 13, 19, 24, "teil", "offenland"),
_("kernbeisser", "Kernbeißer", "Coccothraustes coccothraustes", "Hawfinch",
"fink", "selten", 18, 55, 31, "stand", "wald"),
_("fichtenkreuzschnabel", "Fichtenkreuzschnabel", "Loxia curvirostra", "Red Crossbill",
"fink", "episch", 17, 40, 29, "stand", "wald"),
_("rohrammer", "Rohrammer", "Emberiza schoeniclus", "Reed Bunting",
"ammer", "episch", 15, 19, 23, "teil", "wasser"),
_("grauammer", "Grauammer", "Emberiza calandra", "Corn Bunting",
"ammer", "episch", 18, 45, 29, "stand", "offenland"),
# ---------- Schnäpper und Verwandte ----------
_("blaukehlchen", "Blaukehlchen", "Luscinia svecica", "Bluethroat",
"schnaepper", "episch", 14, 18, 23, "zug", "wasser"),
_("braunkehlchen", "Braunkehlchen", "Saxicola rubetra", "Whinchat",
"schnaepper", "episch", 13, 17, 23, "zug", "offenland"),
_("schwarzkehlchen", "Schwarzkehlchen", "Saxicola rubicola", "European Stonechat",
"schnaepper", "episch", 12, 15, 20, "teil", "offenland"),
_("steinschmaetzer", "Steinschmätzer", "Oenanthe oenanthe", "Northern Wheatear",
"schnaepper", "episch", 15, 24, 30, "zug", "offenland"),
# ---------- Drosseln ----------
_("misteldrossel", "Misteldrossel", "Turdus viscivorus", "Mistle Thrush",
"drossel", "selten", 27, 120, 45, "teil", "wald"),
_("wasseramsel", "Wasseramsel", "Cinclus cinclus", "White-throated Dipper",
"drossel", "episch", 18, 60, 28, "stand", "gebirge"),
# ---------- Grasmücken und Goldhähnchen ----------
_("dorngrasmuecke", "Dorngrasmücke", "Sylvia communis", "Greater Whitethroat",
"grasmuecke", "selten", 14, 15, 21, "zug", "offenland"),
_("wintergoldhaehnchen", "Wintergoldhähnchen", "Regulus regulus", "Goldcrest",
"grasmuecke", "selten", 9, 5.5, 14, "teil", "wald"),
_("sommergoldhaehnchen", "Sommergoldhähnchen", "Regulus ignicapilla", "Common Firecrest",
"grasmuecke", "selten", 9, 5.5, 14, "teil", "wald"),
# ---------- Stelzen, Pieper, Lerchen ----------
_("gebirgsstelze", "Gebirgsstelze", "Motacilla cinerea", "Grey Wagtail",
"stelze", "selten", 19, 18, 26, "teil", "gebirge"),
_("schafstelze", "Schafstelze", "Motacilla flava", "Western Yellow Wagtail",
"stelze", "episch", 17, 17, 25, "zug", "offenland"),
_("wiesenpieper", "Wiesenpieper", "Anthus pratensis", "Meadow Pipit",
"lerche", "episch", 15, 18, 24, "teil", "offenland"),
_("feldlerche", "Feldlerche", "Alauda arvensis", "Eurasian Skylark",
"lerche", "episch", 18, 38, 33, "teil", "offenland"),
_("haubenlerche", "Haubenlerche", "Galerida cristata", "Crested Lark",
"lerche", "legendaer", 17, 42, 32, "stand", "offenland"),
# ---------- Würger ----------
_("neuntoeter", "Neuntöter", "Lanius collurio", "Red-backed Shrike",
"wuerger", "episch", 17, 30, 26, "zug", "offenland"),
_("raubwuerger", "Raubwürger", "Lanius excubitor", "Northern Shrike",
"wuerger", "legendaer", 25, 65, 33, "teil", "offenland"),
# ---------- Rabenvögel ----------
_("nebelkraehe", "Nebelkrähe", "Corvus cornix", "Hooded Crow",
"rabenvogel", "selten", 48, 510, 98, "stand", "offenland"),
_("saatkraehe", "Saatkrähe", "Corvus frugilegus", "Rook",
"rabenvogel", "selten", 46, 460, 90, "teil", "offenland"),
_("alpendohle", "Alpendohle", "Pyrrhocorax graculus", "Alpine Chough",
"rabenvogel", "legendaer", 38, 210, 78, "stand", "gebirge"),
# ---------- Tauben ----------
_("strassentaube", "Straßentaube", "Columba livia", "Rock Pigeon",
"taube", "selten", 33, 300, 65, "stand", "garten"),
_("turteltaube", "Turteltaube", "Streptopelia turtur", "European Turtle-Dove",
"taube", "episch", 27, 150, 50, "zug", "offenland"),
# ---------- Schwalben ----------
_("uferschwalbe", "Uferschwalbe", "Riparia riparia", "Bank Swallow",
"schwalbe", "selten", 12, 14, 28, "zug", "wasser"),
# ---------- Auffällige Einzelgänger ----------
_("seidenschwanz", "Seidenschwanz", "Bombycilla garrulus", "Bohemian Waxwing",
"exot", "selten", 20, 60, 34, "zug", "garten"),
_("kuckuck", "Kuckuck", "Cuculus canorus", "Common Cuckoo",
"exot", "episch", 33, 115, 58, "zug", "wald"),
_("wiedehopf", "Wiedehopf", "Upupa epops", "Common Hoopoe",
"exot", "legendaer", 27, 65, 45, "zug", "offenland"),
_("eisvogel", "Eisvogel", "Alcedo atthis", "Common Kingfisher",
"exot", "legendaer", 17, 40, 25, "stand", "wasser"),
_("bienenfresser", "Bienenfresser", "Merops apiaster", "European Bee-Eater",
"exot", "legendaer", 28, 55, 46, "zug", "offenland"),
_("blauracke", "Blauracke", "Coracias garrulus", "European Roller",
"exot", "legendaer", 31, 130, 70, "zug", "offenland"),
# ---------- Greifvögel ----------
_("habicht", "Habicht", "Accipiter gentilis", "Northern Goshawk",
"greifvogel", "episch", 55, 900, 105, "stand", "wald"),
_("raufussbussard", "Raufußbussard", "Buteo lagopus", "Rough-legged Hawk",
"greifvogel", "legendaer", 55, 950, 130, "zug", "offenland"),
_("rotmilan", "Rotmilan", "Milvus milvus", "Red Kite",
"greifvogel", "episch", 65, 1000, 160, "teil", "offenland"),
_("schwarzmilan", "Schwarzmilan", "Milvus migrans", "Black Kite",
"greifvogel", "episch", 58, 850, 150, "zug", "wasser"),
_("rohrweihe", "Rohrweihe", "Circus aeruginosus", "Western Marsh-Harrier",
"greifvogel", "episch", 52, 650, 120, "zug", "wasser"),
_("kornweihe", "Kornweihe", "Circus cyaneus", "Northern Harrier",
"greifvogel", "legendaer", 47, 450, 110, "teil", "offenland"),
_("fischadler", "Fischadler", "Pandion haliaetus", "Osprey",
"greifvogel", "legendaer", 57, 1500, 160, "zug", "wasser"),
_("steinadler", "Steinadler", "Aquila chrysaetos", "Golden Eagle",
"greifvogel", "legendaer", 85, 4500, 210, "stand", "gebirge"),
_("schlangenadler", "Schlangenadler", "Circaetus gallicus", "Short-toed Snake-Eagle",
"greifvogel", "legendaer", 67, 1800, 180, "zug", "offenland"),
_("gaensegeier", "Gänsegeier", "Gyps fulvus", "Eurasian Griffon",
"greifvogel", "legendaer", 100, 8000, 260, "teil", "gebirge"),
_("wanderfalke", "Wanderfalke", "Falco peregrinus", "Peregrine Falcon",
"greifvogel", "episch", 45, 800, 105, "stand", "gebirge"),
_("baumfalke", "Baumfalke", "Falco subbuteo", "Eurasian Hobby",
"greifvogel", "episch", 33, 230, 80, "zug", "offenland"),
_("merlin", "Merlin", "Falco columbarius", "Merlin",
"greifvogel", "legendaer", 28, 190, 60, "zug", "offenland"),
# ---------- Eulen ----------
_("schleiereule", "Schleiereule", "Tyto alba", "Barn Owl",
"eule", "episch", 35, 320, 90, "stand", "offenland"),
_("waldohreule", "Waldohreule", "Asio otus", "Long-eared Owl",
"eule", "episch", 36, 280, 92, "stand", "wald"),
_("sumpfohreule", "Sumpfohreule", "Asio flammeus", "Short-eared Owl",
"eule", "legendaer", 37, 330, 100, "zug", "offenland"),
_("schnee_eule", "Schnee-Eule", "Bubo scandiacus", "Snowy Owl",
"eule", "legendaer", 60, 2000, 150, "zug", "offenland"),
# ---------- Schreitvögel ----------
_("graureiher", "Graureiher", "Ardea cinerea", "Grey Heron",
"schreitvogel", "episch", 95, 1700, 180, "teil", "wasser"),
_("silberreiher", "Silberreiher", "Ardea alba", "Great Egret",
"schreitvogel", "legendaer", 95, 1200, 165, "teil", "wasser"),
_("purpurreiher", "Purpurreiher", "Ardea purpurea", "Purple Heron",
"schreitvogel", "legendaer", 85, 900, 130, "zug", "wasser"),
_("seidenreiher", "Seidenreiher", "Egretta garzetta", "Little Egret",
"schreitvogel", "legendaer", 60, 500, 95, "zug", "wasser"),
_("weissstorch", "Weißstorch", "Ciconia ciconia", "White Stork",
"schreitvogel", "episch", 105, 3400, 200, "zug", "offenland"),
_("kranich", "Kranich", "Grus grus", "Common Crane",
"schreitvogel", "legendaer", 115, 5500, 220, "zug", "offenland"),
# ---------- Hühnervögel ----------
_("fasan", "Fasan", "Phasianus colchicus", "Ring-necked Pheasant",
"huhn", "episch", 80, 1200, 80, "stand", "offenland"),
# ---------- Watvögel ----------
_("kiebitz", "Kiebitz", "Vanellus vanellus", "Northern Lapwing",
"watvogel", "episch", 30, 220, 75, "teil", "offenland"),
_("austernfischer", "Austernfischer", "Haematopus ostralegus", "Eurasian Oystercatcher",
"watvogel", "legendaer", 43, 520, 85, "teil", "wasser"),
_("saebelschnaebler", "Säbelschnäbler", "Recurvirostra avosetta", "Pied Avocet",
"watvogel", "legendaer", 44, 300, 78, "zug", "wasser"),
_("stelzenlaeufer", "Stelzenläufer", "Himantopus himantopus", "Black-winged Stilt",
"watvogel", "legendaer", 37, 180, 75, "zug", "wasser"),
_("flussregenpfeifer", "Flussregenpfeifer", "Charadrius dubius", "Little Ringed Plover",
"watvogel", "legendaer", 16, 40, 45, "zug", "wasser"),
_("sandregenpfeifer", "Sandregenpfeifer", "Charadrius hiaticula", "Common Ringed Plover",
"watvogel", "legendaer", 19, 65, 50, "zug", "wasser"),
_("bekassine", "Bekassine", "Gallinago gallinago", "Common Snipe",
"watvogel", "legendaer", 26, 110, 45, "teil", "wasser"),
_("grosser_brachvogel", "Großer Brachvogel", "Numenius arquata", "Eurasian Curlew",
"watvogel", "legendaer", 55, 800, 90, "teil", "wasser"),
_("regenbrachvogel", "Regenbrachvogel", "Numenius phaeopus", "Whimbrel",
"watvogel", "legendaer", 42, 400, 82, "zug", "wasser"),
_("rotschenkel", "Rotschenkel", "Tringa totanus", "Common Redshank",
"watvogel", "legendaer", 28, 130, 62, "teil", "wasser"),
_("gruenschenkel", "Grünschenkel", "Tringa nebularia", "Common Greenshank",
"watvogel", "legendaer", 32, 180, 70, "zug", "wasser"),
_("waldwasserlaeufer", "Waldwasserläufer", "Tringa ochropus", "Green Sandpiper",
"watvogel", "legendaer", 22, 80, 58, "zug", "wasser"),
_("bruchwasserlaeufer", "Bruchwasserläufer", "Tringa glareola", "Wood Sandpiper",
"watvogel", "legendaer", 20, 62, 56, "zug", "wasser"),
_("flussuferlaeufer", "Flussuferläufer", "Actitis hypoleucos", "Common Sandpiper",
"watvogel", "legendaer", 20, 50, 40, "zug", "wasser"),
# ---------- Möwen und Seeschwalben ----------
_("lachmoewe", "Lachmöwe", "Chroicocephalus ridibundus", "Black-headed Gull",
"moewe", "episch", 38, 280, 105, "teil", "wasser"),
_("silbermoewe", "Silbermöwe", "Larus argentatus", "Herring Gull",
"moewe", "episch", 60, 1100, 145, "teil", "wasser"),
_("sturmmoewe", "Sturmmöwe", "Larus canus", "Mew Gull",
"moewe", "legendaer", 42, 400, 115, "teil", "wasser"),
_("mantelmoewe", "Mantelmöwe", "Larus marinus", "Great Black-backed Gull",
"moewe", "legendaer", 70, 1700, 160, "teil", "wasser"),
_("heringsmoewe", "Heringsmöwe", "Larus fuscus", "Lesser Black-backed Gull",
"moewe", "legendaer", 55, 800, 140, "zug", "wasser"),
_("mittelmeermoewe", "Mittelmeermöwe", "Larus michahellis", "Yellow-legged Gull",
"moewe", "legendaer", 60, 1100, 145, "teil", "wasser"),
_("flussseeschwalbe", "Flussseeschwalbe", "Sterna hirundo", "Common Tern",
"moewe", "legendaer", 34, 130, 82, "zug", "wasser"),
_("kuestenseeschwalbe", "Küstenseeschwalbe", "Sterna paradisaea", "Arctic Tern",
"moewe", "legendaer", 35, 110, 78, "zug", "wasser"),
# ---------- Taucher und Kormoran ----------
_("kormoran", "Kormoran", "Phalacrocorax carbo", "Great Cormorant",
"taucher", "episch", 90, 2500, 140, "teil", "wasser"),
_("haubentaucher", "Haubentaucher", "Podiceps cristatus", "Great Crested Grebe",
"taucher", "legendaer", 48, 900, 88, "teil", "wasser"),
_("rothalstaucher", "Rothalstaucher", "Podiceps grisegena", "Red-necked Grebe",
"taucher", "legendaer", 45, 800, 82, "zug", "wasser"),
_("schwarzhalstaucher", "Schwarzhalstaucher", "Podiceps nigricollis", "Eared Grebe",
"taucher", "legendaer", 30, 300, 58, "zug", "wasser"),
_("zwergtaucher", "Zwergtaucher", "Tachybaptus ruficollis", "Little Grebe",
"taucher", "legendaer", 27, 150, 42, "teil", "wasser"),
# ---------- Rallen ----------
_("blaesshuhn", "Blässhuhn", "Fulica atra", "Eurasian Coot",
"ralle", "episch", 38, 750, 75, "teil", "wasser"),
_("teichhuhn", "Teichhuhn", "Gallinula chloropus", "Eurasian Moorhen",
"ralle", "episch", 33, 320, 55, "teil", "wasser"),
# ---------- Schwäne und Gänse ----------
_("hoeckerschwan", "Höckerschwan", "Cygnus olor", "Mute Swan",
"gans", "episch", 150, 11000, 230, "stand", "wasser"),
_("singschwan", "Singschwan", "Cygnus cygnus", "Whooper Swan",
"gans", "legendaer", 150, 10000, 235, "zug", "wasser"),
_("graugans", "Graugans", "Anser anser", "Greylag Goose",
"gans", "episch", 82, 3300, 160, "teil", "wasser"),
_("blaessgans", "Blässgans", "Anser albifrons", "Greater White-fronted Goose",
"gans", "legendaer", 72, 2500, 145, "zug", "wasser"),
_("kanadagans", "Kanadagans", "Branta canadensis", "Canada Goose",
"gans", "episch", 95, 4500, 170, "teil", "wasser"),
_("weisswangengans", "Weißwangengans", "Branta leucopsis", "Barnacle Goose",
"gans", "legendaer", 65, 1700, 135, "zug", "wasser"),
_("ringelgans", "Ringelgans", "Branta bernicla", "Brant",
"gans", "legendaer", 58, 1400, 115, "zug", "wasser"),
# ---------- Enten ----------
_("stockente", "Stockente", "Anas platyrhynchos", "Mallard",
"ente", "episch", 58, 1100, 90, "teil", "wasser"),
_("spiessente", "Spießente", "Anas acuta", "Northern Pintail",
"ente", "legendaer", 60, 900, 88, "zug", "wasser"),
_("krickente", "Krickente", "Anas crecca", "Green-winged Teal",
"ente", "legendaer", 36, 330, 60, "teil", "wasser"),
_("schnatterente", "Schnatterente", "Anas strepera", "Gadwall",
"ente", "legendaer", 50, 850, 88, "teil", "wasser"),
_("loeffelente", "Löffelente", "Anas clypeata", "Northern Shoveler",
"ente", "legendaer", 48, 650, 78, "zug", "wasser"),
_("pfeifente", "Pfeifente", "Anas penelope", "Eurasian Wigeon",
"ente", "legendaer", 48, 750, 82, "zug", "wasser"),
_("knaekente", "Knäkente", "Anas querquedula", "Garganey",
"ente", "legendaer", 38, 350, 63, "zug", "wasser"),
_("tafelente", "Tafelente", "Aythya ferina", "Common Pochard",
"ente", "legendaer", 46, 900, 77, "teil", "wasser"),
_("reiherente", "Reiherente", "Aythya fuligula", "Tufted Duck",
"ente", "legendaer", 43, 700, 70, "teil", "wasser"),
_("bergente", "Bergente", "Aythya marila", "Greater Scaup",
"ente", "legendaer", 46, 1000, 78, "zug", "wasser"),
]
# fmt: on
BY_SLUG = {e.slug: e for e in EXTRA}