Release Candidate 1 zur V 4.5 veröffentlicht

Verehrte Insider, es wäre toll, wenn Ihr diese Version zeitnah installieren und testen könntet, da wir die Hauptversion 4.5 bei guten Rückmeldungen noch diese Woche veröffentlichen wollen. Danke Euch.

Release Notes: https://elabnet.atlassian.net/wiki/x/AQBIyQ

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

User-Geschichten zu erfolgreichen Projekten wie Migrationen vom Wiregate, Eigenbauten, usw.
Forumsregeln
  • Denke bitte an aussagekräftige Titel und gebe dort auch die [Firmware] an. Wenn ETS oder CometVisu beteiligt sind, dann auch deren Version
  • Bitte mache vollständige Angaben zu Deinem Server, dessen ID und dem Online-Status in Deiner Signatur. Hilfreich ist oft auch die Beschreibung der angeschlossener Hardware sowie die verwendeten Protokolle
  • Beschreibe Dein Projekt und Dein Problem bitte vollständig. Achte bitte darauf, dass auf Screenshots die Statusleiste sichtbar ist
  • Bitte sei stets freundlich und wohlwollend, bleibe beim Thema und unterschreibe mit deinem Vornamen. Bitte lese alle Regeln, die Du hier findest: https://wiki.timberwolf.io/Forenregeln
Antworten

Ersteller
ms20de
Elaborated Networks
Elaborated Networks
Beiträge: 1296
Registriert: Sa Aug 11, 2018 9:14 pm
Hat sich bedankt: 375 Mal
Danksagung erhalten: 780 Mal

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

#1

Beitrag 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
[ Timberwolf Entwicklung ]

TWS 2400 ID:102 VPN offen, Reboot auf Nachfrage
TWS 3500 ID:695 VPN offen, Bitte kein Reboot ohne Absprache
Benutzeravatar

jensgulow
Beiträge: 488
Registriert: Fr Apr 19, 2019 4:37 pm
Wohnort: Leipzig
Hat sich bedankt: 79 Mal
Danksagung erhalten: 211 Mal

#2

Beitrag 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
Viele Grüße

Jens

_____________________________________________________________________
TWS 2600#394 , TWS 3500L#1051, TWS 3500XL#1691 VPN offen, Reboot erlaubt

Ersteller
ms20de
Elaborated Networks
Elaborated Networks
Beiträge: 1296
Registriert: Sa Aug 11, 2018 9:14 pm
Hat sich bedankt: 375 Mal
Danksagung erhalten: 780 Mal

#3

Beitrag 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
Zuletzt geändert von ms20de am Mi Sep 03, 2025 12:59 pm, insgesamt 1-mal geändert.
[ Timberwolf Entwicklung ]

TWS 2400 ID:102 VPN offen, Reboot auf Nachfrage
TWS 3500 ID:695 VPN offen, Bitte kein Reboot ohne Absprache
Benutzeravatar

jensgulow
Beiträge: 488
Registriert: Fr Apr 19, 2019 4:37 pm
Wohnort: Leipzig
Hat sich bedankt: 79 Mal
Danksagung erhalten: 211 Mal

#4

Beitrag von jensgulow »

@ms20de Hallo Matthias....habe jetzt die ai-kamera erhalten. Wollte nochmal nach der Druckdatei fragen.
Danke!
Viele Grüße

Jens

_____________________________________________________________________
TWS 2600#394 , TWS 3500L#1051, TWS 3500XL#1691 VPN offen, Reboot erlaubt
Benutzeravatar

jensgulow
Beiträge: 488
Registriert: Fr Apr 19, 2019 4:37 pm
Wohnort: Leipzig
Hat sich bedankt: 79 Mal
Danksagung erhalten: 211 Mal

#5

Beitrag von jensgulow »

Habe nunmehr die ersten Tests gemacht. Primär funktioniert das gut.
Es gibt aber noch einige Stolpersteine.
Zum einen wird der zero2W ziemlich heiß (habe nur kleine Kühlrippen aufgeklebt). Eventuell ist dies auch der Grund wieso das System nach gewisser Zeit "einfriert". Vorher habe ich um erkannte Objekte immer mehrere Markierungsrahmen (die alten werden nicht aus der Ansicht gelöscht). Auch funktioniert die Logik noch nicht so gehärtet wie ich mir das vorstelle, es kommt ja über mqtt sehr viel input - allerdings ändert sich die Ausgabe der Logik nicht zufriedenstellend (z.B. wenn 2 Objekte erkannt wurden und dann 1 entfernt wird bleibt das Ergebnis trotzdem das mit den 2 Objekten).
Ich probiere die nächsten Tage mal weiter und werde ggf. berichten (habe mir extra einen Raspi4 bestellt mit aktiver Kühlung.....mal sehen).
tws-ai-cam-01.jpg
Ach und zur oben genannten tws-ai-cam:
Da ich die bookworm-Variante des Raspi OS aufgespielt habe ist es nicht möglich via pip3 nativ python Programme aufzuspielen - hierzu musste ich eine virtuelle Umgebung erstellen und alle Abhängigkeiten da hinein installieren.
Hintergund siehe hier:
https://pimoroni.github.io/venv-python/
Das erforderte natürlich auch die Pfade in der Installation als Service anzupassen.
Kann ich auch mal zur Verfügung stellen - falls gewünscht. Aber um da eine Installationsanleitung zu verfassen mit allen Einzelschritten braucht es noch etwas Zeit (die bei mir gerade etwas knapp ist ;-))
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Zuletzt geändert von jensgulow am Fr Sep 19, 2025 6:03 pm, insgesamt 1-mal geändert.
Viele Grüße

Jens

_____________________________________________________________________
TWS 2600#394 , TWS 3500L#1051, TWS 3500XL#1691 VPN offen, Reboot erlaubt

Ersteller
ms20de
Elaborated Networks
Elaborated Networks
Beiträge: 1296
Registriert: Sa Aug 11, 2018 9:14 pm
Hat sich bedankt: 375 Mal
Danksagung erhalten: 780 Mal

#6

Beitrag von ms20de »

Hallo Jens,

manchmal tritt das Problem mit den vielen Rahmen bei mir auch auf. Mein Verdacht ist, dass es bei schneller Bewegung passiert. Vielleicht ist auch noch ein Programmierfehler drin. Versuche mal den Parameter --movement-threshold auf 20 zu setzen, diese Einstellung habe ich gerade bei mir. Es hängt wahrscheinlich auch damit zusammen, wie groß der Abstand des Objekts zu Kamera ist.

Ich hatte die letzten Wochen nicht soviel Zeit, seitdem läuft ein Raspberry und das Programm ohne Abstürze durch. Mein Load über 5 Minuten ist 0,7 und die CPU Temperatur aus cat /sys/class/thermal/thermal_zone0/temp ist 74 °C bei 27 °C Außentemperatur im geschlossenen Gehäuse. Ich habe 800x600 und die Vorgabe Framerate, das war mir aktuell ausreichend. Ich habe auch nur einen kleinen Kühlkörper auf die CPU geklebt, von irgendeinem anderen Projekt übrigblieben.

Viele Grüße,
Matthias
[ Timberwolf Entwicklung ]

TWS 2400 ID:102 VPN offen, Reboot auf Nachfrage
TWS 3500 ID:695 VPN offen, Bitte kein Reboot ohne Absprache
Benutzeravatar

jensgulow
Beiträge: 488
Registriert: Fr Apr 19, 2019 4:37 pm
Wohnort: Leipzig
Hat sich bedankt: 79 Mal
Danksagung erhalten: 211 Mal

#7

Beitrag von jensgulow »

ich habe das Problem mit den vielfachen Boxen mal einer KI geschildert. Sie hat mir mehrere mHionweise gegeben. Seitdem läuft es stabiler.
Wenn Du willst kann ich das demnächst hier mal hochladen (allerdings gibt es ja von Seiten mancher User gewisse Bedenken gegenüber KI-Content)....
Viele Grüße

Jens

_____________________________________________________________________
TWS 2600#394 , TWS 3500L#1051, TWS 3500XL#1691 VPN offen, Reboot erlaubt

Ersteller
ms20de
Elaborated Networks
Elaborated Networks
Beiträge: 1296
Registriert: Sa Aug 11, 2018 9:14 pm
Hat sich bedankt: 375 Mal
Danksagung erhalten: 780 Mal

#8

Beitrag von ms20de »



Hier noch mein aktuelles Gehäuse. Freecad und 3mf Dateien der drei Teile in Anlage.
Ich habe die Teile in PETG gedruckt.

Deckel

Hier habe ich transparentes PETG genutzt, damit man die LEDs des PI sehen kann, ist Geschmackssache.
Der Deckel hat eine Lippe in die man Silikon einbringen kann und eine Dichtung zu schaffen und den Deckel festhält.
Die Idee den Deckel erst nachdem das Silikon gehärtet ist in das Unterteil zu stecken, sonst bekommt man es wahrscheinlich nie wieder auf. Überflüssiges Silikon mit Cutter-Messer entfernen. Wenn keine Lust auf Silkiongeschmiere, kann man den Deckel auch einfach mit einem Kabelbinder fixieren, oder den Deckel leicht vergrößern für "friction-fit".
Die Kamera-Linse sollte genau in das Loch passen, auch die Fokussierung sollte durch vorsichtiges Aufdrücken und drehen des Hilfsrings der der Kamera beilag klappen. Die Kamera habe ich durch direktes Schrauben von zwei sehr kleinen Maschinenschrauben in die Abstandshalter befestigt.

Unterteil

Hat vier Abstandshalter für den Pi Zero 2 W. Diagonal habe ich zwei Einschmelzgewinde eingesetzt, vier Stück fand ich übertrieben.
Unter den Abstandshalter ist genug Platz das Kabel der Kamera darunter zu falten, zu starke Knicke würde ich vermeiden.
Ein kleines Loch unten für den Austritt von Feuchtigkeit.
Ein größeres Loch an der Seite um ein abgeschnittenes USB-Kabel zur Stromversorgung einzuführen.
Innen habe Silikon bei der Kabeleinführung zur Zugentlastung und Abdichtung eingebracht.
Die +5V und GND habe ich an die (GPIO) Pinheader angelötet. Hier ganz aufmerksam arbeiten, da kein Verpolungsschutz existiert.

Halter
www.amazon.de/dp/B0D5M46GHW
Ich hatte diese Kamera-Halterungen rumliegen es gehen sicher auch andere.
Bei dem Einschmelzgewinde-Satz waren 1/4 Zoll - 20 UNC dabei.
Ich haben den Halter auf das Unterteil mit Plastikkleber geklebt, das bekommt man nicht mehr auseinander.


Viele Grüße,
Matthias
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Zuletzt geändert von ms20de am Sa Sep 20, 2025 3:56 pm, insgesamt 1-mal geändert.
[ Timberwolf Entwicklung ]

TWS 2400 ID:102 VPN offen, Reboot auf Nachfrage
TWS 3500 ID:695 VPN offen, Bitte kein Reboot ohne Absprache
Benutzeravatar

jensgulow
Beiträge: 488
Registriert: Fr Apr 19, 2019 4:37 pm
Wohnort: Leipzig
Hat sich bedankt: 79 Mal
Danksagung erhalten: 211 Mal

#9

Beitrag von jensgulow »

Ich bin weiter am probieren.
Da mir aufgefallen war, dass die Logik zwar 1-3 Objekte erkennt und kommasepariert ausgibt, jedoch bei "Nulldetektion" immer das letzte label 1 stehen blieb habe ich die Logik im Module-Teil um eine abschließende Prüfung auf "Nulldetektion" erweitert ($Lgc_MatchFound ist dann ja false)
siehe hier:

Code: Alles auswählen

  "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" ],
    
    //zum Schluss der Fall, dass eigentlich überhaupt kein Treffer (match) zu verzeichnen war -> $Lgc_MatchFound ist 0 -> dann auch leeren String ausgeben
    ["Latch","$Konst_EmptyString","$O_ConcatenatedLabels","-$Lgc_MatchFound",0]
  ]
Ausserdem hänge ich mal meine aktuelle cam_mpeg.py-Datei mit an (einfach die .txt in eine .py umbenennen). Wer es mal ausprobieren möchte....
. Es gibt Veränderungen in der detection, welche die "Mehrfachrahmen" reduzieren soll und ausserdem sendet es nun nur bei label-Änderung (Anzahl oder Inhalt, nicht jedoch Positionierung) eine neue mqtt-Nachricht (bei bewegten Objekten gab es eine irre Flut an Nachrichten, weil jeder kleine Bewegung eine neue Nachricht auslöste).
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Viele Grüße

Jens

_____________________________________________________________________
TWS 2600#394 , TWS 3500L#1051, TWS 3500XL#1691 VPN offen, Reboot erlaubt
Antworten

Zurück zu „Erfolgsgeschichten“