Nie jest to najlepsze rozwiązanie, ale to rozwiązanie. Chciałbym nauczyć się lepszych technik:
Jeśli nie miałyby być obracane ani skalowane, można użyć prostej korelacji krzyżowej obrazów. Tam, gdzie pojawia się mały obraz na dużym obrazie, będzie jasny szczyt.
Możesz przyspieszyć korelację krzyżową za pomocą metody FFT, ale jeśli po prostu dopasowujesz mały obraz źródłowy do dużego obrazu docelowego, metoda wielokrotnego dodawania i dodawania brutalnej siły jest czasami (zwykle) szybsza.
Źródło:
Cel:
Korelacja krzyżowa:
Dwa jasne punkty to pasujące lokalizacje.
Ale zrobić mieć parametr rotacji W przykładzie obrazu, tak że nie będzie działać sama. Jeśli dozwolony jest tylko obrót, a nie skalowanie, nadal można zastosować korelację krzyżową, ale trzeba skorelować krzyżowo, obrócić źródło, skorelować go z całym obrazem docelowym, obrócić go ponownie itp. Dla wszystkie obroty.
Pamiętaj, że to niekoniecznie zawsze znajdzie obraz. Jeśli obrazem źródłowym jest szum losowy, a celem jest szum losowy, nie można go znaleźć, dopóki nie wyszukasz dokładnie pod odpowiednim kątem. W normalnych sytuacjach prawdopodobnie go znajdzie, ale zależy to od właściwości obrazu i kątów wyszukiwania.
Ta strona pokazuje przykład, jak by to zrobić, ale nie podaje algorytmu.
Każde przesunięcie, w którym suma jest powyżej pewnego progu, jest zgodne. Możesz obliczyć stopień dopasowania, skorelując obraz źródłowy ze sobą i dzieląc wszystkie swoje sumy przez tę liczbę. Idealne dopasowanie to 1.0.
Będzie to jednak bardzo trudne obliczeniowo i prawdopodobnie istnieją lepsze metody dopasowywania wzorów kropek (o których chciałbym wiedzieć).
Szybki przykład w Pythonie przy użyciu skali szarości i metody FFT:
from __future__ import division
from pylab import *
import Image
import ImageOps
source_file = 'dots source.png'
target_file = 'dots target.png'
# Load file as grayscale with white dots
target = asarray(ImageOps.invert(Image.open(target_file).convert('L')))
close('all')
figure()
imshow(target)
gray()
show()
source_Image = ImageOps.invert(Image.open(source_file).convert('L'))
for angle in (0, 180):
source = asarray(source_Image.rotate(angle, expand = True))
best_match = max(fftconvolve(source[::-1,::-1], source).flat)
# Cross-correlation using FFT
d = fftconvolve(source[::-1,::-1], target, mode='same')
figure()
imshow(source)
# This only finds a single peak. Use something that finds multiple peaks instead:
peak_x, peak_y = unravel_index(argmax(d),shape(d))
figure()
plot(peak_y, peak_x,'ro')
imshow(d)
# Keep track of all these matches:
print angle, peak_x, peak_y, d[peak_x,peak_y] / best_match
1-kolorowe bitmapy
W przypadku bitmap jednokolorowych byłoby to jednak znacznie szybsze. Korelacja krzyżowa staje się:
- Umieść obraz źródłowy nad obrazem docelowym
- Przenieś obraz źródłowy o 1 piksel
- bitowo-ORAZ wszystkie nakładające się piksele
- zsumuj wszystkie 1
- ...
Przekroczenie progu obrazu w skali szarości do pliku binarnego, a następnie zrobienie tego może być wystarczające.
Chmura punktów
Jeśli źródłem i celem są wzory kropek, szybszą metodą byłoby znalezienie środków każdej kropki (skorelowanie raz ze znaną kropką, a następnie znalezienie pików) i przechowywanie ich jako zestawu punktów, a następnie dopasowanie źródła aby celować, obracając, tłumacząc i znajdując błąd najmniejszych kwadratów między najbliższymi punktami w dwóch zestawach.