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 auf Schlüsselpunkten basierenden Bildanpassung zu umgehen, indem ich die Geschwindigkeit von Phash ausnutzte.
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.
An der Spitze die schnellsten Algorithmen; unten am langsamsten (wenn auch genauer). Sie können die langsamen überspringen, wenn auf der schnelleren Ebene eine gute Übereinstimmung gefunden wird.
- Datei-Hash-basiert (md5, sha1 usw.) für genaue Duplikate
- Perceptual Hashing (Phash) für neu skalierte Bilder
- Feature-basiert (SIFT) für geänderte Bilder
Ich habe sehr gute Ergebnisse mit Phash. Die Genauigkeit ist gut für neu skalierte Bilder. Es ist nicht gut für (wahrnehmungsmäßig) modifizierte Bilder (zugeschnitten, gedreht, gespiegelt usw.). Um mit der Hashing-Geschwindigkeit fertig zu werden, müssen wir einen Festplatten-Cache / eine Festplatten-Datenbank verwenden, um die Hashes für den Heuhaufen zu verwalten.
Das wirklich Schöne an Phash ist, dass die Suche nach dem Erstellen Ihrer Hash-Datenbank (für mich ungefähr 1000 Bilder / Sek.) 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 von 1 Million 64-Bit-Hashwerten (8 MB) erforderlich. Bei einigen CPUs passt dies in den L2 / L3-Cache! Im praktischen Gebrauch habe ich einen Corei7-Vergleich mit über 1 Giga-Hamm / Sek. Gesehen, es ist nur eine Frage der Speicherbandbreite zur CPU. Eine 1-Milliarden-Bilddatenbank ist auf einer 64-Bit-CPU (8 GB RAM erforderlich) praktisch und die Suche wird 1 Sekunde nicht überschreiten!
Für modifizierte / zugeschnittene Bilder scheint ein transformationsinvarianter Feature- / Keypoint-Detektor wie SIFT der richtige Weg zu sein. SIFT erzeugt gute Schlüsselpunkte, die Ernten / Drehen / Spiegeln usw. erkennen. Der Deskriptorvergleich ist jedoch im Vergleich zu der von Phash verwendeten Hamming-Distanz sehr langsam. Dies ist eine wesentliche Einschränkung. Es gibt viele Vergleiche zu tun, da es maximale IxJxK-Deskriptor-Vergleiche gibt, um ein Bild nachzuschlagen (I = Anzahl Heuhaufenbilder, J = Zielschlüsselpunkte pro Heuhaufenbild, K = Zielschlüsselpunkte pro Nadelbild).
Um das Geschwindigkeitsproblem zu umgehen, habe ich versucht, um jeden gefundenen Schlüsselpunkt einen Phash zu verwenden und das Subrechteck anhand der Feature-Größe / des Radius zu bestimmen. Der Trick, um dies gut zu machen, besteht darin, den Radius zu vergrößern / verkleinern, um verschiedene sub-rect-Pegel zu erzeugen (auf dem Nadelbild). Normalerweise stimmt die erste Ebene (nicht skaliert) überein, jedoch dauert es oft einige weitere. Ich bin nicht 100% sicher, warum dies funktioniert, aber ich kann mir vorstellen, dass es Funktionen ermöglicht, die zu klein sind, als dass Phash funktionieren könnte (Phash skaliert Bilder auf 32x32).
Ein weiteres Problem ist, dass SIFT die Schlüsselpunkte nicht optimal verteilt. Wenn es einen Abschnitt des Bildes mit vielen Kanten gibt, werden die Schlüsselpunkte dort gruppiert und Sie erhalten keine in einem anderen Bereich. Ich verwende den GridAdaptedFeatureDetector in OpenCV, um die Verteilung zu verbessern. Ich bin mir 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 Nadeln) vor der Feature-Erkennung auf eine kleinere Größe skalieren (ich verwende 210 Pixel entlang der maximalen Abmessung). Dies reduziert das Bildrauschen (immer ein Problem für Computer-Vision-Algorithmen) und fokussiert den Detektor auch auf wichtigere Merkmale.
Bei Bildern von Personen können Sie die Gesichtserkennung ausprobieren und damit die zu skalierende Bildgröße und die Rastergröße bestimmen (z. B. das größte Gesicht, das auf 100 Pixel skaliert ist). Der Feature-Detektor berücksichtigt mehrere Skalierungsstufen (mithilfe von Pyramiden), es gibt jedoch eine Beschränkung für die Anzahl der verwendeten Ebenen (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ückbekommen, ist das gut. Wenn Sie jedes Mal 400 zurückbekommen, mussten wahrscheinlich einige gute Funktionen weggelassen 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 Unterrechtecke, führen Sie einen erneuten Hash durch und führen Sie die Suchfunktion erneut aus.