Eines der interessantesten Projekte, an denen ich in den letzten Jahren gearbeitet habe, war ein Projekt zur Bildverarbeitung . Das Ziel war es, ein System zu entwickeln, mit dem Coca-Cola -Dosen erkannt werden können (beachten Sie, dass ich das Wort "Dosen" betone, Sie werden gleich sehen, warum). Unten sehen Sie ein Beispiel, wobei die Dose im grünen Rechteck mit Skalierung und Drehung erkannt wird .
Einige Einschränkungen für das Projekt:
- Der Hintergrund kann sehr laut sein.
- Die Dose könnte jede Skala oder Rotation oder sogar Ausrichtung (in Grenzen).
- Das Bild kann einen gewissen Grad an Unschärfe aufweisen (Konturen sind möglicherweise nicht ganz gerade).
- Das Bild könnte Coca-Cola-Flaschen enthalten, und der Algorithmus sollte nur die Dose erkennen !
- Die Helligkeit des Bildes kann stark variieren (Sie können sich also nicht "zu sehr" auf die Farberkennung verlassen).
- Die Dose könnte teilweise an den Seiten oder in der Mitte und möglicherweise teilweise hinter einer Flasche versteckt sein.
- Das Bild konnte überhaupt keine Dose enthalten. In diesem Fall musste man nichts finden und eine entsprechende Nachricht schreiben.
Sie könnten also mit solchen kniffligen Dingen enden (bei denen mein Algorithmus in diesem Fall völlig versagt hat):
Ich habe dieses Projekt vor einiger Zeit gemacht und hatte viel Spaß dabei, und ich hatte eine anständige Implementierung. Hier einige Details zu meiner Implementierung:
Sprache : Fertig in C ++ mit OpenCV- Bibliothek.
Vorverarbeitung : Für die Bildvorverarbeitung, dh die Umwandlung des Bildes in eine rohere Form, um sie dem Algorithmus zu geben, habe ich zwei Methoden verwendet:
- Ändern des Farbbereichs von RGB zu HSV und Filtern basierend auf dem "roten" Farbton, Sättigung über einem bestimmten Schwellenwert, um orangefarbene Farben zu vermeiden, und Filtern eines niedrigen Werts, um dunkle Töne zu vermeiden. Das Endergebnis war ein binäres Schwarzweißbild, bei dem alle weißen Pixel die Pixel darstellen, die diesem Schwellenwert entsprechen. Natürlich ist immer noch viel Mist im Bild, aber dies reduziert die Anzahl der Dimensionen, mit denen Sie arbeiten müssen.
- Rauschfilterung mithilfe der Medianfilterung (wobei der mittlere Pixelwert aller Nachbarn verwendet und das Pixel durch diesen Wert ersetzt wird), um das Rauschen zu reduzieren.
- Verwenden des Canny Edge Detection-Filters , um die Konturen aller Elemente nach zwei vorhergehenden Schritten abzurufen.
Algorithmus : Der Algorithmus selbst, den ich für diese Aufgabe ausgewählt habe, stammt aus diesem großartigen Buch über Feature-Extraktion und heißt Generalized Hough Transform (ziemlich anders als die reguläre Hough Transform). Es sagt im Grunde ein paar Dinge:
- Sie können ein Objekt im Raum beschreiben, ohne seine analytische Gleichung zu kennen (was hier der Fall ist).
- Es ist beständig gegen Bildverformungen wie Skalierung und Drehung, da es Ihr Bild grundsätzlich für jede Kombination aus Skalierungsfaktor und Rotationsfaktor testet.
- Es verwendet ein Basismodell (eine Vorlage), das der Algorithmus "lernt".
- Jedes im Konturbild verbleibende Pixel stimmt für ein anderes Pixel, das angeblich der Mittelpunkt (in Bezug auf die Schwerkraft) Ihres Objekts ist, basierend auf dem, was es aus dem Modell gelernt hat.
Am Ende erhalten Sie eine Heatmap der Stimmen. Hier stimmen beispielsweise alle Pixel der Kontur der Dose für ihr Gravitationszentrum ab, sodass Sie viele Stimmen in demselben Pixel haben, das dem entspricht Mitte, und wird einen Peak in der Heatmap wie folgt sehen:
Sobald Sie das haben, kann eine einfache schwellenwertbasierte Heuristik Ihnen die Position des mittleren Pixels geben, aus der Sie die Skalierung und Drehung ableiten und dann Ihr kleines Rechteck darum zeichnen können (die endgültige Skalierung und der Rotationsfaktor sind offensichtlich relativ zu Ihrer Originalvorlage). Zumindest theoretisch ...
Ergebnisse : Während dieser Ansatz in den Grundfällen funktionierte, fehlte er in einigen Bereichen erheblich:
- Es ist extrem langsam ! Ich betone das nicht genug. Es wurde fast ein ganzer Tag benötigt, um die 30 Testbilder zu verarbeiten, offensichtlich, weil ich einen sehr hohen Skalierungsfaktor für Rotation und Translation hatte, da einige der Dosen sehr klein waren.
- Es ging völlig verloren, als Flaschen im Bild waren, und aus irgendeinem Grund fand man fast immer die Flasche anstelle der Dose (vielleicht weil die Flaschen größer waren, also mehr Pixel hatten, also mehr Stimmen)
- Fuzzy-Bilder waren auch nicht gut, da die Stimmen an zufälligen Stellen in der Mitte in Pixel endeten und somit mit einer sehr verrauschten Wärmekarte endeten.
- Eine Abweichung in Bezug auf Translation und Rotation wurde erreicht, jedoch nicht in Bezug auf die Ausrichtung, was bedeutet, dass eine Dose, die nicht direkt auf das Kameraobjektiv gerichtet war, nicht erkannt wurde.
Können Sie mir helfen, meinen spezifischen Algorithmus zu verbessern , indem ich ausschließlich OpenCV- Funktionen verwende, um die vier genannten spezifischen Probleme zu lösen ?
Ich hoffe, dass einige Leute auch etwas daraus lernen werden, schließlich denke ich, dass nicht nur Leute, die Fragen stellen, lernen sollten. :) :)