Object Detection in C Sharp mit Custom Vision And OnnxRuntime

[Reading Time: 9 minutes]
Table Of Contents

Etwas vorweg

Wer meine letzten Blogbeiträge gelesen hat, wird sicher Parallelen zu Diesem hier sehen. Ich habe mich seit einiger Zeit mit einem Security/Surveilance Camera Konzept beschäftigt und probiere immer wider verschiedene Ansätze aus. Hier kannst du noch einmal nachlesen.
AI Powered Security Cam:

  1. Technologie DeepDive
  2. Custom Vision
  3. ML on the Edge
  4. IoT Edge Lösung
  5. Object Detection & Tracking

Nun habe ich einmal versucht etwas an der grundlegenden Lösungsarchitektur zu ändern. Ich möchte gern eine Object Detection haben, die genau auf meine Umgebung zu geschnitten ist. Dadurch erhoffe ich mir eine bessere Performance bei der Erkennung (Geschindigkeit und Trefferquote). Es gibt einige Models, die generelle Objekte erkennen (die gängigsten sind MobileNet SSD, Yolo und verschiedene andere R-CNNs,…), aber ich hätte gern Spezifischere Labels erkannt, wie zum Beispiel “Schwiegermutter”, “Post”, “Mülltonne” usw..

1) Ich benötige dafür viele Daten/Bilder meiner Hofeinfahrt zu unterschiedlichen Jahreszeiten, Wetterbedingungen und mit unterschiedlichen OOIs (Objects of Interests) gespickt.
Das ist mittlerweile kein Thema für mich, da ich bereits seit einigen Jahren mein System am Laufen habe. In meinem Datenportfolio befinden sich nun über 55.000 Bilder und etwa gleich viele kurze Videosequenzen, die ich gern zu einem späteren Zeitpunkt für andere Zwecke auswerten möchte.

2) Als nächstes muss ich mich für eine Möglichkeit zum Trainieren eines Models entscheiden. Dazu gibt es gefühlt unzählig Viele. Ich stelle mir die Fragen: “Sollte ich alles selber trainieren?” “Lokal auf meinem PC?” “Remote, in der Cloud – Azure 😉 ?”. Ich entscheide mich für die Custom Vision API von Microsoft. Zum einen möchte ich zu Testzwecken schnell zu Ergebnissen kommenn, zum anderen, weil ich einfach zu Lazy bin, um alles per Hand aufzusetzen *LoL*. Außerdem hat die Custom Vision mittlerweile ein tolles Feature dabei, dass ich gern ausprobieren wollte (Smart Labeler) – dazu später gern mehr. Und zu guter Letzt, möchte ich das ONNX Format besser kennenlernen, welches ich komfortabel über den Export bekomme.

3) Zum Schluss muss ich mir gedanken machen, wie ich die Daten für das Training vorbereite. Für meine Custom Object Detection brauche ich also jeweils einige Bilder zu den oben genannten Kategorien (Labels). …Sollte bei 55.000 Bildern kein Problem sein. Jedoch ist das Vorbereiten geeigneter Daten schon sehr aufwendig. Wenn ich nicht jedes Bild screenen möchte, muss ich kreativ sein. Ich habe mich dafür entschieden das Vorsortieren zu automatisieren. Und so gehe ich vor:

Daten vorbereiten

Meine Bilder möchte ich in Kategorien, wie “Person”, “Auto allgemein”, “Post”, “Mülltonne” und diverse Andere aufteilen. Da diese Kategorien in generelle Kategorien fallen, kann ich mich diverser vortrainierter Modelle bedienen. Ich entscheide mich für Tiny YoloV3, da es eines der bekanntesten ist, welches eine sehr schnelle Prediction macht, recht klein ist und noch recht zuverlässige Resultate hervorbringt. Es ist nach meinen Tests recht robust bei Dämmerung im Gegensatz zu bspw. MobileNet SSD (Ich erhebe aber nicht den Anspruch einer akademischen Messung).

Mit diesem Netz kann ich nun meine Bilder in generelle Kategorien sortieren. Ich will kurz erläutern, wie ich das gelöst habe.

Falls du neugierig bist und gern sehen möchtest, worum es mir geht, schau doch bitte einfach in dieses Video.

Sortieren der Objekte in Ordern – in Action

Ich habe das Einlesen des Bilder-Ordners mit einer C# Console App realisiert und das Analysieren der Bilder über einen Docker Container, in dem Yolo verwendet wird.

Die App nimmt einen Source-Folder auf und ließt jedes einzelne Bild ein. Zur Beschleunigung habe ich das Pipeline-Pattern umgesetzt. Das Bild wid dann an die REST-Api des Docker-Containers übertragen und darin per Object Detection verarbeitet. Anschließend bekommt die Console die Labels wieder zurück und fügt sie als Exif Meta Daten dem jeweiligen Bild hinzu.

Highlevel Solution Architecture
55k Images in data source
Objects detected

Die Consolen-Anwendung fügt dem Bild die gefundenen Label als Metadaten (EXIF), zum Beispiel Titel, hinzu. Auf diese Weise kann ich komfortabel im File Explorer sortieren und filtern. Nach diesem Schritt bekomme ich langsam Ordnung in die Bilder und kann nun mit viel weniger Aufwand meine Trainingsdaten zusammen sammeln. (im obeigen Bild habe ich einmal die gefundenen Objekte per Hand markiert).

Trainieren der Daten

Als nächsten Schritt möchte ich meine spezialisierte Object Detection trainieren. Dazu verwende ich, wie oben geteasert, die Custom Vision API von Microsoft. Ich habe bereits im Artikel “Azure Custom Vision-Technology Deep Dives” über die Custom Vision geschrieben und verweise gern darauf, wenn du Details zur Handhabe brauchst. Das nachfolgende Bild demonstriert die Labels, die ich erstellt habe (es ist derzeit noch eine Mischung aus generellen Objekten und spezialisierten Objekten ).

Tags & Training images

Als eine besondere Spezialisierung habe ich ein Objekt namens “Tonne” trainiert. Ich möchte im späteren Verlauf meines Projektes detailliertere Infos über meine Umgebung haben – so zum Beispiel, ob die Mülltonne geleert wurde oder gar vom Nachbarn einfach mitgenommen 🙂 – kommt tatsächlich auch mal vor.

Special – Trashcan

Nach einigen Trainings mit Anreichern mehrerer Bilder, habe ich nun folgende Ergebnisse Erziehlt:

Performance results of training

Nun, zufrieden geben kann ich mich nicht mit diesem Ergebnis, aber für den ersten Anlauf schonmal verwendbar. (Zeitlich, wäre ich eigtl. noch beim händischen Sortieren der Bilder 🙂 )

Hier kommt übrigens noch das oben erwähnte Feature “Smart Labeler” in Spiel. Dieses sorgt dafür, dass ich beim Bearbeiten meiner noch nicht getaggten Bilder Vorschläge für bereits bekannte Tags im Bild markiert bekomme. Dazu muss ich mindestens einen Trainingsdurchlauf (Iteration) gemacht haben.

Smart Labeler – Suggested Tags

Im Bild ist zu erkennen, dass von den zur Verfügung gestellten (und bereits trainierten) Labels, das Label “V50” in drei Bildern gefunden wurde. Der Schieberegler ganz unten hilft beim Justieren – ich musste manchmal eine Confidence von 13% einstellen, damit ich komfortabler taggen konnte.

To confirm hit simply blue button

Mit diesen Schritten, habe ich nun ein ersten Schritt für mein eigenes Object Detection Model getan. Nun geht es an das Konsumieren/ Anwenden des Ergebnisses.

Anwenden des erstellten Modells

Ich habe mir das fertige Model über den Export der Custom Vision API herunter geladen. Da ich gern mehr mit dem Format ONNX arbeiten möchte, entscheide ich mich für einen solchen Export.

Export options
Export as standard ONNX

Für die Anwendung habe ich meine vorherige Lösung modifiziert (Das Video oben wurde für diese Änderung aufgenommen). Statt des Docker-Containers, habe ich nun ein weiteres Modul – ebenfalls in C# – geschrieben, welches die Bilder des Quellverzeichnisses einließt und dann anhand des heruntergeladenen ONNX Modells analysiert. Für eine schnell Bearbeitung habe ich noch eine parallel Verarbeitung mit vier gleichzeitigen Prozessen (per Core) eingebaut, die dann jeweils ein Bild gleichzeitig analysieren. Die Ergebnisse sind für diesen Stand gar nicht so schlecht; ich hätte eine geringere Qualität erwartet. Hier die Ausgabe eines Durchlaufs mit 1698 Files für den ersten Test.

Created folder structure and sorting images (1698 files)

Der Lauf benötigte 75,23s , was meiner Meinung nach, gar nicht so schlecht ist – das sind ca. 0,04s pro Bild (ohne GPU Unterstützung).

Hier folgt ein Beispiel für ein getaggtes Bild, das in den Ordner “Post” einsortiert wurde:

Post car detected (hard to read: 77.1% probability)

Das nachfolgende Bild zeigt einen erkannten “Van”. Was vermutlich schwer zu erkennen ist: rechts oben ist ein Bild-in-Bild, das den Van von einer anderen Perspektive zeigt. Hier wurde Dieser als Auto erkannt. Die Personen zwischen Van und Häuschen wurden leider nicht erkannt, was wahrscheinlich an der geringen Größe liegt.
Das andere Bild zeigt ein Postauto sowie eine Mülltonne.

Ich bin zufrieden, also lassen ich mal die Anwendung über alle Bilder laufen… . In Summe ergibt sich das folgende Ergebnis:

complete run over 55k images in under 45min

Ab hier ist es nur noch eine Frage des Fleißes, bis das Datenmodell ausreichend gut trainiert ist und es in einer richtigen Anwendung eingebaut werden kann.

Alternative zum Model Download

Natürlich kann man das Model auch ohne diesen Umweg verbessern. Die Custom Vision API hat ihren Namen aus guten Grund. Der Service kann auch via REST Calls oder eben auch mit einem SDK angesprochen werden. Dann ist die Variante von oben ebenfalls umsetzbar. Der Unterschied dazu ist lediglich, dass ich nun alles online Abfragen muss. Außerdem kann ich auch nicht das CustomVision.ai Portal nutzen, um die Objekte aus zu wählen, sondern muss mit anderen Labeling Tools arbeiten, was sicher eine gute Sache ist, für mich in diesem Projekt aber nicht im Vordergrund stand.

Falls du gern mal in den Code reinschauen möchtest oder diesen erweitern würdest, schau doch gern hier im GitHub-Repo nach.

Von Thomas

Als Director arbeite ich bei CGI in Stuttgart. Verantwortlich für das Thema Innovation im Bereich Cloud und DevOps, treibe ich mit Teams diverse Themen wie IoT, AI und Cloud voran. Dabei spielt die agile Transformation deutscher IT-Betriebe oder Ministerien ein große Rolle, genauso wie die Modernersierung von Applikationen anhand smarten Diensten. Seit fast zwei Jahrzehnten unterstütze ich als IT-Architekt, Entwickler und Coach. In der Community bin ich ebenfalls sehr aktive unterwegs. Als Host von Azure Meetup Konstnaz & Region, sowie Co-Host von Azure Meetup Stuttgart und als Co-Admin von GitHub Meetup Stuttgart, möchte ich gern Wissen und Erfahrungen mit Gleichgesinnten teilen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.