it-swarm.com.de

Bildvergleich - schneller Algorithmus

Ich möchte eine Basistabelle mit Bildern erstellen und dann alle neuen Bilder damit vergleichen, um festzustellen, ob das neue Bild ein genaues (oder nahes) Duplikat der Basis ist.

Beispiel: Wenn Sie den Speicherbedarf für ein und dasselbe Bild um ein Vielfaches reduzieren möchten, können Sie eine Kopie davon speichern und Referenzlinks dazu bereitstellen. Wenn Sie ein neues Bild eingeben, möchten Sie es mit einem vorhandenen Bild vergleichen, um sicherzustellen, dass es sich nicht um ein Duplikat handelt.

Eine Idee von mir war es, auf ein kleines Vorschaubild zu reduzieren und dann zufällig 100 Pixelstellen auszuwählen und zu vergleichen.

377
meade

Es folgen drei Lösungsansätze für dieses Problem (und es gibt viele andere).

  • Der erste Ansatz ist ein Standardansatz für die Computer-Vision und den Schlüsselpunktabgleich. Die Implementierung erfordert möglicherweise Hintergrundwissen und kann langsam sein.

  • Die zweite Methode verwendet nur die elementare Bildverarbeitung und ist möglicherweise schneller als die erste Methode und lässt sich problemlos implementieren. Was jedoch an Verständlichkeit gewinnt, ist mangelnde Robustheit - bei skalierten, gedrehten oder verfärbten Bildern schlägt der Abgleich fehl.

  • Die dritte Methode ist sowohl schnell als auch robust, möglicherweise jedoch am schwierigsten zu implementieren.

Schlüsselpunktabgleich

Besser als die Auswahl von 100 zufälligen Punkten ist die Auswahl von 100 wichtig Punkten. Bestimmte Teile eines Bildes enthalten mehr Informationen als andere (insbesondere an Kanten und Ecken), und diese sind diejenigen, die Sie für die intelligente Bildanpassung verwenden möchten. Google " Keypoint Extraction " und " Keypoint Matching " und Sie finden eine ganze Reihe von wissenschaftlichen Artikeln zu diesem Thema. In diesen Tagen sind SIFT-Schlüsselpunkte wohl die beliebtesten, da sie Bilder mit unterschiedlichen Maßstäben, Rotationen und Lichtverhältnissen zuordnen können. Einige SIFT-Implementierungen finden Sie hier .

Ein Nachteil beim Schlüsselpunktabgleich ist die Laufzeit einer naiven Implementierung: O (n ^ 2 m), wobei n die Anzahl der Schlüsselpunkte in jedem Bild und m die Anzahl der Bilder in der Datenbank ist. Einige clevere Algorithmen, wie Quadtrees oder die Partitionierung von Binärräumen, finden die beste Übereinstimmung möglicherweise schneller.


Alternative Lösung: Histogramm-Methode

Eine andere weniger robuste, aber möglicherweise schnellere Lösung besteht darin, Merkmalshistogramme für jedes Bild zu erstellen und das Bild mit dem Histogramm auszuwählen, das dem Histogramm des Eingabebildes am nächsten liegt. Ich habe dies als Undergrad implementiert und wir haben 3 Farbhistogramme (rot, grün und blau) und zwei Texturhistogramme, Richtung und Skalierung, verwendet. Ich gebe die Details unten an, aber ich sollte beachten, dass dies nur für übereinstimmende Bilder gut funktionierte, die den Datenbankbildern SEHR ähnlich sind. Neu skalierte, gedrehte oder verfärbte Bilder können mit dieser Methode fehlschlagen, aber kleine Änderungen wie das Zuschneiden können den Algorithmus nicht beeinträchtigen

Die Berechnung der Farbhistogramme ist unkompliziert. Wählen Sie einfach den Bereich für Ihre Histogramm-Buckets aus und zählen Sie für jeden Bereich die Anzahl der Pixel mit einer Farbe in diesem Bereich. Betrachten Sie beispielsweise das "grüne" Histogramm und nehmen Sie an, wir wählen 4 Buckets für unser Histogramm: 0-63, 64-127, 128-191 und 192-255. Dann schauen wir uns für jedes Pixel den grünen Wert an und addieren eine Zählung zu dem entsprechenden Bucket. Wenn wir mit dem Zählen fertig sind, dividieren wir jede Bucket-Summe durch die Anzahl der Pixel im gesamten Bild, um ein normalisiertes Histogramm für den grünen Kanal zu erhalten.

Für das Texturrichtungshistogramm haben wir zunächst eine Kantenerkennung für das Bild durchgeführt. Jeder Kantenpunkt hat einen Normalenvektor, der in die Richtung senkrecht zur Kante zeigt. Wir haben den Winkel des Normalenvektors in einen von 6 Buckets zwischen 0 und PI quantisiert (da Kanten eine 180-Grad-Symmetrie haben, haben wir Winkel zwischen -PI und 0 konvertiert, um zwischen 0 und PI zu liegen). Nachdem Sie die Anzahl der Kantenpunkte in jeder Richtung gezählt haben, erhalten Sie ein nicht normalisiertes Histogramm, das die Texturrichtung darstellt. Dieses Histogramm haben wir normalisiert, indem Sie jeden Bucket durch die Gesamtzahl der Kantenpunkte im Bild dividiert haben.

Um das Histogramm der Texturskala für jeden Kantenpunkt zu berechnen, haben wir den Abstand zum nächstgelegenen Kantenpunkt mit derselben Richtung gemessen. Wenn beispielsweise der Kantenpunkt A eine Richtung von 45 Grad hat, wandert der Algorithmus in diese Richtung, bis er einen anderen Kantenpunkt mit einer Richtung von 45 Grad findet (oder innerhalb einer angemessenen Abweichung). Nach der Berechnung dieses Abstands für jeden Kantenpunkt werden diese Werte in ein Histogramm geschrieben und durch Division durch die Gesamtzahl der Kantenpunkte normalisiert.

Jetzt haben Sie 5 Histogramme für jedes Bild. Um zwei Bilder zu vergleichen, nehmen Sie den absoluten Wert der Differenz zwischen jedem Histogramm-Bucket und addieren diese Werte. Um beispielsweise die Bilder A und B zu vergleichen, würden wir berechnen

|A.green_histogram.bucket_1 - B.green_histogram.bucket_1| 

für jeden Bereich im grünen Histogramm und für die anderen Histogramme wiederholen und dann alle Ergebnisse zusammenfassen. Je kleiner das Ergebnis, desto besser die Übereinstimmung. Wiederholen Sie dies für alle Bilder in der Datenbank, und das Spiel mit dem kleinsten Ergebnis gewinnt. Wahrscheinlich möchten Sie einen Schwellenwert haben, über dem der Algorithmus zu dem Schluss kommt, dass keine Übereinstimmung gefunden wurde.


Dritte Wahl - Schlüsselpunkte + Entscheidungsbäume

Ein dritter Ansatz, der wahrscheinlich viel schneller ist als die beiden anderen, ist semantischer Text in Wäldern (PDF). Dies beinhaltet das Extrahieren einfacher Schlüsselpunkte und die Verwendung von Sammlungsentscheidungsbäumen, um das Bild zu klassifizieren. Dies ist schneller als der einfache SIFT-Schlüsselpunktabgleich, da der kostspielige Abgleich entfällt und Schlüsselpunkte viel einfacher als SIFT sind, sodass die Schlüsselpunktextraktion viel schneller ist. Die Invarianz der SIFT-Methode in Bezug auf Drehung, Skalierung und Beleuchtung bleibt jedoch erhalten, ein wichtiges Merkmal, das bei der Histogrammmethode fehlte.

Update :

Mein Fehler - das Papier von Semantic Texton Forests befasst sich nicht speziell mit der Bildanpassung, sondern mit der Kennzeichnung von Regionen. Das Originalpapier, das übereinstimmt, ist dieses: Schlüsselpunkterkennung unter Verwendung von zufälligen Bäumen . In den folgenden Abhandlungen werden die Ideen weiterentwickelt und der Stand der Technik dargestellt (ca. 2010):

441
Kyle Simek

Die beste Methode, die ich kenne, ist die Verwendung eines Perceptual Hash. Es scheint eine gute Open-Source-Implementierung eines solchen Hashes zu geben:

http://phash.org/

Die Hauptidee ist, dass jedes Bild auf einen kleinen Hash-Code oder „Fingerabdruck“ reduziert wird, indem hervorstechende Merkmale in der Originalbilddatei identifiziert und eine kompakte Darstellung dieser Merkmale erstellt wird (anstatt die Bilddaten direkt zu verarbeiten). Dies bedeutet, dass die Falsch-Positiv-Rate im Vergleich zu einem simplen Ansatz wie dem Reduzieren von Bildern auf ein winziges Bild in der Größe eines Fingerabdrucks und dem Vergleichen von Fingerabdrücken stark reduziert wird.

phash bietet verschiedene Arten von Hash an und kann für Bilder, Audio oder Video verwendet werden.

80
redcalx

Dieser Beitrag war der Ausgangspunkt meiner Lösung, viele gute Ideen hier, damit ich meine Ergebnisse teilen kann. Die wichtigste Erkenntnis ist, dass ich einen Weg gefunden habe, um die Langsamkeit der Keypoint-basierten Bildanpassung zu umgehen durch Ausnutzen der Geschwindigkeit von phash.

Für die allgemeine Lösung ist es am besten, mehrere Strategien anzuwenden. Jeder Algorithmus eignet sich am besten für bestimmte Arten von Bildtransformationen, und Sie können dies nutzen.

Oben die schnellsten Algorithmen; am unteren Rand der langsamste (wenn auch genauer). Sie können die langsamen überspringen, wenn eine gute Übereinstimmung auf der schnelleren Ebene gefunden wird.

  • datei-hash-basiert (md5, sha1, etc) für exakte duplikate
  • wahrnehmungs-Hashing (Phash) für neu skalierte Bilder
  • merkmalsbasiert (SIFT) für geänderte Bilder

Ich habe sehr gute Ergebnisse mit Phash. Die Genauigkeit ist gut für neu skalierte Bilder. Es eignet sich nicht für (perzeptuell) veränderte Bilder (beschnitten, gedreht, gespiegelt usw.). Um mit der Hashing-Geschwindigkeit fertig zu werden, müssen wir einen Festplatten-Cache/eine Datenbank verwenden, um die Hashes für den Heuhaufen zu verwalten.

Das wirklich Schöne an phash ist, dass, sobald Sie Ihre Hash-Datenbank erstellt haben (was für mich ungefähr 1000 Bilder/Sek. Ist), die Suche sehr, sehr schnell sein kann, insbesondere wenn Sie die gesamte Hash-Datenbank im Speicher halten können. Dies ist ziemlich praktisch, da ein Hash nur 8 Bytes umfasst.

Wenn Sie beispielsweise 1 Million Bilder haben, ist ein Array mit 1 Million 64-Bit-Hashwerten (8 MB) erforderlich. Bei einigen CPUs passt dies in den L2/L3-Cache! Im praktischen Einsatz habe ich einen Corei7 mit über 1 Gigahamm/Sek. Vergleichen sehen, es ist nur eine Frage der Speicherbandbreite zur CPU. Eine 1-Milliarde-Bilddatenbank ist praktisch für eine 64-Bit-CPU (8 GB RAM erforderlich)) und die Suche dauert nicht länger als 1 Sekunde!

Bei modifizierten/beschnittenen Bildern scheint es sich um eine transformationsinvariante Funktion zu handeln. Ein Schlüsselpunktdetektor wie SIFT ist der richtige Weg. SIFT erzeugt gute Keypoints, die das Zuschneiden/Drehen/Spiegeln usw. erkennen. Der Vergleich der Deskriptoren ist jedoch im Vergleich zur Hamming-Distanz, die von Phash verwendet wird, sehr langsam. Dies ist eine wesentliche Einschränkung. Es sind viele Vergleiche zu machen, da es maximal IxJxK-Deskriptor-Vergleiche gibt, um ein Bild nachzuschlagen (I = Anzahl Heuhaufenbilder, J = Ziel-Schlüsselpunkte pro Heuhaufenbild, K = Ziel-Schlüsselpunkte pro Nadelbild).

Um das Geschwindigkeitsproblem zu umgehen, habe ich versucht, einen Phash um jeden gefundenen Schlüsselpunkt zu verwenden. Dabei habe ich die Größe/den Radius des Features verwendet, um das untergeordnete Rechteck zu bestimmen. Der Trick, um diese Funktion zu verbessern, besteht darin, den Radius zu vergrößern/zu verkleinern, um verschiedene untergeordnete Ebenen (auf dem Nadelbild) zu erzeugen. Normalerweise stimmt die erste Stufe (nicht skaliert) überein, jedoch dauert es oft ein paar Minuten länger. Ich bin mir nicht hundertprozentig sicher, warum dies funktioniert, aber ich kann mir vorstellen, dass es Funktionen ermöglicht, die zu klein für Phash sind (Phash skaliert Bilder auf 32x32).

Ein weiteres Problem ist, dass SIFT die Schlüsselpunkte nicht optimal verteilt. Wenn es einen Bildausschnitt mit vielen Kanten gibt, gruppieren sich die Schlüsselpunkte dort und Sie erhalten keine in einem anderen Bereich. Ich verwende den GridAdaptedFeatureDetector in OpenCV, um die Verteilung zu verbessern. Nicht sicher, welche Rastergröße am besten ist, ich verwende ein kleines Raster (1x3 oder 3x1, je nach Bildausrichtung).

Sie möchten wahrscheinlich alle Heuhaufenbilder (und die Nadel) vor der Feature-Erkennung auf eine kleinere Größe skalieren (ich verwende 210px entlang der maximalen Abmessung). Dies reduziert das Bildrauschen (immer ein Problem für Computer-Vision-Algorithmen) und fokussiert den Detektor auf wichtigere Merkmale.

Bei Bildern von Personen können Sie versuchen, die Gesichtserkennung zu verwenden, um die zu skalierende Bildgröße und die Rastergröße zu bestimmen (z. B. das größte Gesicht, das auf 100 Pixel skaliert ist). Der Feature-Detektor berücksichtigt mehrere Skalierungsstufen (unter Verwendung von Pyramiden), es gibt jedoch eine Beschränkung hinsichtlich der Anzahl der verwendeten Stufen (dies ist natürlich einstellbar).

Der Schlüsselpunktdetektor funktioniert wahrscheinlich am besten, wenn er weniger als die gewünschte Anzahl von Funktionen zurückgibt. Wenn Sie zum Beispiel nach 400 fragen und 300 zurückerhalten, ist das gut. Wenn Sie jedes Mal 400 zurückbekommen, mussten wahrscheinlich einige gute Funktionen ausgelassen werden.

Das Nadelbild kann weniger Schlüsselpunkte als die Heuhaufenbilder haben und dennoch gute Ergebnisse erzielen. Wenn Sie mehr hinzufügen, erhalten Sie nicht unbedingt enorme Gewinne. Bei J = 400 und K = 40 liegt meine Trefferquote beispielsweise bei 92%. Mit J = 400 und K = 400 steigt die Trefferquote nur auf 96%.

Wir können die extreme Geschwindigkeit der Hamming-Funktion nutzen, um Skalierung, Rotation, Spiegelung usw. zu lösen. Eine Mehrfachdurchlauf-Technik kann verwendet werden. Transformieren Sie bei jeder Iteration die Teilrechtecke, wiederholen Sie den Hash und führen Sie die Suchfunktion erneut aus.

34
wally

Ich habe eine Idee, die funktionieren kann und die höchstwahrscheinlich sehr schnell ist. Sie können ein Bild mit einer Auflösung von 80 x 60 oder einer vergleichbaren Auflösung unterabtasten und es in Graustufen konvertieren (nach dem Unterabtasten ist es schneller). Verarbeiten Sie beide Bilder, die Sie vergleichen möchten. Führen Sie dann die normalisierte Summe der quadrierten Differenzen zwischen zwei Bildern (das Abfragebild und jedes aus der Datenbank) oder besser die normalisierte Kreuzkorrelation aus, die eine Antwort näher an 1 ergibt, wenn beide Bilder ähnlich sind. Wenn die Bilder ähnlich sind, können Sie anspruchsvollere Techniken anwenden, um sicherzustellen, dass es sich um dieselben Bilder handelt. Offensichtlich ist dieser Algorithmus in Bezug auf die Anzahl der Bilder in Ihrer Datenbank linear, obwohl er auf der modernen Hardware mit bis zu 10000 Bildern pro Sekunde sehr schnell sein wird. Wenn Sie eine Invarianz zur Drehung benötigen, kann ein dominanter Gradient für dieses kleine Bild berechnet werden, und dann kann das gesamte Koordinatensystem zur kanonischen Ausrichtung gedreht werden, dies ist jedoch langsamer. Und nein, hier gibt es keine maßstabsgetreue Invarianz.

Wenn Sie etwas allgemeineres möchten oder große Datenbanken (Millionen von Bildern) verwenden möchten, müssen Sie sich mit der Bildwiederherstellungstheorie befassen (in den letzten 5 Jahren sind viele Artikel erschienen). Es gibt einige Hinweise in anderen Antworten. Aber es könnte übertrieben sein, und der vorgeschlagene Histogramm-Ansatz wird die Arbeit erledigen. Obwohl ich denke, dass die Kombination vieler verschiedener schneller Ansätze noch besser sein wird.

6
Denis C

Wie Cartman betonte, können Sie jeden Hash-Wert verwenden, um exakte Duplikate zu finden.

Ein Ausgangspunkt, um nahe Bilder zu finden, könnte hier sein. Dies ist ein Tool, das von CG-Unternehmen verwendet wird, um zu überprüfen, ob überarbeitete Bilder immer noch im Wesentlichen dieselbe Szene zeigen.

6
Tobiesque

Ich glaube, dass es gut funktionieren sollte, die Größe des Bildes auf eine fast symbolische Größe zu reduzieren, z. B. 48 x 48, dann in Graustufen zu konvertieren und dann den Unterschied zwischen Pixeln oder Delta zu nehmen. Da wir die Änderung der Pixelfarbe und nicht die tatsächliche Pixelfarbe vergleichen, spielt es keine Rolle, ob das Bild etwas heller oder dunkler ist. Große Änderungen sind wichtig, da Pixel, die zu hell/dunkel werden, verloren gehen. Sie können dies auf eine Zeile oder auf beliebig viele anwenden, um die Genauigkeit zu erhöhen. Es müssten höchstens 47x47 = 2.209 Subtraktionen durchgeführt werden, um einen vergleichbaren Schlüssel zu bilden.

5
Tanoshimi

Das Auswählen von 100 zufälligen Punkten kann dazu führen, dass ähnliche (oder gelegentlich sogar unähnliche) Bilder als gleich markiert werden. Ich gehe davon aus, dass dies nicht das ist, was Sie möchten. MD5-Hashes würden nicht funktionieren, wenn die Bilder unterschiedliche Formate (PNG, JPEG usw.), unterschiedliche Größen oder unterschiedliche Metadaten hätten. Es empfiehlt sich, alle Bilder auf eine kleinere Größe zu verkleinern. Ein Pixel-für-Pixel-Vergleich sollte nicht zu lange dauern, solange Sie eine gute Bildbibliothek/schnelle Sprache verwenden und die Größe klein genug ist.

Sie könnten versuchen, sie winzig zu machen. Wenn sie gleich sind, führen Sie einen weiteren Vergleich mit einer größeren Größe durch. Dies könnte eine gute Kombination aus Geschwindigkeit und Genauigkeit sein.

3
HarryM

Mein Unternehmen hat ungefähr 24 Millionen Bilder, die jeden Monat von Herstellern eingehen. Ich suchte nach einer schnellen Lösung, um sicherzustellen, dass die Bilder, die wir in unseren Katalog hochladen, neue Bilder sind.

Ich möchte sagen, dass ich weit und breit im Internet gesucht habe, um eine ideale Lösung zu finden. Ich habe sogar meinen eigenen Kantenerkennungsalgorithmus entwickelt.
Ich habe die Geschwindigkeit und Genauigkeit mehrerer Modelle bewertet. Meine Bilder mit weißem Hintergrund eignen sich hervorragend für das Phashing. Wie redcalx sagte, empfehle ich phash oder ahash. Verwenden Sie NICHT MD5-Hashing oder andere kryptografische Hashes. Es sei denn, Sie möchten nur GENAUE Bildübereinstimmungen. Jede Größenänderung oder Manipulation, die zwischen Bildern auftritt, führt zu einem anderen Hash.

Überprüfen Sie Folgendes für phash/ahash: imagehash

Ich wollte den Beitrag von * redcalx * erweitern, indem ich meinen Code und meine Genauigkeit poste.

Was ich mache:

from PIL import Image
from PIL import ImageFilter
import imagehash

img1=Image.open(r"C:\yourlocation")
img2=Image.open(r"C:\yourlocation")
if img1.width<img2.width:
    img2=img2.resize((img1.width,img1.height))
else:
    img1=img1.resize((img2.width,img2.height))
img1=img1.filter(ImageFilter.BoxBlur(radius=3))
img2=img2.filter(ImageFilter.BoxBlur(radius=3))
phashvalue=imagehash.phash(img1)-imagehash.phash(img2)
ahashvalue=imagehash.average_hash(img1)-imagehash.average_hash(img2)
totalaccuracy=phashvalue+ahashvalue

Hier sind einige meiner Ergebnisse:

item1  item2  totalaccuracy
desk1  desk2       3
desk2  phone1     22
chair1 desk1      17
phone1 chair1     34

dabei steht der Gegenstand für das eigentliche Motiv des Bildes und die Zahl für die Orientierungsskala.

Hoffe das hilft!

2
Tanner Clark

Wenn Sie eine große Anzahl von Bildern haben, schauen Sie in ein Bloom-Filter , das mehrere Hashes für ein wahrscheinliches, aber effizientes Ergebnis verwendet. Wenn die Anzahl der Bilder nicht sehr groß ist, sollte ein kryptografischer Hash wie md5 ausreichen.

2
jdigital