Ten post był punktem wyjścia do mojego rozwiązania, jest tu wiele dobrych pomysłów, więc pomyślałem, że podzielę się z tobą wynikami. Główny wgląd jest taki, że znalazłem sposób na obejście powolności dopasowywania obrazu opartego na kluczowych punktach, wykorzystując szybkość phash.
W przypadku ogólnego rozwiązania najlepiej zastosować kilka strategii. Każdy algorytm najlepiej nadaje się do niektórych rodzajów transformacji obrazu i możesz z tego skorzystać.
Na górze najszybsze algorytmy; na dole najwolniejszy (choć dokładniejszy). Możesz pominąć wolne, jeśli na wyższym poziomie zostanie znalezione dobre dopasowanie.
- oparty na haszowaniu plików (md5, sha1 itp.) dla dokładnych duplikatów
- haszowanie percepcyjne (phash) dla przeskalowanych obrazów
- oparty na funkcjach (SIFT) dla zmodyfikowanych obrazów
Mam bardzo dobre wyniki z phash. Dokładność jest dobra w przypadku przeskalowanych obrazów. Nie nadaje się do (percepcyjnie) zmodyfikowanych obrazów (przyciętych, obróconych, dublowanych itp.). Aby poradzić sobie z szybkością mieszania, musimy zastosować pamięć podręczną dysku / bazę danych w celu utrzymania skrótów dla stogu siana.
Naprawdę fajną rzeczą w phash jest to, że po zbudowaniu bazy danych hash (która dla mnie wynosi około 1000 obrazów / s), wyszukiwanie może być bardzo, bardzo szybkie, szczególnie gdy możesz przechowywać całą bazę danych hash w pamięci. Jest to dość praktyczne, ponieważ skrót ma tylko 8 bajtów.
Na przykład, jeśli masz 1 milion obrazów, wymagałoby to tablicy 1 miliona 64-bitowych wartości skrótu (8 MB). Na niektórych procesorach pasuje to do pamięci podręcznej L2 / L3! W praktyce widziałem porównanie corei7 z prędkością powyżej 1 Giga-hamm / s, to tylko kwestia przepustowości pamięci procesora. Baza danych z 1 miliardem obrazów jest praktyczna na 64-bitowym procesorze (potrzeba 8 GB pamięci RAM), a wyszukiwania nie przekroczą 1 sekundy!
W przypadku zmodyfikowanych / przyciętych obrazów wydaje się, że najlepszym rozwiązaniem jest detektor niezmiennej transformacji / detektor punktów kluczowych, taki jak SIFT. SIFT wytworzy dobre punkty kluczowe, które wykrywają kadrowanie / obracanie / odbicie lustrzane itp. Jednak porównanie deskryptorów jest bardzo wolne w porównaniu do odległości hamowania używanej przez phash. To jest główne ograniczenie. Istnieje wiele porównań do zrobienia, ponieważ istnieje maksymalna liczba deskryptorów IxJxK w porównaniu do wyszukiwania jednego obrazu (I = liczba obrazów stogu siana, J = docelowe punkty kluczowe na obrazie stogu siana, K = docelowe punkty kluczowe na obrazie igły).
Aby obejść problem z prędkością, próbowałem użyć Phash wokół każdego znalezionego punktu kluczowego, używając rozmiaru / promienia elementu do określenia pod-prostokąta. Sztuką, aby to dobrze działało, jest zwiększenie / zmniejszenie promienia w celu wygenerowania różnych poziomów pod-prostokątnych (na zdjęciu igły). Zazwyczaj pierwszy poziom (nieskalowany) będzie pasował, jednak często zajmuje to kilka więcej. Nie jestem w 100% pewien, dlaczego to działa, ale mogę sobie wyobrazić, że włącza funkcje, które są zbyt małe, aby mógł działać Phash (Phash skaluje obrazy do 32 x 32).
Inną kwestią jest to, że SIFT nie rozdzieli optymalnie punktów kluczowych. Jeśli jest fragment obrazu z wieloma krawędziami, punkty kluczowe zostaną tam skupione i nie dostaniesz ich w innym obszarze. Korzystam z GridAdaptedFeatureDetector w OpenCV, aby poprawić dystrybucję. Nie jestem pewien, jaki rozmiar siatki jest najlepszy, używam małej siatki (1x3 lub 3x1 w zależności od orientacji obrazu).
Prawdopodobnie zechcesz przeskalować wszystkie obrazy stogu siana (i igły) do mniejszego rozmiaru przed wykryciem funkcji (używam 210 pikseli wzdłuż maksymalnego wymiaru). Zmniejszy to szum na obrazie (zawsze stanowi to problem dla algorytmów widzenia komputerowego), a także skupi detektor na bardziej znaczących funkcjach.
W przypadku zdjęć ludzi możesz spróbować wykryć twarz i użyć jej do określenia rozmiaru obrazu do skalowania i rozmiaru siatki (na przykład największa twarz skalowana do 100 pikseli). Detektor cech uwzględnia wiele poziomów skali (przy użyciu piramid), ale istnieje ograniczenie liczby używanych poziomów (jest to oczywiście dostrajane).
Detektor punktów kluczowych prawdopodobnie działa najlepiej, gdy zwraca mniej niż żądana liczba funkcji. Na przykład, jeśli poprosisz o 400 i odzyskasz 300, to dobrze. Jeśli odzyskujesz 400 za każdym razem, prawdopodobnie pewne dobre funkcje musiały zostać pominięte.
Obraz igły może mieć mniej punktów kluczowych niż obrazy stogu siana i nadal osiągać dobre wyniki. Dodanie więcej niekoniecznie przyniesie ogromne zyski, na przykład przy J = 400 i K = 40 mój wskaźnik trafień wynosi około 92%. Przy J = 400 i K = 400 wskaźnik trafień wzrasta tylko do 96%.
Możemy wykorzystać ekstremalną prędkość funkcji Hamminga do rozwiązania skalowania, obrotu, odbicia lustrzanego itp. Można zastosować technikę wielokrotnego przejścia. Na każdej iteracji przekształć pod-prostokąty, ponownie hashuj i ponownie uruchom funkcję wyszukiwania.