Sortierung & Filter
24.11.2024
Mattis Thieme
EinleitungEinleitung
Herzlich Willkommen! Probleme der Bilderkennung und Bildverarbeitung gewinnen immer mehr an Relevanz. Kein Wunder: Mit der stetigen Verbreitung von mobilen Endgeräten haben immer mehr Systeme Zugriff auf eine (mittlerweile sehr hochwertige) Kamera. Die Möglichkeiten, die sich dadurch ergeben, sind vielfältig: über das Scannen von Dokumenten, hin zur Klassifizierung von Tieren und Pflanzen bis hin zum industriellen Einsatz in der Qualitätskontrolle.Zusätzlich geht der Trend auch in die Richtung von Onlineservices und Webanwendungen. Programme die früher noch installiert werden mussten, laufen nun direkt im Browser des Clients - entweder als online gehostete Webseite oder lokal in Form einer Cross-Plattform-Desktop-Anwendung. Hauptgrund ist natürlich die Plattformunabhängigkeit und die damit verbundene Reduktion von Entwicklungskosten und Zeit.Aber wie sieht es mit Bildverarbeitung und Bilderkennung im Webkontext aus? Wenn Probleme im Bereich der Bildverarbeitung gelöst werden sollen, fällt die Wahl häufig auf OpenCV. Und das nicht ohne Grund: OpenCV bietet ein riesiges Spektrum an Funktionen und Algorithmen, von einfachen Bildoperationen hin zu ausgereiften Algorithmen der Gesichtserkennung, Bildsegmentierung und Objekterkennung. Auch Maschinelles Lernen und Deep Learning sind im Funktionsumfang von OpenCV enthalten.Jedoch wurde OpenCV nun einmal in C++ geschrieben und kann somit nicht direkt auf Clientseite implementiert werden. Aber nicht immer ist die Option sinnvoll, Aufgaben der Bildverarbeitung auf der Seite des Servers lösen zu lassen. Nicht immer steht die benötigte Rechenleistung zur Verfügung, auch die Latenz kann letztendlich je nach Anwendungsfalls ein Problem darstellen. Somit stellt sich einem die folgende Frage: Ist es möglich OpenCV auch im Browser des Clients zu lösen? Die Antwort: Ja! Mit openCV.js.
26.11.2024
Mattis Thieme
EinleitungMotivation
Aber warum der Blog? Einst musste ich (wie du vielleicht auch) ein Problem der Bildverarbeitung lösen, welches zwingend im Webkontext stattfinden sollte. Die Anforderungen waren klar: die Bildverarbeitung sollte direkt im Browser des Clients stattfinden, ohne dass der Nutzer eine zusätzliche Software installieren muss.Die Bibliothek openCV war natürlich die erste Wahl, jedoch stand ich nun genau vor diesem Problem: wie bekomme ich openCV, eine Bibliothek, die ursprünglich in C++ geschrieben ist, in meiner Webanwendung zum Laufen? Meine Lösung war natürlich openCV.js.Als relativ neuer Bestandteil des openCV-Projektes, ist openCV.js eine JavaScript-Portierung der OpenCV-Bibliothek. Sie ermöglicht es, OpenCV-Funktionen direkt im Browser auszuführen, ohne dass der Nutzer eine zusätzliche Software installieren muss. Somit können wir die volle Bandbreite der OpenCV-Funktionen nutzen, ohne auf die Vorteile einer Webanwendung verzichten zu müssen.Obwohl es sich zunächst als die beste Lösung angehört hat, war die Nutzung von openCV.js jedoch kein Selbstläufer. Wie du wahrscheinlich bereits mit Schrecken festgestellt hast, ist die offizielle Dokumentation nur für die C++ Schnittstelle geschrieben, und Tutorials für openCV.js sind leider rar gesät. Die JavaScript-Schnittstelle von openCV ist nun mal die neuste Änderung des mittlerweile 20 Jahre alten Projektes und somit noch nicht so ausgereift und erprobt wie die anderen Schnittstellen.Genau aus diesen Gründen habe ich mich für das Schreiben dieses Devblogs entschieden. Ich möchte meine Erfahrungen und Erkenntnisse teilen, um anderen Entwicklern zu helfen, die vor dem gleichen Problem stehen. Ich möchte zeigen, dass es gar nicht so kompliziert ist, openCV.js in einer Webanwendung zu nutzen und wie mächtig die Bibliothek tatsächlich ist. Ja es gibt ein paar Eigenheiten und Macken, aber genau diese werde ich erläutern, damit du nicht die gleichen Fehler machst wie sie ich einst gemacht habe.
28.11.2024
Mattis Thieme
EinleitungZielsetzung
Kommen wir nun zu den eigentlichen Fragen: Was möchte ich erreichen? Was möchte ich entwickeln? Wie bereits oben erwähnt, möchte ich eine Webanwendung erstellen, welche durch Nutzung von openCV.js Probleme der Bildverarbeitung und Bilderkennung lösen kann. Das konkrete Problem sollte dabei sowohl häufig genutzte Methoden der Bildverarbeitung abdecken, als auch leicht verständlich und reproduzierbar sein. Ich möchte, dass du die Anwendung einfach nachbauen und selber ausprobieren kannst, um die Funktionsweise von openCV.js direkt durch eigene Erfahrungen zu erlernen.Nach einigen Überlegungen bin ich auf die Idee gekommen, eine Webanwendung zu entwickeln, welche Münzen erkennen und deren Wert bestimmen kann. Warum ausgerechnet Münzen? Zum einen ist es ein angemessen komplexes Problem, welches gleich mehrere unterschiedliche Aspekte der Bildverarbeitung abdeckt. Zum anderen ist es eine Problemstellung, welche sich leicht auf einem anderen System reproduzieren lässt. Alles was du brauchst, sind lediglich eine Webkamera und ein paar Münzen.Interessiert? Dann lass uns anfangen! Im meinem nächsten Beitrag werde ich direkt die grundlegende Webseitenstruktur und die Einbindung von openCV.js erläutern.Bis dahin!
30.11.2024
Mattis Thieme
EinrichtungGrundaufbau der Website
Nun stellt sich die Frage: Welche Funktionen soll unsere Webseite haben? Zum einen brauchen wir natürlich Zugriff auf die Kamera des Nutzers, um den Videostream zu erhalten. Zum anderen benötigen wir eine Möglichkeit, das Ergebnis der Bildverarbeitung anzuzeigen.Mithilfe eines Video-Elementes können wir den Kamerastream von Webkameras anzeigen und auf diesen zugreifen. Für die Anzeige der Bildverarbeitungsergebnisse habe ich mich für ein Canvas-Element entschieden. Warum? - In OpenCV gibt es viele Möglichkeiten, Zeichenvorgänge auf Matrizen anzuwenden. Diese Matrizen können dann auf ein Canvas-Element gezeichnet werden (mehr dazu weiter unten). Mein Plan ist somit alle relevanten Ergebnisse direkt auf den zu verarbeitenden Frame zu zeichnen und diesen dann auf dem Canvas-Element anzuzeigen.Nach einigen Tests habe ich mich für folgende Struktur entschieden:Als nächstes braucht es nun grundlegende Methoden, um auf die Kamera des Nutzers zuzugreifen und den Videostream auf dem Video-Element anzuzeigen.
02.12.2024
Mattis Thieme
ProgrammierungGrundlegende OpenCV-Methoden
Um auf die Kamera des Nutzers zuzugreifen, kann man unter anderem ein openCV-VideoCapture-Objekt verwenden. Dieses Objekt kann entweder direkt auf ein Video-Element zugreifen oder auf eine Datei. Da wir in unserem Fall den Kamerastream verwenden wollen, greifen wir direkt auf das Video-Element zu. Für den Zugriff auf die Webkamera benötigen wir die getUserMedia()-Methode des MediaDevices-Interfaces. Um sicherzustellen, dass openCV vollständig geladen ist, warten wir zusätzlich auf das "load"-Event des Fensters und initialisieren erst dann die Kamera:Nun haben wir das Grundgerüst für unsere Webseite erstellt. Als nächstes können wir uns an die Implementierung der ersten Bildverarbeitungsalgorithmen wie der Kreiserkennung machen. Mehr dazu gibt es im nächsten Eintrag. Bis bald!
04.12.2024
Mattis Thieme
ProgrammierungTesting
Meine Idee ist es, einen HTML-Slider erstellen zu können, mit dem ich schnell und einfach den Wert einer beliebigen JS-Variable verändern kann. Diese Slider sollen sowohl den aktuellen Wert der Variable anzeigen als auch bei Interaktion des Benutzers ihre zugewiesene Variable verändern. Der Wert des HTMl-Elementes soll somit direkt mit der Variable synchronisiert werden.Für die Slider habe ich die Bibliothek noUISlider verwendet. Über die data-Attribute von den HTML-Elementen kann unkompliziert der Wertebereich und die Schrittweite des Sliders festgelegt werden.Nun müsste aber standardmäßig ein Event-Listener für jeden Slider erstellt werden, der bei Veränderung den Wert einer Variable ändert. Da ich jedoch nicht für jede Variable einen eigenen Event-Listener erstellen möchte, habe ich mich für einen anderen Ansatz entschieden. Stattdessen soll man direkt im HTML-Element des Sliders angeben können, welche Variable durch diesen Slider verändert werden soll.Hierfür benötigen wir zunächst ein eigenes data-Attribute , in welchem der Name der zu verändernden Variable angegeben wird. Zum Zweiten benötigen wir eine Funktion, die alle Slider-Elemente durchgeht und für jedes Element mithilfe des data-Attributs den Event-Listener für die angegebene Variable erstellt. Hierfür braucht es eine Möglichkeit den String-Namen der Variable in eine Referenz auf die Variable umzuwandeln. Dies kann mithilfe der eval()-Funktion erreicht werden.Die Event-Listener Funktion sieht dann wie folgt aus:Wie du vielleicht gesehen hast, gibt es auch noch die Funktionen SetSliderValueFromCookie() und SetSliderCookie(). Diese Funktionen dienen dazu, die Werte der Slider in Cookies zu speichern und beim Laden der Webseite wiederherzustellen. So behalten die Slider ihre eingestellten Werte auch nach einem Neuladen der Webseite.
06.12.2024
Mattis Thieme
ProgrammierungCookies
Cookies sind kleine Textdateien, die auf dem Computer des Benutzers gespeichert werden. Wie du sicherlich bereits weißt, dienen sie unter anderem dem Zweck, Informationen Session-übergreifend zu speichern. In meinem Fall möchte ich die Werte der Slider speichern, um sie beim Neuladen der Webseite wiederherzustellen.Jedoch ist das Speichern von Werten in Cookies nicht ganz trivial: Pro Cookie kann nur ein einziger String mit einer maximalen Länge von 4096 Bytes gespeichert werden. Da die Werte der Slider jedoch Arrays von Zahlen sind, müssen diese erst in einen String umgewandelt werden. Hierfür habe ich mich für die JSON.stringify()-Funktion entschieden, die ein JavaScript-Objekt in einen JSON-String umwandelt. Die Funktion zum schreiben des Cookies sieht dann wie folgt aus:Nun habe ich endlich eine solide Möglichkeit geschaffen, schnell und unkompliziert Variablen zur Laufzeit zu verändern und diese Änderungen sogar über einen Neustart der Webseite hinweg zu speichern. Dies wird mir hoffentlich eine Menge Zeit und Nerven sparen, wenn ich nun im nächsten Blogeintrag mit der Implementierung der Kreiserkennung beginne.
12.12.2024
Mattis Thieme
ProgrammierungKreiserkennung
Um Kreise in einem Bild zu erkennen, gibt es in OpenCV.js praktischerweise bereits eine fertige Methode, die dies für uns übernimmt. Diese Methode heißt cv.HoughCircles und verwendet die HoughTransformation, um Kreise in einem Bild zu finden. Die Methode hat folgende Signatur:Bei den Parametern dp, param1 und param2 stellte sich mir nun die Frage, welche Werte ich hier verwenden soll. Eine pauschale Antwort darauf gibt es nicht, da die optimalen Werte wie bereits erwähnt stark vom Bild, vom Verwendungszweck und in meinem Beispiel auch von der Kamera abhängen.Um nun die passenden Werte ausfindig zu machen, habe ich den Mainloop so angepasst, dass in einer Schleife die Kreiserkennung auf dem aktuellen Kamera-Frame durchgeführt wird. Die gefundenen Kreise werden dann auf eine separate "GUI-Matrix"gezeichnet, die dann auf dem Bildschirm angezeigt wird. Durch das Verändern der Parameter per Slider konnte ich so direkt die Auswirkungen auf die Kreiserkennung sehen.Letztendlich habe ich bei diesen Werten sehr gute Ergebnisse erzielt:dp = 2minDist = 18param1 = 230param2 = 129minRadius = 18 maxRadius = 67Dies bedeutet nicht, dass diese Werte auch für andere Anwendungsfälle optimal sind. Je nach Lichtverhältnissen, Kamerawinkel und Bildqualität können diese Werte stark variieren. Wenn du also die Kreiserkennung in deinem eigenen Projekt verwenden möchtest, empfehle ich dir wärmstens, die Parameter selbst zu testen und anzupassen.Mit der Kreiserkennung fertig implementiert, sind wir dem Ziel, Münzen zu erkennen, ein ganzes Stück näher gekommen. Jetzt wo wir Kreise (und somit auch Münzen) im Bild erkennen können, können wir uns daran machen, die Münzen zu klassifizieren. Dazu aber mehr beim nächsten Eintrag.
20.12.2024
Mattis Thieme
ProgrammierungTemplate Matching
Für das eigentliche Template-Matching benutzte ich in openCV.js die folgende Funktion:Diese Funktion erstellt eine Maske, die nur die Pixel enthält, die zum Kreis gehören. Um die Maske anwenden zu können, muss die Matrix in ihre einzelnen Kanäle aufgeteilt werden. Anschließend wird die Maske auf jeden Kanal angewendet, bevor die Kanäle wieder zu einem Bild zusammengefügt werden. Das Ergebnis ist ein Bild, welches nur die Pixel enthält, die zum Kreis gehören. Dieses Bild wird dann zurückgegeben.
23.12.2024
Mattis Thieme
ProgrammierungExkursExkurs: Mehrere Matrizen in einem Canvas
Bei wachsender Komplexität der Webanwendung ob ich mir immer wieder gewünscht eine Möglichkeit zu haben, mehrere Matrizen in einem Canvas anzuzeigen. Dies ist standardmäßig in openCV.js nicht vorgesehen, da die Funktion cv.imshow() immer nur eine Matrix anzeigen kann. Also habe ich mir eine eigene Funktion geschrieben, die mehrere Matrizen in einem Canvas anzeigen kann. Diese Funktion sieht so aus:Um mehrere Bilder in einen Canvas zu zeichnen, musste ich die Größe der Bilder anpassen, damit sie in ein Grid passen. Dafür habe ich die Funktion cv.resize() verwendet. Anschließend müssen die Matrizen zuerst in ein temporäres Canvas gezeichnet werden, bevor sie in das Haupt-Canvas gezeichnet werden können. Die Funktion drawImage() von Canvas kann nur Bilder zeichnen, keine Matrizen. Daher musste ich die Matrizen in ein ImageData-Objekt umwandeln, bevor ich sie in das Canvas zeichnen konnte.
28.12.2024
Mattis Thieme
AuswertungErste Ergebnisse
Es hat sich gezeigt, dass der Vergleich der Vorlagen prinzipiell funktionieren kann. Jedoch ist die Genauigkeit noch nicht zufriedenstellend. Münzen können aktuell zwar grob in die richtige Kategorie eingeordnet werden (sprich 1-2-5 Cent Münzen und 10-20-50 Cent Münzen), jedoch ist die Unterscheidung innerhalb dieser Kategorien nicht funktional. So werden aktuell nur maximal die Hälfte der Münzen korrekt zugeordnet.Es scheint, als wären die Informationen der Ziffern auf den Münzen nicht ausreichend, um eine genaue Klassifizierung zu ermöglichen. Die Farbe einer Münze hat im Gegensatz dazu einen relativ großen Einfluss auf das Ergebnis. So werden Münzen meist der korrekten Farbkategorie zugeordnet, jedoch nicht dem korrekten Wert. Dies ist ein Hinweis darauf, dass die Farbinformationen der Münzen stärker gewichtet werden als die Forminformationen. Da sich Münzen innerhalb einer Kategorie (z.B. 1-2-5 Cent Münzen) jedoch nur in der Größe und ihrer Ziffer optisch unterscheiden, ist es schwierig eine weitere Methode der Klassifizierung zu finden. Ein Prüfen der Größe würde in meinem Anwendungsfall nicht funktionieren, da sowohl der Abstand zur Kamera als auch die Position der Münzen im Bild variabel sind.Eine Möglichkeit die Genauigkeit zu erhöhen wäre es, den störenden Faktor der Farbinformationen zu eliminieren, und stattdessen nur Vorlagen zu verwenden, welche nur die notwendigen Informationen enthalten. Dies könnte z.B. durch das Erstellen von Kantenbildern der Münzen erreicht werden. Solche Bilder wie sie vom Canny-Algorithmus erstellt werden, enthalten nur die Kanten des Ausgangsbildes und keine Farbinformationen, da sie rein als Schwarz-Weiß-Bilder vorliegen. Diese Kantenbilder könnten dann an Stelle der aktuellen Farbbilder als Vorlagen verwendet werden.Jedoch gibt es noch ein weiteres Problem: die Rotation. Bereits eine kleine Drehung des Ausgangsbildes verursacht große Unterschiede in der Übereinstimmung. Das Template Matching in openCV berechnet standardmäßig nur die Übereinstimmung für das Template in der gleichen Rotation wie das Bild. Dies ist ein Problem, da die Münzen im Kamerabild in unterschiedlichen Rotationen vorkommen können. Eine Möglichkeit dieses Problem zu lösen wäre es, das Template in verschiedenen Rotationen zu speichern und für jede Rotation die Übereinstimmung zu berechnen. Dies würde jedoch die Anzahl der Vorlagen vervielfachen und einen unverhältnismäßig hohen Aufwand bedeuten. Eine andere Möglichkeit wäre es, das Ausgangsbild mehrfach zu rotieren und für jede Rotation die Übereinstimmung zu den Vorlagen berechnen. So wäre bei ausreichend kleinen Rotationsschritten sichergestellt, dass jede Münze mindestens einmal eine ähnliche Ausrichtung wie das zutreffende Template hat. Dies würde jedoch die Rechenzeit signifikant erhöhen, da bedeutend mehr Berechnungen pro Münze durchgeführt werden müssten. Zudem braucht es dafür eine Möglichkeit, alle Zwischenergebnisse der Rotationen zu speichern, um anschließend das beste Ergebnis zu wählen.Alles in allem ein durchwachsenes Ergebnis. Die Klassifizierung der Münzen ist noch nicht zufriedenstellend, jedoch gibt es noch viele Möglichkeiten, die Genauigkeit zu erhöhen. Ich werde mich in den nächsten Tagen mit diesen Möglichkeiten beschäftigen und einige Änderungen vornehmen. Hoffentlich kann ich so die Genauigkeit der Klassifizierung noch um einiges erhöhen.
02.01.2025
Mattis Thieme
AuswertungProgrammierungAnpassungen
Da ich nun jeden Kreis mehrfach drehe und die Kantenerkennung für jedes Bild neu berechnen muss, dauert der Prozess des Template Matchings sehr lange. Der ursprüngliche Plan, die Methode in einer Schleife aufzurufen und das Ergebnis in Echtzeit anzuzeigen, ist somit nicht mehr möglich. Daher habe ich mich dazu entschieden, die Methode asynchron zu machen und einen Ladebalken einzufügen, der den Fortschritt anzeigt.Ein Ladebalken kann in OpenCV relativ leicht mittels einigen Rechtecken erstellt werden:Diese Zeile bewirkt, dass der Interpreter die Methode verlässt und erst nach Ablauf der Zeit, die in setTimeout übergeben wird, wieder zurückkehrt. Da die Zeit auf 0 gesetzt ist, wird die Methode direkt im nächsten Frame fortgesetzt. Dies gibt dem Browser jedoch die Möglichkeit, andere Aufgaben zu erledigen.
07.01.2025
Mattis Thieme
AuswertungErgebnisse
Meine finale MatchTemplate-Funktion sieht nun so aus:Nun kommt der Moment der Wahrheit. Wie gut funktioniert die Münzerkennung? Um dies zu überprüfen, habe ich eine kleine Testreihe durchgeführt, bei der ich für 3 verschiedene Einstellungen je 5 Bilder aufgenommen habe. Die Einstellungen waren:180 CCOEFF _NORMED - 180 Iterationen, Vergleichsmethode CCOEFF _NORMED180 SQDIFF _NORMED - 180 Iterationen, Vergleichsmethode SQDIFF _NORMED360 CCOEFF _NORMED - 360 Iterationen, Vergleichsmethode CCOEFF _NORMEDNachdem ich für jede Einstellung 5 verschiedene Bilder aufgenommen ung geprüft habe, bei denen alle 8 Münzen in zufälliger Rotation und Position auf einem Tisch lagen, bin ich zu folgendem Ergebnis gekommen:180 CCOEFF _NORMED - Durchschnittliche Erfolgsrate: 67,5%180 SQDIFF _NORMED - Durchschnittliche Erfolgsrate: 60,0%360 CCOEFF _NORMED - Durchschnittliche Erfolgsrate: 62,5%Die Erfolgsrate ist dabei definiert als die Anzahl der Durchläufe, bei denen die Münze korrekt klassifiziert wurde, geteilt durch die Gesamtanzahl der Durchläufe.Anschließend habe ich für die Einstellungen mit dem besten Ergebnis (180 CCOEFF _NORMED) eine weitere Testreihe mit 10 Bildern durchgeführt, um etwas aussagekräftigere Werte zu erhalten. Jedes Bild hatte wie in der vorherigen Testreihe wieder alle verfügbaren Euromünzen in einem zufälligen Winkel abgebildet. Die Ergebnisse sind in folgender Abbildung dargestellt:Wie man sofort sieht, gibt es starke Unterschiede in der Erfolgsrate der einzelnen Münzen. Während die 2-Euro Münze in fast allen Fällen korrekt erkannt wurde, lag die Erfolgsquote für die 1 Euro Münze nur bei etwa 30%. Neben der 2-Euro Münze werden auch die 20-Cent, 2-Cent und 1-Cent Münzen in den meisten Fällen (>50%) korrekt erkannt. Dagegen werden die 1-Euro, 50-Cent und 5-Cent Münzen nur in etwa 30-40% der Fälle korrekt erkannt. Für die 10-Cent Münze liegt die Erfolgsrate bei etwa 50%. Insgesamt beträgt die durchschnittliche Erfolgsrate für alle Münzen somit 62,5%.Alles in allem wieder recht durchwachsene Ergebnisse. Zwar konnte ich durch meine Änderungen die Erfolgsrate im Vergleich zu meinem letzten Blogbeitrag auf über 50% steigern, jedoch ist dies immer noch weit von einer zuverlässigen Münzerkennung entfernt. Die Kantenerkennung scheint dabei der richtige Weg gewesen zu sein, dennoch scheint sie noch nicht einwandfrei zu funktionieren. Die Kanten-Bilder der Vorlagen sehen nahezu perfekt aus, jedoch scheinen besonders die zu prüfenden Münzen nicht immer in ein verwertbares Kantenbild umgewandelt zu werden. Es hat sich als sehr schwierig erwiesen Parameter zu finden, welche für alle Münzen ein gutes Ergebnis liefern, sodass die Konturen der Ziffer klar erkennbar sind, jedoch nicht zu viele Störungen vorhanden sind.Ich denke jedoch, dass ich dennoch beweisen konnte, dass mittels Template-Matching und OpenCV.js eine Münzerkennung im Browser möglich ist. Die Ergebnisse könnten sicherlich mit etwas weiterer Feinjustierung verbessert werden, jedoch würde dies den Rahmen dieses Blogs sprengen. Jener Blog neigt sich nun auch dem Ende zu, daher möchte ich im nächsten Abschnitt noch ein Fazit ziehen und einen Ausblick auf mögliche Weiterentwicklungen geben.
09.01.2025
Mattis Thieme
AuswertungFazit
Das war mein Blog über den CoinFinder! Ich hoffe, dass ich dir einen guten Einblick in die Möglichkeiten von OpenCV.js geben konnte und dass du jetzt ein besseres Verständnis dafür hast, wie Bildverarbeitungsalgorithmen im Browser implementiert werden können. In diesem Abschnitt werde ich noch einmal kurz zusammenfassen, was für mich die größten Probleme und Herausforderungen bei der Implementierung waren und einen Ausblick darauf geben, wie das Projekt in Zukunft weiterentwickelt werden könnte. Vielen Dank schonmal fürs Lesen!Ich hoffe mit diesem Blog einen Einblick in die Möglichkeiten von OpenCV.js gegeben zu haben. Die Implementierung von Bildverarbeitungsalgorithmen im Browser ist eine spannende Entwicklung, die in Zukunft sicherlich noch an Bedeutung gewinnen wird. Selbst wenn die letztendlichen Ergebnisse des CoinFinders nicht perfekt sind, so zeigt das Projekt doch sehr gut, für welche verschiedene Anwendungsfälle OpenCV.js genutzt werden kann.Man darf nicht vergessen, dass die Kreiserkennung und das Template-Matching, wie ich es in diesem Blog implementiert habe, nur ein kleiner Teil der Möglichkeiten von OpenCV sind. OpenCV bietet eine Vielzahl von weiteren Funktionen, die womöglich auch für das Problem des CoinFinders verwendet werden könnten. So gibt es in OpenCV weitere Möglichkeiten der Objekterkennung, welche mithilfe von Deep Neural Networks (DNN) realisiert werden. Diese sind natürlich deutlich komplizierter und aufwendiger zu implementieren als die Methoden die ich in diesem Blog vorgestellt habe, sie könnten jedoch auch deutlich bessere Ergebnisse liefern. Dies wäre eine spannende Weiterentwicklung des Projekts, welche jedoch den Scope dieses Blogs übersteigen würde. Aber vielleicht ist das ja ein Thema für einen weiteren Blog?Lasst mich gerne wissen, was ihr von dem Blog haltet und ob ihr euch eine Fortsetzung wünscht. Ich freue mich über Feedback und Anregungen!