Mit welchen Bildverarbeitungstechniken kann eine Anwendung implementiert werden, die die in den folgenden Bildern gezeigten Weihnachtsbäume erkennt?
Ich suche nach Lösungen, die an all diesen Bildern funktionieren. Daher sind Ansätze, die das Training von Haarkaskadenklassifikatoren oder den Vorlagenabgleich erfordern, nicht sehr interessant.
Ich suche etwas, das in jeder Programmiersprache geschrieben werden kann, solange es nur Open Source- Technologien verwendet. Die Lösung muss mit den Bildern getestet werden, die für diese Frage freigegeben sind. Es gibt 6 Eingabebilder und die Antwort sollte die Ergebnisse der Verarbeitung jedes einzelnen anzeigen. Schließlich wird für jedes Ausgangsbild muss es rote Linien ziehen , um den erfassten Baum zu umgeben.
Wie würden Sie die Bäume in diesen Bildern programmgesteuert erkennen?
quelle
Antworten:
Ich habe einen Ansatz, den ich interessant finde und der sich ein bisschen von den anderen unterscheidet. Der Hauptunterschied in meinem Ansatz im Vergleich zu einigen anderen besteht darin, wie der Bildsegmentierungsschritt ausgeführt wird. Ich habe den DBSCAN- Clustering-Algorithmus aus Pythons Scikit-Learn verwendet. Es ist optimiert, um etwas amorphe Formen zu finden, die möglicherweise nicht unbedingt einen einzigen klaren Schwerpunkt haben.
Auf der obersten Ebene ist mein Ansatz ziemlich einfach und kann in ungefähr 3 Schritte unterteilt werden. Zuerst wende ich einen Schwellenwert an (oder tatsächlich das logische "oder" von zwei getrennten und unterschiedlichen Schwellenwerten). Wie bei vielen anderen Antworten nahm ich an, dass der Weihnachtsbaum eines der helleren Objekte in der Szene sein würde, daher ist die erste Schwelle nur ein einfacher monochromer Helligkeitstest. Alle Pixel mit Werten über 220 auf einer Skala von 0 bis 255 (wobei Schwarz 0 und Weiß 255 ist) werden in einem binären Schwarzweißbild gespeichert. Die zweite Schwelle versucht, nach roten und gelben Lichtern zu suchen, die in den Bäumen oben links und unten rechts in den sechs Bildern besonders hervorstechen und sich gut von dem blaugrünen Hintergrund abheben, der auf den meisten Fotos vorherrscht. Ich konvertiere das RGB-Bild in HSV-Raum, und verlangen, dass der Farbton entweder weniger als 0,2 auf einer Skala von 0,0 bis 1,0 (entspricht ungefähr der Grenze zwischen Gelb und Grün) oder mehr als 0,95 (entspricht der Grenze zwischen Lila und Rot) beträgt, und zusätzlich benötige ich helle, gesättigte Farben: Sättigung und Wert müssen beide über 0,7 liegen. Die Ergebnisse der beiden Schwellenwertverfahren sind logisch "oder" miteinander verknüpft, und die resultierende Matrix von Schwarzweiß-Binärbildern ist unten dargestellt:
Sie können deutlich sehen, dass jedes Bild eine große Pixelgruppe hat, die ungefähr der Position jedes Baums entspricht, und einige der Bilder haben auch einige andere kleine Gruppen, die entweder Lichtern in den Fenstern einiger Gebäude oder a entsprechen Hintergrundszene am Horizont. Der nächste Schritt besteht darin, den Computer zu erkennen, dass es sich um separate Cluster handelt, und jedes Pixel korrekt mit einer Clustermitgliedschafts-ID zu kennzeichnen.
Für diese Aufgabe habe ich DBSCAN gewählt . Es gibt einen ziemlich guten visuellen Vergleich des Verhaltens von DBSCAN im Vergleich zu anderen hier verfügbaren Clustering-Algorithmen . Wie ich bereits sagte, eignet es sich gut für amorphe Formen. Die Ausgabe von DBSCAN, wobei jeder Cluster in einer anderen Farbe dargestellt ist, wird hier gezeigt:
Bei der Betrachtung dieses Ergebnisses sind einige Dinge zu beachten. Erstens muss der Benutzer bei DBSCAN einen "Proximity" -Parameter festlegen, um sein Verhalten zu regulieren. Dieser steuert effektiv, wie getrennt ein Punktpaar sein muss, damit der Algorithmus einen neuen separaten Cluster deklarieren kann, anstatt einen Testpunkt zu agglomerieren ein bereits vorhandener Cluster. Ich habe diesen Wert auf das 0,04-fache der Größe entlang der Diagonale jedes Bildes eingestellt. Da die Größe der Bilder von ungefähr VGA bis ungefähr HD 1080 variiert, ist diese Art der skalierungsbezogenen Definition von entscheidender Bedeutung.
Ein weiterer erwähnenswerter Punkt ist, dass der DBSCAN-Algorithmus, wie er in Scikit-Learn implementiert ist, Speicherbeschränkungen aufweist, die für einige der größeren Bilder in diesem Beispiel ziemlich schwierig sind. Daher musste ich für einige der größeren Bilder tatsächlich jeden Cluster "dezimieren" (dh nur jedes 3. oder 4. Pixel beibehalten und die anderen löschen), um innerhalb dieser Grenze zu bleiben. Infolge dieses Keulungsprozesses sind die verbleibenden einzelnen Pixel mit geringer Dichte auf einigen der größeren Bilder schwer zu sehen. Daher wurden die farbcodierten Pixel in den obigen Bildern nur zu Anzeigezwecken effektiv nur geringfügig "erweitert", damit sie besser hervorstechen. Es ist eine rein kosmetische Operation für die Erzählung; obwohl es Kommentare gibt, die diese Erweiterung in meinem Code erwähnen,
Sobald die Cluster identifiziert und beschriftet sind, ist der dritte und letzte Schritt einfach: Ich nehme einfach den größten Cluster in jedem Bild (in diesem Fall habe ich mich entschieden, die "Größe" in Bezug auf die Gesamtzahl der Elementpixel zu messen, obwohl dies möglich ist haben genauso einfach stattdessen eine Art Metrik verwendet, die die physikalische Ausdehnung misst) und die konvexe Hülle für diesen Cluster berechnet. Die konvexe Hülle wird dann zur Baumgrenze. Die sechs konvexen Hüllen, die mit dieser Methode berechnet wurden, sind unten rot dargestellt:
Der Quellcode ist für Python 2.7.6 geschrieben und hängt von numpy , scipy , matplotlib und scikit-learn ab . Ich habe es in zwei Teile geteilt. Der erste Teil ist für die eigentliche Bildverarbeitung verantwortlich:
und der zweite Teil ist ein Skript auf Benutzerebene, das die erste Datei aufruft und alle obigen Diagramme generiert:
quelle
scipy.ndimage.filters.maximum_filter()
derselben Stelle ersetzen, an der ich einen Schwellenwert verwendet habe.HINWEIS BEARBEITEN: Ich habe diesen Beitrag bearbeitet, um (i) jedes Baumbild einzeln zu verarbeiten, wie in den Anforderungen gefordert, (ii) um sowohl die Objekthelligkeit als auch die Form zu berücksichtigen, um die Qualität des Ergebnisses zu verbessern.
Im Folgenden wird ein Ansatz vorgestellt, der die Helligkeit und Form des Objekts berücksichtigt. Mit anderen Worten, es wird nach Objekten mit dreieckiger Form und signifikanter Helligkeit gesucht. Es wurde in Java unter Verwendung des Marvin- Bildverarbeitungsframeworks implementiert .
Der erste Schritt ist die Farbschwelle. Ziel ist es, die Analyse auf Objekte mit erheblicher Helligkeit zu konzentrieren.
Ausgabebilder:
Quellcode:
Im zweiten Schritt werden die hellsten Punkte im Bild erweitert, um Formen zu bilden. Das Ergebnis dieses Prozesses ist die wahrscheinliche Form der Objekte mit signifikanter Helligkeit. Bei Anwendung der Flutungssegmentierung werden nicht verbundene Formen erkannt.
Ausgabebilder:
Quellcode:
Wie im Ausgabebild gezeigt, wurden mehrere Formen erkannt. Bei diesem Problem gibt es nur wenige helle Punkte in den Bildern. Dieser Ansatz wurde jedoch implementiert, um komplexere Szenarien zu behandeln.
Im nächsten Schritt wird jede Form analysiert. Ein einfacher Algorithmus erkennt Formen mit einem Muster ähnlich einem Dreieck. Der Algorithmus analysiert die Objektform zeilenweise. Wenn der Massenmittelpunkt jeder Formlinie nahezu gleich ist (bei einem Schwellenwert) und die Masse mit zunehmendem y zunimmt, hat das Objekt eine dreieckige Form. Die Masse der Formlinie ist die Anzahl der Pixel in dieser Linie, die zur Form gehört. Stellen Sie sich vor, Sie schneiden das Objekt horizontal und analysieren jedes horizontale Segment. Wenn sie zueinander zentralisiert sind und die Länge in einem linearen Muster vom ersten zum letzten Segment zunimmt, haben Sie wahrscheinlich ein Objekt, das einem Dreieck ähnelt.
Quellcode:
Schließlich wird die Position jeder Form, die einem Dreieck ähnelt und eine signifikante Helligkeit aufweist, in diesem Fall ein Weihnachtsbaum, im Originalbild hervorgehoben, wie unten gezeigt.
endgültige Ausgabebilder:
endgültiger Quellcode:
Der Vorteil dieses Ansatzes ist die Tatsache, dass er wahrscheinlich mit Bildern funktioniert, die andere leuchtende Objekte enthalten, da er die Objektform analysiert.
Fröhliche Weihnachten!
BEARBEITEN SIE HINWEIS 2
Es gibt eine Diskussion über die Ähnlichkeit der Ausgabebilder dieser Lösung und einiger anderer. In der Tat sind sie sehr ähnlich. Dieser Ansatz segmentiert jedoch nicht nur Objekte. In gewissem Sinne werden auch die Objektformen analysiert. Es kann mehrere leuchtende Objekte in derselben Szene verarbeiten. Tatsächlich muss der Weihnachtsbaum nicht der hellste sein. Ich schreibe es nur auf, um die Diskussion zu bereichern. In den Beispielen gibt es eine Tendenz, dass Sie nur nach dem hellsten Objekt suchen und die Bäume finden. Aber wollen wir die Diskussion an dieser Stelle wirklich beenden? Inwieweit erkennt der Computer zu diesem Zeitpunkt tatsächlich ein Objekt, das einem Weihnachtsbaum ähnelt? Versuchen wir, diese Lücke zu schließen.
Nachfolgend finden Sie ein Ergebnis, um diesen Punkt zu erläutern:
Eingabebild
Ausgabe
quelle
Hier ist meine einfache und dumme Lösung. Es basiert auf der Annahme, dass der Baum das hellste und größte Ding auf dem Bild sein wird.
Der erste Schritt besteht darin, die hellsten Pixel im Bild zu erkennen, aber wir müssen zwischen dem Baum selbst und dem Schnee unterscheiden, der sein Licht reflektiert. Hier versuchen wir, den Schnee auszuschließen, indem wir einen wirklich einfachen Filter auf die Farbcodes anwenden:
Dann finden wir jedes "helle" Pixel:
Schließlich verbinden wir die beiden Ergebnisse:
Jetzt suchen wir nach dem größten hellen Objekt:
Jetzt haben wir es fast geschafft, aber es gibt immer noch einige Unvollkommenheiten aufgrund des Schnees. Um sie abzuschneiden, erstellen wir eine Maske mit einem Kreis und einem Rechteck, um die Form eines Baumes zu approximieren und unerwünschte Teile zu löschen:
Der letzte Schritt besteht darin, die Kontur unseres Baumes zu finden und auf das Originalbild zu zeichnen.
Es tut mir leid, aber im Moment habe ich eine schlechte Verbindung, so dass ich keine Bilder hochladen kann. Ich werde es später versuchen.
Fröhliche Weihnachten.
BEARBEITEN:
Hier einige Bilder der endgültigen Ausgabe:
quelle
./christmas_tree ./*.png
. Sie können beliebig viele sein. Die Ergebnisse werden nacheinander angezeigt, wenn Sie eine beliebige Taste drücken. Ist das falsch?<img src="http://i.stack.imgur.com/nmzwj.png" width="210" height="150">
Ich habe den Code in Matlab R2007a geschrieben. Ich habe k-means verwendet, um den Weihnachtsbaum grob zu extrahieren. Ich werde mein Zwischenergebnis nur mit einem Bild und die Endergebnisse mit allen sechs zeigen.
Zuerst habe ich den RGB-Raum auf den Lab-Raum abgebildet, wodurch der Kontrast von Rot in seinem b-Kanal verbessert werden könnte:
Neben dem Merkmal im Farbraum habe ich auch ein Texturmerkmal verwendet, das für die Nachbarschaft relevant ist und nicht für jedes Pixel selbst. Hier habe ich die Intensität der 3 Originalkanäle (R, G, B) linear kombiniert. Der Grund, warum ich auf diese Weise formatiert habe, ist, dass die Weihnachtsbäume auf dem Bild alle rote Lichter und manchmal auch grüne / manchmal blaue Beleuchtung haben.
Ich habe ein lokales 3X3-Binärmuster
I0
angewendet, das mittlere Pixel als Schwellenwert verwendet und den Kontrast erhalten, indem ich die Differenz zwischen dem mittleren Pixelintensitätswert über dem Schwellenwert und dem Mittelwert darunter berechnet habe.Da ich insgesamt 4 Features habe, würde ich in meiner Clustering-Methode K = 5 wählen. Der Code für k-means ist unten dargestellt (er stammt aus dem maschinellen Lernkurs von Dr. Andrew Ng. Ich habe den Kurs zuvor besucht und den Code selbst in seine Programmieraufgabe geschrieben).
Da das Programm auf meinem Computer sehr langsam läuft, habe ich nur 3 Iterationen ausgeführt. Normalerweise ist das Stoppkriterium (i) eine Iterationszeit von mindestens 10 oder (ii) keine Änderung mehr an den Zentroiden. Nach meinem Test kann eine Erhöhung der Iteration den Hintergrund (Himmel und Baum, Himmel und Gebäude, ...) genauer unterscheiden, zeigte jedoch keine drastischen Änderungen bei der Weihnachtsbaumextraktion. Beachten Sie auch, dass k-means nicht gegen die zufällige Schwerpunktinitialisierung immun ist. Daher wird empfohlen, das Programm mehrmals auszuführen, um einen Vergleich durchzuführen.
Nach dem k-Mittel wurde der markierte Bereich mit der maximalen Intensität von
I0
gewählt. Die Grenzverfolgung wurde verwendet, um die Grenzen zu extrahieren. Für mich ist der letzte Weihnachtsbaum am schwierigsten zu extrahieren, da der Kontrast in diesem Bild nicht hoch genug ist, wie in den ersten fünf. Ein weiteres Problem bei meiner Methode ist, dass ich diebwboundaries
Funktion in Matlab verwendet habe, um die Grenze zu verfolgen, aber manchmal sind auch die inneren Grenzen enthalten, wie Sie in den Ergebnissen 3, 5 und 6 sehen können. Die dunkle Seite innerhalb der Weihnachtsbäume lässt sich nicht nur nicht mit der beleuchteten Seite gruppieren, sondern führt auch dazu, dass so viele winzige innere Grenzen nachgezeichnet werden (imfill
verbessert sich nicht sehr). Insgesamt hat mein Algorithmus noch viel Verbesserungsraum.Einige Veröffentlichungen weisen darauf hin, dass die Mittelwertverschiebung robuster sein kann als die k-Mittelwerte, und viele auf Graph-Cut basierende Algorithmen sind auch bei der Segmentierung komplizierter Grenzen sehr wettbewerbsfähig. Ich habe selbst einen Mean-Shift-Algorithmus geschrieben, der die Regionen ohne genügend Licht besser zu extrahieren scheint. Die Mittelwertverschiebung ist jedoch etwas übersegmentiert, und es ist eine Strategie der Zusammenführung erforderlich. Es lief sogar viel langsamer als k-means in meinem Computer, ich fürchte, ich muss es aufgeben. Ich freue mich sehr darauf, dass andere hier mit den oben genannten modernen Algorithmen hervorragende Ergebnisse erzielen.
Ich glaube jedoch immer, dass die Merkmalsauswahl die Schlüsselkomponente bei der Bildsegmentierung ist. Mit einer geeigneten Merkmalsauswahl, die den Abstand zwischen Objekt und Hintergrund maximieren kann, funktionieren viele Segmentierungsalgorithmen definitiv. Verschiedene Algorithmen können das Ergebnis von 1 auf 10 verbessern, aber die Merkmalsauswahl kann es von 0 auf 1 verbessern.
Fröhliche Weihnachten !
quelle
Dies ist mein letzter Beitrag unter Verwendung der traditionellen Bildverarbeitungsansätze ...
Hier kombiniere ich irgendwie meine beiden anderen Vorschläge, um noch bessere Ergebnisse zu erzielen . Tatsächlich kann ich nicht sehen, wie diese Ergebnisse besser sein könnten (insbesondere wenn Sie sich die maskierten Bilder ansehen, die die Methode erzeugt).
Im Zentrum des Ansatzes steht die Kombination von drei Hauptannahmen :
Unter Berücksichtigung dieser Annahmen funktioniert die Methode wie folgt:
Hier ist der Code in MATLAB (wieder lädt das Skript alle JPG-Bilder in den aktuellen Ordner und dies ist wiederum weit davon entfernt, ein optimierter Code zu sein):
Ergebnisse
Hier sind noch hochauflösende Ergebnisse verfügbar!
Weitere Experimente mit zusätzlichen Bildern finden Sie hier.
quelle
Meine Lösungsschritte:
R-Kanal abrufen (von RGB) - alle Operationen, die wir auf diesem Kanal ausführen:
Region of Interest (ROI) erstellen
Schwellenwert R-Kanal mit Mindestwert 149 (Bild oben rechts)
Ergebnisbereich erweitern (Bild Mitte links)
Erkennen Sie Eges in berechneten Roi. Baum hat viele Kanten (Bild Mitte rechts)
Ergebnis erweitern
Erodieren mit größerem Radius (Bild unten links)
Wählen Sie das größte (nach Fläche) Objekt aus - es ist die Ergebnisregion
ConvexHull (Baum ist konvexes Polygon) (Bild unten rechts)
Begrenzungsrahmen (Bild unten rechts - Grren-Feld)
Schritt für Schritt:
Das erste Ergebnis - am einfachsten, aber nicht in Open Source-Software - "Adaptive Vision Studio + Adaptive Vision Library": Dies ist kein Open Source, aber sehr schnell zum Prototyp:
Ganzer Algorithmus zur Erkennung des Weihnachtsbaums (11 Blöcke):
Nächster Schritt. Wir wollen eine Open Source Lösung. Ändern Sie AVL-Filter in OpenCV-Filter: Hier habe ich kleine Änderungen vorgenommen, z. B. Kantenerkennung. Verwenden Sie den cvCanny-Filter. Um dies zu respektieren, habe ich das Regionsbild mit dem Kantenbild multipliziert, um das größte Element auszuwählen, das ich gefunden habe.
https://www.youtube.com/watch?v=sfjB3MigLH0&index=1&list=UUpSRrkMHNHiLDXgylwhWNQQ
Ich kann jetzt keine Bilder mit Zwischenschritten anzeigen, da ich nur 2 Links einfügen kann.
Ok, jetzt verwenden wir OpenSource-Filter, aber es ist noch nicht ganz Open Source. Letzter Schritt - Port auf C ++ - Code. Ich habe OpenCV in Version 2.4.4 verwendet
Das Ergebnis des endgültigen C ++ - Codes ist:
C ++ - Code ist auch ziemlich kurz:
quelle
std::max_element()
Anruf umschreiben ? Ich möchte auch Ihre Antwort belohnen. Ich glaube ich habe gcc 4.2.... eine weitere altmodische Lösung - rein basierend auf der HSV-Verarbeitung :
Ein Wort zur Heuristik in der HSV-Verarbeitung:
Natürlich kann man mit zahlreichen anderen Möglichkeiten experimentieren, um diesen Ansatz zu verfeinern ...
Hier ist der MATLAB-Code, um den Trick auszuführen (Warnung: Der Code ist weit davon entfernt, optimiert zu werden !!! Ich habe Techniken verwendet, die für die MATLAB-Programmierung nicht empfohlen wurden, nur um irgendetwas im Prozess verfolgen zu können - dies kann stark optimiert werden):
Ergebnisse:
In den Ergebnissen zeige ich das maskierte Bild und den Begrenzungsrahmen.
quelle
Einige altmodische Bildverarbeitungsansätze ...
Die Idee basiert auf der Annahme, dass Bilder beleuchtete Bäume auf normalerweise dunkleren und glatteren Hintergründen (oder in einigen Fällen im Vordergrund) darstellen. Der beleuchtete Baumbereich ist "energetischer" und hat eine höhere Intensität .
Der Prozess ist wie folgt:
Was Sie erhalten, ist eine binäre Maske und ein Begrenzungsrahmen für jedes Bild.
Hier sind die Ergebnisse mit dieser naiven Technik:
Code auf MATLAB folgt: Der Code wird in einem Ordner mit JPG-Bildern ausgeführt. Lädt alle Bilder und gibt erkannte Ergebnisse zurück.
quelle
Mit einem ganz anderen Ansatz als dem, was ich gesehen habe, habe ich einen erstellt phpSkript, das Weihnachtsbäume an ihren Lichtern erkennt. Das Ergebnis ist immer ein symmetrisches Dreieck und gegebenenfalls numerische Werte wie der Winkel ("Fett") des Baumes.
Die größte Bedrohung für diesen Algorithmus sind offensichtlich Lichter neben (in großer Anzahl) oder vor dem Baum (das größere Problem bis zur weiteren Optimierung). Bearbeiten (hinzugefügt): Was es nicht kann: Finden Sie heraus, ob es einen Weihnachtsbaum gibt oder nicht, finden Sie mehrere Weihnachtsbäume in einem Bild, erkennen Sie einen Weihnachtsbaum mitten in Las Vegas korrekt, erkennen Sie Weihnachtsbäume, die stark verbogen sind. verkehrt herum oder gehackt ...;)
Die verschiedenen Stufen sind:
Erläuterung der Markierungen:
Quellcode:
Bilder:
Bonus: Ein deutscher Weihnachtsbaum aus Wikipedia http://commons.wikimedia.org/wiki/File:Weihnachtsbaum_R%C3%B6merberg.jpg
quelle
Ich habe Python mit opencv verwendet.
Mein Algorithmus sieht folgendermaßen aus:
Der Code:
Wenn ich den Kernel von (25,5) auf (10,5) ändere, erhalte ich bessere Ergebnisse für alle Bäume außer links unten.
Mein Algorithmus geht davon aus, dass der Baum beleuchtet ist, und im unteren linken Baum hat der obere weniger Licht als die anderen.
quelle