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.
43 lines
1.8 KiB
HTML
43 lines
1.8 KiB
HTML
{% load static i18n dex_extras %}{% get_current_language as LANG %}<!doctype html>
|
|
<html lang="{{ LANG }}">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Vogelalbum</title>
|
|
<link rel="stylesheet" href="{% static_v 'css/vogelalbum.css' %}">
|
|
<style>
|
|
/* Im iframe gibt es keine Navigation und keinen Seitenrand. */
|
|
body { background: transparent; }
|
|
.wrap { padding: 0; max-width: none; }
|
|
.widget { display: flex; gap: 14px; align-items: center;
|
|
background: var(--card); border: 1px solid var(--line);
|
|
border-radius: var(--radius); padding: 14px; }
|
|
.widget img { width: 96px; height: 74px; object-fit: cover;
|
|
border-radius: 10px; background: #0b120e; flex-shrink: 0; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="wrap">
|
|
<div class="widget">
|
|
{% if latest %}
|
|
{% if latest.kachel_url %}<img src="{{ latest.kachel_url }}" alt="{{ latest.effective_species.name }}">{% endif %}
|
|
<div style="min-width:0">
|
|
<div class="sub">{% trans "Zuletzt gesehen" %}</div>
|
|
<div style="font-weight:700; font-size:18px; margin:2px 0 4px">{{ latest.effective_species.name }}</div>
|
|
<div class="sub">{{ latest.started_at|zeitpunkt }} · {% widthratio latest.confidence 1 100 %}% {% trans "sicher" %}</div>
|
|
</div>
|
|
{% else %}
|
|
<div>
|
|
<div class="sub">Vogelalbum</div>
|
|
<div style="font-weight:700; font-size:18px">{% trans "Noch kein Gast" %}</div>
|
|
</div>
|
|
{% endif %}
|
|
<div style="margin-left:auto; text-align:right; flex-shrink:0">
|
|
<div style="font-weight:800; font-size:22px">{{ progress.species_seen }}<span class="sub" style="font-size:15px">/{{ progress.species_total }}</span></div>
|
|
<div class="sub">{% trans "Arten" %}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|