Seite 1 von 1

Projektvorstellung: TWS-AI-Cam – KI-gestützte Objekterkennung mit Raspberry AI Cam für Timberwolf Server

Verfasst: So Aug 31, 2025 3:43 pm
von ms20de
Hallo Zusammen,

ich möchte euch mein Projekt TWS-AI-Cam vorstellen, eine Lösung zur Echtzeit-Objekterkennung mit der Raspberry Pi AI-Kamera, die direkt in die VISU des Timberwolf Servers eingebunden werden kann. Zusätzlich zum Video-Stream kann die Objekterkennung kann zur Auslösung von Aufnahmen im Timberwolf Server genutzt werden.

Das ist ein Wochenendprojekt. Nachdem die Kamera nach dem Release fast ein Jahr lang Staub auf meinem Schreibtisch angesetzt hatte, lässt sich mit dem aktuellen Stand schon einiges anfangen. Verbesserungsmöglichkeiten gibt es natürlich noch viele.

Bild


Was ist an der Raspberry Pi AI Camera besonders?

Im Gegensatz zu herkömmlichen Kameramodulen, die lediglich Bilddaten erfassen und zur Weiterverarbeitung an ein externes System weiterleiten, verfügt die Raspberry Pi AI Camera über einen integrierten KI-Beschleuniger direkt im Bildsensor. Dieser Sensor von Sony kombiniert eine 12-Megapixel-Bildaufnahme mit einem dedizierten DSP (Digital Signal Processor), der neuronale Netzwerke direkt auf dem Sensor ausführen kann. Dadurch ist es möglich, Objekterkennung in Echtzeit direkt lokal und energieeffizient auf der Kamera durchzuführen, ohne die Daten an andere Dienste senden zu müssen.

Ein vorinstalliertes Modell (MobileNetSSD) ermöglicht sofortige Objekterkennung. Die enge Integration mit dem Raspberry Pi Software-Stack (https://github.com/raspberrypi/picamera2) erlaubt eine einfache Nutzung. Mit ausreichenden Kenntnissen und Trainingsmaterial können auch eigene Modelle verwendet werden.


Was macht mein Projekt?

Die Software nutzt die Picamera2-Bibliothek und die IMX500 Hardware, um ein MJPEG-Videostream bereitzustellen, Objekte in Echtzeit zu erkennen und mit Bounding Boxes sowie Labels zu versehen, die Erkennungen als JSON-Events über MQTT zu veröffentlichen – ideal für Smart Home Automatisierungen.


Features im Überblick:
  • Live-Stream direkt in der Timberwolf VISU (Auflösung konfigurierbar)
  • Echtzeit-Objekterkennung mit KI-Modell (.rpk)
  • MQTT-Integration zur Weiterverarbeitung der Erkennungen
  • Konfigurierbare Parameter wie Bildgröße, Qualität und Schwellenwerte
  • Automatischer Start als systemd-Service auf dem Raspberry PI
  • Integration in den Timberwolf Server

Verwendete Hardware

AI Kamera https://www.raspberrypi.com/products/ai-camera/
Raspberry Pi Zero 2 W
Gehäuse habe ich in FreeCAD konstruiert und dannach ausgedruckt, falls Interesse besteht kann ich die Dateien hochladen.

GitHub

Sourcecode und Anleitung: https://github.com/ms20de-pro/tws-ai-cam
Lizenz: https://wrgt.news/TOLL

Viele Grüße
Matthias

Re: Projektvorstellung: TWS-AI-Cam – KI-gestützte Objekterkennung mit Raspberry AI Cam für Timberwolf Server

Verfasst: Mo Sep 01, 2025 5:31 pm
von jensgulow
Coole Sache. Würde ich gerne mal ausprobieren. Könntest Du die Datei für den 3D Print mal hochladen? Vorzugsweise als stl.
Dankeschön

Re: Projektvorstellung: TWS-AI-Cam – KI-gestützte Objekterkennung mit Raspberry AI Cam für Timberwolf Server

Verfasst: Mi Sep 03, 2025 12:58 pm
von ms20de
jensgulow hat geschrieben: Mo Sep 01, 2025 5:31 pm Könntest Du die Datei für den 3D Print mal hochladen? Vorzugsweise als stl.
Ja, versuche ich am Wochenende zu machen. Ich habe das vielleicht ein bisschen "over engineered" und es braucht ein paar Erklärungen.

-----

Die Erkennungen werden aktuell als JSON‑Array zurückgegeben. Zum Testen möchte ich sie kommasepariert in eine Zeitreihe speichern. Natürlich hätte ich den Python‑Code anpassen können, aber ich habe das Logic‑Code‑Prompt von @eib-eg ausprobiert. Damit konnte ich eine benutzerdefinierte Logik erstellen, die das für mich erledigt. JSON als String rein und max drei Labels zusammengefügt raus.

Code: Alles auswählen

{
  "_Meta": {
    "Description": "Extrahiert bis zu drei 'label'-Werte aus einem JSON-Array und konkateniert sie mit ', '.",
    "Version": "6.06.0",
    "Author": "Georg E. & AI",
    "Last_Update": "2025-09-02"
  },
  "Input": [
    [ "JSON-Eingabe", "Das JSON-Array vom externen System", "$P_InputJson", "a" ]
  ],
  "Output": [
    [ "Extrahierte Labels", "Die ersten drei 'label'-Werte, kommasepariert", "$O_ConcatenatedLabels", "c" ]
  ],
  "Level": [
    // Deklaration der Input-Variable im Level-Block gemäß der Systemanforderung
    [ "$P_InputJson", "string,512", "" ],
    
    // Korrigiertes Regex-Pattern für robustere Label-Extraktion
    [ "$Konst_RegexPattern", "string", "\"label\":\\s*\"([^\"]*)\"(?:.*?\"label\":\\s*\"([^\"]*)\")?(?:.*?\"label\":\\s*\"([^\"]*)\")?" ],
    [ "$Konst_EmptyString", "string", "" ],
    [ "$Konst_CommaSpace", "string", ", " ],
    [ "$Konst_CompareModeEquals", "string", "e" ],
    [ "$Konst_True", "bool", true ],
    [ "$Konst_False", "bool", false ],
    
    [ "$State_Label1", "string,32", "" ],
    [ "$State_Label2", "string,32", "" ],
    [ "$State_Label3", "string,32", "" ],
    [ "$O_ConcatenatedLabels", "string,128", "" ],
    
    [ "$Lgc_MatchFound", "bool", false ],
    [ "$State_FullMatch", "string,512", "" ], 
    
    [ "$Lgc_Label1_Is_Empty", "bool", true ], // Wird direkt in den Multiplexern negiert
    [ "$Lgc_Label2_Is_Empty", "bool", true ], // Wird direkt in den Multiplexern negiert
    [ "$Lgc_Label3_Is_Empty", "bool", true ], // Wird direkt in den Multiplexern negiert
    
    [ "$Lgc_Concat_L1_L2", "string,64", "" ],
    [ "$State_Intermediate_1_2", "string,64", "" ],
    [ "$Lgc_Concat_L12_L3", "string,128", "" ]
  ],
  "Module": [
    // 1. Extrahiere die ersten drei 'label'-Werte mittels Regex
    // Der Pattern sucht nach "label":"<Wert>" und fängt bis zu drei Werte in den Capturing Groups 1-3.
    // Die optionalen Teile (?:.*?) erlauben, dass weniger als drei Labels vorhanden sind, 
    // und überspringen flexibel alle Zeichen bis zum nächsten "label"-Key.
    [ "Regex", "$P_InputJson", "$Konst_RegexPattern", "$Lgc_MatchFound", "$State_FullMatch", "$State_Label1", "$State_Label2", "$State_Label3", 0, 0 ],

    // 2. Prüfe, ob Label1, Label2 oder Label3 leer sind
    [ "Stringcompare", "$State_Label1", "$Lgc_Label1_Is_Empty", "$Konst_EmptyString", "$Konst_CompareModeEquals" ],
    [ "Stringcompare", "$State_Label2", "$Lgc_Label2_Is_Empty", "$Konst_EmptyString", "$Konst_CompareModeEquals" ],
    [ "Stringcompare", "$State_Label3", "$Lgc_Label3_Is_Empty", "$Konst_EmptyString", "$Konst_CompareModeEquals" ],
    
    // 3. Konkateniere Label1 und Label2, falls Label2 vorhanden ist
    // Wenn Label2 vorhanden (d.h. -$Lgc_Label2_Is_Empty ist TRUE), dann "Label1, Label2", sonst nur "Label1"
    [ "Concat", [ "$State_Label1", "$Konst_CommaSpace", "$State_Label2" ], "$Lgc_Concat_L1_L2" ],
    [ "Multiplexer", [ "$State_Label1", "$Lgc_Concat_L1_L2" ], "$State_Intermediate_1_2", "-$Lgc_Label2_Is_Empty" ],

    // 4. Konkateniere das Zwischenergebnis mit Label3, falls Label3 vorhanden ist
    // Wenn Label3 vorhanden (d.h. -$Lgc_Label3_Is_Empty ist TRUE), dann "Zwischenergebnis, Label3", sonst das Zwischenergebnis
    [ "Concat", [ "$State_Intermediate_1_2", "$Konst_CommaSpace", "$State_Label3" ], "$Lgc_Concat_L12_L3" ],
    [ "Multiplexer", [ "$State_Intermediate_1_2", "$Lgc_Concat_L12_L3" ], "$O_ConcatenatedLabels", "-$Lgc_Label3_Is_Empty" ]
  ]
}
Bild

Viele Grüße,
Matthias