Beispiel-Config + reread/update/restart/status/Logs, mit Hinweis auf directory= (.env/counting_line) und Restart-Bedarf nach Code-Updates. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fahrzeug- und Objekt-Erkennungssystem
Eine webbasierte Anwendung zur Echtzeit-Objekterkennung und -Verfolgung mittels YOLOv11. Die Anwendung unterstützt sowohl Live-Webcam-Streams als auch die Verarbeitung hochgeladener Videodateien.
Funktionen
- Webcam-Erkennung: Echtzeit-Objekterkennung über die Webcam
- Video-Upload: Hochladen und Verarbeiten von Videodateien mit Objekterkennung
- Objekt-Tracking: Persistente Verfolgung von Objekten mit eindeutigen IDs über Frames hinweg
- Visuelle Markierungen: Bounding Boxes und Labels für erkannte Objekte
- Browser-basiert: Einfacher Zugriff über den Webbrowser
Voraussetzungen
- Python 3.12 oder höher
- NVIDIA-Grafikkarte mit CUDA-Unterstützung – für die Echtzeit-Erkennung erforderlich (siehe Hardware & CUDA)
- ESP32-CAM als Live-Quelle, die einen MJPEG-Stream im Netzwerk bereitstellt (siehe Kamera / Livestream (ESP32-CAM))
- MQTT-Broker (optional) zum Empfang der Zähl-Events (z. B. Mosquitto); per
MQTT_ENABLED=falseabschaltbar (siehe MQTT / Zähl-Events) - Die YOLO-Modelle werden beim ersten Start automatisch von Ultralytics geladen (Internetverbindung erforderlich)
⚠️ Wichtig: Für die flüssige Live-Erkennung wird eine NVIDIA-GPU mit CUDA benötigt. Ohne CUDA läuft die Inferenz auf der CPU und ist für Echtzeit-Streams zu langsam.
Installation
-
Repository klonen oder herunterladen
-
Erforderliche Python-Pakete installieren:
pip3 install flask opencv-python numpy ultralytics requests paho-mqtt python-dotenv
- CUDA-fähiges PyTorch installieren (für GPU-Beschleunigung). Die passende Variante richtet sich nach der installierten CUDA-Version, z. B. für CUDA 12.x:
pip3 install torch --index-url https://download.pytorch.org/whl/cu121
Prüfen, ob die GPU erkannt wird:
python3 -c "import torch; print(torch.cuda.is_available())"
Gibt der Befehl True aus, wird die NVIDIA-GPU genutzt und FP16-Inferenz
automatisch aktiviert.
- Die YOLO-Modelle (
yolo11s.ptfür Video-Upload,yolo11n.ptfür die Webcam) müssen nicht manuell beschafft werden – Ultralytics lädt sie beim ersten Start automatisch herunter (Internetverbindung erforderlich) und legt sie im Hauptverzeichnis ab.
Verwendung
Anwendung starten
python3 app.py
Die Anwendung ist dann unter http://localhost:8080 erreichbar.
Dauerbetrieb mit supervisord (24/7)
Für den Dauerbetrieb (automatischer Start, Neustart bei Absturz) eignet sich
supervisord. Beispiel-Konfiguration unter
/etc/supervisor/conf.d/vehicle-counter.conf:
[program:vehicle-counter]
directory=/pfad/zum/vehicle-counter
command=/pfad/zur/python app.py
user=DEIN_USER
autostart=true
autorestart=true
startsecs=5
stopwaitsecs=10
stdout_logfile=/var/log/vehicle-counter.log
stderr_logfile=/var/log/vehicle-counter-error.log
stdout_logfile_maxbytes=20MB
stderr_logfile_backups=5
environment=PYTHONUNBUFFERED="1"
⚠️
directory=muss auf das Projektverzeichnis zeigen! Sonst findet die App die.env(Kamera/MQTT) undcounting_line.jsonnicht und fällt auf Defaults zurück.
Aktivieren und steuern:
sudo supervisorctl reread # neue Config einlesen
sudo supervisorctl update # Programm hinzufügen/starten
sudo supervisorctl restart vehicle-counter # nach Code-Updates neu starten
sudo supervisorctl status vehicle-counter # Status prüfen
tail -f /var/log/vehicle-counter.log # Logs ansehen
Nach einem git pull mit Code-Änderungen ist ein restart nötig; reine
Template-/Frontend-Änderungen werden dank TEMPLATES_AUTO_RELOAD auch ohne
Neustart übernommen.
Konfiguration (.env)
Kamera-, MQTT- und Inferenz-Einstellungen werden über Umgebungsvariablen
gesteuert. Am einfachsten kopierst du die mitgelieferte Vorlage und passt die
Werte an – die .env wird beim Start automatisch geladen (python-dotenv):
cp .env.example .env
# anschließend .env im Editor öffnen und die Werte anpassen
Die wichtigsten Einstellungen:
export CAMERA_URL="http://CAMERA-IP:81/stream" # MJPEG-Stream der Kamera
export MQTT_ENABLED="true" # "false" = ohne Broker starten
export MQTT_HOST="127.0.0.1" # Adresse des MQTT-Brokers
export MQTT_PORT=1883
export MQTT_TOPIC="vehiclecounter/meine-kamera" # Basis-Topic der Events
export CAMERA_ID="meine-kamera" # Kennung in den Events
Eine vollständige, kommentierte Liste aller Variablen steht in
.env.example.
💡 Ohne MQTT-Broker? Setze
MQTT_ENABLED="false"– dann startet die App ganz normal, zählt und streamt, sendet aber keine MQTT-Events. Ideal zum Ausprobieren ohne Broker-Setup. (Auch mittruestartet die App übrigens, wenn der Broker gerade nicht erreichbar ist – sie verbindet sich dann später.)
⚠️ Beim Betrieb über einen Prozess-Manager (z. B. supervisord) muss das Arbeitsverzeichnis auf das Projekt zeigen (
directory=/pfad/zum/projekt), sonst wird die.envnicht gefunden und es greifen die Defaults. Die.envist per.gitignoreausgeschlossen und gehört nicht ins Repo.
Webcam-Erkennung
- Öffnen Sie
http://localhost:8080im Browser - Klicken Sie auf "Start Webcam Detection"
- Die Webcam wird aktiviert und Objekte werden in Echtzeit erkannt und markiert
- Jedes Objekt erhält eine Track-ID und Klassenbeschriftung
Video-Upload
- Öffnen Sie
http://localhost:8080im Browser - Wählen Sie eine Videodatei über das Upload-Formular aus
- Klicken Sie auf "Upload Video"
- Das Video wird verarbeitet und mit Objekterkennungen angezeigt
Projektstruktur
.
├── app.py # Haupt-Flask-Anwendung
├── yolo11s.pt # YOLOv11-Modell (wird autom. geladen, nicht versioniert)
├── yolo11n.pt # YOLOv11-Nano-Modell für Webcam (autom. geladen)
├── templates/ # HTML-Templates
│ ├── index.html # Startseite
│ ├── webcam.html # Webcam-Anzeige
│ └── play_video.html # Video-Wiedergabe
├── uploads/ # Hochgeladene Videos (automatisch erstellt)
└── highway1.mp4 # Beispielvideo
Technische Details
Kamera / Livestream (ESP32-CAM)
In diesem Beispiel dient eine ESP32-CAM als Live-Quelle. Sie stellt einen MJPEG-Stream im Netzwerk bereit, den die Anwendung abgreift, mit YOLO auswertet und an die Browser-Viewer weiterverteilt.
📷 Hardware-Empfehlung (Outdoor-Setup):
| Komponente | Zweck |
|---|---|
| ESP32-CAM | Die Kamera selbst – günstig (~5–10 €), bei Diebstahl/Defekt kein großer Verlust |
| Regenwasserdichte Box | Wetterschutz für den Außeneinsatz – Kamera und Powerbank passen hinein |
| Powerbank | Günstige Stromversorgung, macht die Kamera netzunabhängig |
Affiliate-Links – beim Kauf darüber unterstützt du das Projekt ohne Mehrkosten für dich.
- Die Stream-Adresse wird über die Umgebungsvariable
CAMERA_URLgesetzt. Typisch für die ESP32-CAM sind Port81und der Pfad/stream–CAMERA-IPdurch die IP-Adresse der eigenen Kamera ersetzen:export CAMERA_URL="http://CAMERA-IP:81/stream" - Es wird eine einzige Verbindung zur ESP32-CAM aufgebaut und das Bild an beliebig viele Zuschauer verteilt (Fan-out). So wird der begrenzte Stream-Slot der ESP32-CAM nicht durch jeden Browser blockiert.
- Mit
GRABBER_ALWAYS_ON=1läuft der Grabber rund um die Uhr und zählt auch dann, wenn niemand zuschaut. Bei0(Standard) verbindet er sich nur, solange ein Browser den Stream betrachtet – das gibt den ESP32-Slot wieder frei.
💡 Statt einer ESP32-CAM kann über
CAMERA_URLauch jede andere MJPEG-/HTTP- Stream-Quelle eingebunden werden.
MQTT / Zähl-Events
Jede erkannte Linienüberquerung wird als MQTT-Event veröffentlicht. Dafür wird ein MQTT-Broker benötigt (z. B. Mosquitto). So lassen sich die Zähldaten z. B. über n8n weiterverarbeiten und in einer Datenbank wie NocoDB ablegen.
- Die Events werden auf dem Topic
{MQTT_TOPIC}/crossingmit QoS 1 (nicht retained) publiziert. - Zusätzlich gibt es ein Status-/Availability-Topic
{MQTT_TOPIC}/status(retained): Beim Verbinden sendet die Apponline(Birth-Message), bei einem Verbindungsabbruch publiziert der Broker automatischoffline(Last Will / LWT). So lässt sich jederzeit erkennen, ob der Counter läuft. - Das Payload ist JSON, z. B.:
{ "event": "crossing", "camera": "cam1", "source": "webcam", "type": "car", "track_id": 42, "ts": "2026-06-01T12:34:56+02:00" } - Konfiguriert wird der Broker über Umgebungsvariablen:
Variable Standard Beschreibung MQTT_ENABLEDtrueMQTT komplett ein-/ausschalten MQTT_HOST127.0.0.1Adresse des MQTT-Brokers MQTT_PORT1883Broker-Port MQTT_USER– Benutzername (optional) MQTT_PASS– Passwort (optional) MQTT_TOPICvehiclecounter/cam1Basis-Topic der Events CAMERA_IDcam1Kamera-Kennung im Payload
ℹ️ Die Verbindung zum Broker erfolgt asynchron. Ist der Broker nicht erreichbar, startet die Anwendung trotzdem – es werden dann lediglich keine Events übertragen.
Hardware & CUDA
Die Objekterkennung mit YOLOv11 ist rechenintensiv. Für die Echtzeit-Verarbeitung von Live-Streams wird daher eine NVIDIA-Grafikkarte mit CUDA benötigt.
- Mit NVIDIA-GPU (CUDA): Die Inferenz läuft auf der Grafikkarte. Erkennt die
Anwendung eine CUDA-fähige GPU, wird automatisch FP16-Inferenz aktiviert
(per
YOLO_HALFüberschreibbar) – das halbiert den Speicherbedarf und erhöht die Bildrate spürbar. - Ohne GPU (nur CPU): Die Anwendung startet zwar, die Inferenz ist für Live-Streams jedoch zu langsam. Ein zusätzliches Motion-Gate sorgt dafür, dass YOLO nur bei tatsächlicher Bewegung im Bild ausgeführt wird, was die Last reduziert – ersetzt eine GPU aber nicht.
Voraussetzungen für die GPU-Nutzung:
- NVIDIA-Treiber + passende CUDA-Runtime
- CUDA-fähiges PyTorch (siehe Installation)
Verwendete Technologien
- Flask: Web-Framework für Routing und Template-Rendering
- OpenCV: Videobearbeitung und Frame-Manipulation
- Ultralytics YOLO: YOLOv11-Modell für Objekterkennung und Tracking
- NumPy: Array-Operationen für Bilddaten
Verarbeitungs-Pipeline
- Frame-Erfassung: Webcam oder Videodatei als Quelle
- Frame-Skipping: Verarbeitung jedes 2. Frames zur Leistungsoptimierung
- Größenanpassung: Alle Frames werden auf 1020x600 Pixel skaliert
- YOLO-Tracking: Objekterkennung mit persistenten Track-IDs
- Annotation: Zeichnen von Bounding Boxes und Labels
- Streaming: Übertragung als MJPEG-Stream an den Browser
Objekterkennung
- Erkennt verschiedene Objektklassen (abhängig vom YOLO-Modell)
- Vergibt eindeutige Track-IDs für jedes Objekt
- Beschriftung im Format:
{Track-ID} - {Klassenname} - Grüne Bounding Boxes um erkannte Objekte
- Magenta-farbene Textbeschriftungen
Leistungsoptimierung
- Frame-Skipping: Nur jeder 2. Frame wird verarbeitet, um CPU-Last zu reduzieren
- Feste Auflösung: Einheitliche Größe von 1020x600 Pixel für alle Frames
- Effizientes Streaming: JPEG-Kompression für Frame-Übertragung
Einschränkungen
- Keine Validierung der Upload-Dateigröße
- Keine automatische Bereinigung hochgeladener Dateien
- Feste Frame-Dimensionen (1020x600)
- Keine Fehlerbehandlung bei Webcam-Zugriffsproblemen
Hinweise
- Bei der ersten Verwendung kann das Laden des YOLO-Modells einige Sekunden dauern
- Die Erkennungsgenauigkeit hängt vom verwendeten YOLO-Modell ab
- Frame-Skipping kann bei sehr schnell bewegten Objekten zu Erkennungslücken führen
- Hochgeladene Videos werden im Ordner
uploads/gespeichert und müssen manuell gelöscht werden
Lizenz
Projekt basiert auf Ressourcen von Pyresearch

