Files
vehicle-counter/README.md
Joachim Hummel 394c72d6d9 MQTT: Birth-Message + Last Will auf {MQTT_TOPIC}/status
- "online" (retained) beim (Re-)Connect via on_connect-Callback
- "offline" automatisch durch Broker bei Verbindungsabbruch (LWT)
- Abnehmer (n8n / Home Assistant) sehen jederzeit den Live-Zustand
- README um Status-/Availability-Topic ergaenzt

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 14:37:32 +02:00

10 KiB
Raw Blame History

Fahrzeug- und Objekt-Erkennungssystem

Video Demo

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 zum Empfang der Zähl-Events (z. B. Mosquitto; 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

  1. Repository klonen oder herunterladen

  2. Erforderliche Python-Pakete installieren:

pip3 install flask opencv-python numpy ultralytics requests paho-mqtt python-dotenv
  1. 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.

  1. Die YOLO-Modelle (yolo11s.pt für Video-Upload, yolo11n.pt fü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.

Konfiguration (.env)

Kamera-, MQTT- und Inferenz-Einstellungen werden über Umgebungsvariablen gesteuert. Lege dazu eine .env-Datei im Projektverzeichnis an sie wird beim Start automatisch geladen (python-dotenv):

export CAMERA_URL="http://CAMERA-IP:81/stream"
export MQTT_HOST="MQTT-HOST"
export MQTT_PORT=1883
export MQTT_TOPIC="counter/cam1"
export CAMERA_ID="cam1"

⚠️ Beim Betrieb über einen Prozess-Manager (z. B. supervisord) muss das Arbeitsverzeichnis auf das Projekt zeigen (directory=/pfad/zum/projekt), sonst wird die .env nicht gefunden und es greifen die Defaults. Die .env ist per .gitignore ausgeschlossen und gehört nicht ins Repo.

Webcam-Erkennung

  1. Öffnen Sie http://localhost:8080 im Browser
  2. Klicken Sie auf "Start Webcam Detection"
  3. Die Webcam wird aktiviert und Objekte werden in Echtzeit erkannt und markiert
  4. Jedes Objekt erhält eine Track-ID und Klassenbeschriftung

Video-Upload

  1. Öffnen Sie http://localhost:8080 im Browser
  2. Wählen Sie eine Videodatei über das Upload-Formular aus
  3. Klicken Sie auf "Upload Video"
  4. 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.

  • Die Stream-Adresse wird über die Umgebungsvariable CAMERA_URL gesetzt. Standard ist die typische ESP32-CAM-Adresse (Port 81, Pfad /stream):
    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=1 läuft der Grabber rund um die Uhr und zählt auch dann, wenn niemand zuschaut. Bei 0 (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_URL auch 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}/crossing mit QoS 1 (nicht retained) publiziert.
  • Zusätzlich gibt es ein Status-/Availability-Topic {MQTT_TOPIC}/status (retained): Beim Verbinden sendet die App online (Birth-Message), bei einem Verbindungsabbruch publiziert der Broker automatisch offline (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_HOST 127.0.0.1 Adresse des MQTT-Brokers
    MQTT_PORT 1883 Broker-Port
    MQTT_USER Benutzername (optional)
    MQTT_PASS Passwort (optional)
    MQTT_TOPIC vehiclecounter/cam1 Basis-Topic der Events
    CAMERA_ID cam1 Kamera-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

  1. Frame-Erfassung: Webcam oder Videodatei als Quelle
  2. Frame-Skipping: Verarbeitung jedes 2. Frames zur Leistungsoptimierung
  3. Größenanpassung: Alle Frames werden auf 1020x600 Pixel skaliert
  4. YOLO-Tracking: Objekterkennung mit persistenten Track-IDs
  5. Annotation: Zeichnen von Bounding Boxes und Labels
  6. 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