2010-01-27 9 views
35

Es gibt einige Themen, die hilfreich sind, um ähnliche Bilder zu finden.OpenCV/SURF Wie erstelle ich einen Bild-Hash/Fingerabdruck/Signatur aus den Deskriptoren?

Was ich tun möchte, ist einen Fingerabdruck eines Bildes zu bekommen und das gleiche Bild auf verschiedenen Fotos von einer Digitalkamera zu finden. Der SURF-Algorithmus scheint der beste Weg zu sein, unabhängig von Skalierung, Winkel und anderen Verzerrungen zu sein.

Ich verwende OpenCV mit dem SURF-Algorithmus, um Merkmale auf dem Beispielbild zu extrahieren. Jetzt frage ich mich, wie man all diese Feature-Daten (Position, Laplace, Größe, Ausrichtung, Hessian) in einen Fingerabdruck oder Hash konvertieren kann.

Dieser Fingerabdruck wird in einer Datenbank gespeichert und eine Suchanfrage muss in der Lage sein, diesen Fingerabdruck mit einem Fingerabdruck eines Fotos mit fast den gleichen Merkmalen zu vergleichen.

Update:

Es scheint, dass es keine Möglichkeit, alle Descriptor Vektoren in eine einfache Hash zu konvertieren ist. Was wäre also der beste Weg, um die Bilddeskriptoren für schnelle Abfragen in der Datenbank zu speichern?

Würden Wortschatzbäume eine Option sein?

Ich wäre sehr dankbar für jede Hilfe.

+0

Der Code führt, was "nächster Nachbar" matching genannt wird - Nehme den Deskriptor (einen Vektor der Größe N) und vergleiche ihn mit einem Satz von Vektoren anderer Größe N (dies kann durch Berechnen des euklidischen Abstandes zwischen ihnen oder irgendeines anderen Abstandsmaßes sein) und Auswählen desjenigen, welches am nächsten ist. Das Naive im Namen bedeutet, dass der Vektor mit ALLEN anderen Vektoren verglichen wird. Es gibt andere Algorithmen, die approximative nearest neighbour verwenden, die weniger genau, aber effizienter sind. – elijah

+1

Um es kurz zu machen: Sie können keine Hash-Funktion aus Bildern machen (das ist zu schlecht gestellt und anmaßend). Sie können sich auf die Literatur für Nearest-Neighbor-Klassifikation oder Bildähnlichkeitsmaße beziehen. – elijah

+0

Okay, was wäre der beste Weg, um alle Bilddeskriptoren abzufragen? – dan

Antwort

9

Die Feature-Daten, die Sie erwähnen (Position, Laplace, Größe, Ausrichtung, Hessian), sind für Ihren Zweck nicht ausreichend (dies sind die weniger relevanten Teile des Deskriptors, wenn Sie einen Abgleich durchführen möchten). Die Daten, die Sie wollen, zu betrachten sind die „Deskriptoren“ (das vierte Argument):

void cvExtractSURF(const CvArr* image, const CvArr* mask, CvSeq** keypoints, CvSeq** descriptors, CvMemStorage* storage, CvSURFParams params)

Dies sind 128 oder 64 (je nach params) Vektoren, die die „Fingerabdrücke“ der spezifischen Funktion enthalten (jeweils Bild wird eine variable Menge solcher Vektoren enthalten). Wenn Sie die neueste Version von OpenCV bekommen sie eine Probe namens find_obj.cpp haben, die Ihnen zeigt, wie es für passend

Update verwendet wird:

könnten Sie this Diskussion hilfreich

+0

Hallo Liza, danke für deine Antwort. Ich habe mir das Beispiel angeschaut, finde aber keine Möglichkeit, die Vektoren der in CvSeq gespeicherten Deskriptoren in einen Hashwert zu transformieren, der es ermöglicht, in einer Datenbank gespeichert und mit anderen Hashes verglichen zu werden. Hast du einen Hinweis darauf? – dan

+0

Das CvSeq speichert einfach Float-Arrays (sehen Sie sich den Quellcode von cvExtractSURF an, um zu sehen, wie sie es speichern). diese Arrays (128 oder 64 in der Länge) sind, was Sie interessiert sind – elijah

+0

übrigens, wenn was Sie wollen, ist ein magischer Hash, der alle Hund Bilder zum Beispiel auf den gleichen Hash-Code zuordnen würde, ich fürchte, es ist mehr kompliziert, als nur die SURF-Funktionen zu extrahieren. Sehen Sie sich den Link an, den ich auf das Update gesetzt habe – elijah

3

A trivial finden Weg, um einen Hash zu berechnen, wäre das folgende. Holen Sie alle Deskriptoren aus dem Bild (sagen wir, N von ihnen). Jeder Deskriptor ist ein Vektor mit 128 Zahlen (Sie können sie in ganze Zahlen zwischen 0 und 255 umwandeln). Sie haben also eine Menge von N * 128 ganzen Zahlen. Schreiben Sie sie nacheinander in eine Zeichenfolge und verwenden Sie diese als Hashwert. Wenn Sie möchten, dass die Hash-Werte klein sind, glaube ich, dass es Möglichkeiten gibt, Hash-Funktionen von Strings zu berechnen, also konvertieren Sie Deskriptoren in Strings und verwenden Sie dann den Hash-Wert dieses Strings.

Das könnte funktionieren, wenn Sie genaue Duplikate finden möchten. Aber es scheint (da Sie über Skalierung, Rotation usw. sprechen) möchten Sie nur "ähnliche" Bilder finden. In diesem Fall ist es wahrscheinlich keine gute Methode, einen Hash zu verwenden. Sie verwenden wahrscheinlich einen interessierenden Punktdetektor, um Punkte zu finden, an denen SURF-Deskriptoren berechnet werden können. Stellen Sie sich vor, dass es die gleiche Menge von Punkten zurückgibt, aber in anderer Reihenfolge. Plötzlich wird Ihr Hash-Wert sehr unterschiedlich sein, selbst wenn die Bilder und Deskriptoren identisch sind.

Also, wenn ich ähnliche Bilder zuverlässig finden müsste, würde ich einen anderen Ansatz verwenden.Zum Beispiel könnte ich die SURF-Deskriptoren vektorquantisieren, Histogramme von vektorquantisierten Werten erstellen und eine Histogramm-Kreuzung für die Übereinstimmung verwenden. Müssen Sie wirklich Hash-Funktionen verwenden (vielleicht aus Effizienzgründen), oder wollen Sie einfach nur das verwenden, um ähnliche Bilder zu finden?

+0

Hallo Sheldon, danke für Ihre Antwort. Bevor ich mich mit SURF beschäftigte, arbeitete ich mit der pHash lib. Diese Bibliothek erzeugt einen Hash-Wert für Mediendaten (Bilder, Video und Audio). Dann könnten Sie die Hamming-Distanz verwenden, um Ihre Datenbank mit ähnlichen Bild-Hashes ganz einfach abzufragen. Ich dachte, es muss einen Weg geben, das Gleiche mit den SURF-Deskriptoren in irgendeiner Weise zu tun. Jetzt denke ich über das Speichern aller serialisierten Bilddeskriptor-Array-Objekte in der Datenbank. Wenn ich ein ähnliches Bild in der Datenbank finden will, muss ich Zeile für Zeile auswählen und ähnliche Deskriptoren von Hand finden. (...) – dan

+2

(Fortsetzung) Der große Nachteil wäre eine sehr schlechte Leistung für eine große Bilddatenbank. Ich frage mich, wie TinEye.com ähnliche Bilder so schnell finden konnte. Es muss einen Trick geben, um ihre Datenbank sehr schnell abzufragen. – dan

+1

Ich denke, was helfen würde, wenn Sie erzählten, was genau Sie erreichen möchten. Angesichts eines Bildes, was versuchst du zu finden? Identische Bilder, ähnliche Bilder, ähnliche Bilder bis zur Rotations-/Translationsskalierung? Bei einem Bild X möchten Sie nur Bilder finden, die X ähnlich sind, oder möchten Sie auch Bilder, die X als Unterteil enthalten? Die Abfrage ist beispielsweise ein Gesichtsbild. Möchten Sie andere Gesichtsbilder oder auch Ganzkörperaufnahmen mit dem Gesicht, aber auch viele andere Dinge finden? Warum haben Sie auf pHash verzichtet und stattdessen mit SURF-Deskriptoren gearbeitet? – user245973

2

Min-Hash oder min-Hashing ist eine Technik, die Ihnen helfen könnte. Es kodiert das gesamte Bild in einer Darstellung mit einstellbarer Größe, die dann in Hash-Tabellen gespeichert wird. Mehrere Varianten wie Geometrisch min-Hashing, Partition min-Hash und Bundle min-Hashing existieren. Der resultierende Speicher-Footprint ist nicht einer der kleinsten, aber diese Techniken funktionieren für eine Vielzahl von Szenarien, wie nahezu doppelte Abholung und sogar kleine Objekt-Retrieval - ein Szenario, wo andere kurze Signaturen oft nicht sehr gut funktionieren.

Es gibt mehrere Artikel zu diesem Thema. Eintrag Literatur wäre: nahes Duplikat Bilderkennung: min-Hash und tf-idf Gewichtung Ondrej Chum, James Philbin, Andrew Zisserman, BMVC 2008PDF