Files
vehicle-counter/README.md
Joachim Hummel 63c4890c35 README: Outdoor-Setup-Hardwareliste (Box + Powerbank) ergaenzt
ESP32-CAM-Empfehlung zu einer Tabelle erweitert: wetterdichte Box und
Powerbank fuer netzunabhaengigen Aussenbetrieb (Affiliate-Links).

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

12 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 (optional) zum Empfang der Zähl-Events (z. B. Mosquitto); per MQTT_ENABLED=false abschaltbar (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. 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 mit true startet 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 .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.

📷 Hardware-Empfehlung (Outdoor-Setup):

Komponente Zweck
ESP32-CAM Die Kamera selbst günstig (~510 €), 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_URL gesetzt. Typisch für die ESP32-CAM sind Port 81 und der Pfad /stream CAMERA-IP durch 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=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_ENABLED true MQTT komplett ein-/ausschalten
    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