Ini bukan solusi terbaik, tapi itu sebuah solusi. Saya ingin belajar teknik yang lebih baik:
Jika tidak akan diputar atau diskalakan, Anda bisa menggunakan korelasi silang sederhana dari gambar. Akan ada puncak cerah di mana pun gambar kecil terjadi pada gambar besar.
Anda dapat mempercepat korelasi silang dengan menggunakan metode FFT, tetapi jika Anda hanya mencocokkan gambar sumber kecil dengan gambar target besar, metode multiplikasi tambah tambah kasar kadang-kadang (biasanya tidak) lebih cepat.
Sumber:
Target:
Korelasi silang:
Dua titik terang adalah lokasi yang cocok.
Tapi Anda lakukan memiliki parameter rotasi dalam contoh gambar Anda, sehingga tidak akan bekerja dengan sendirinya. Jika hanya rotasi yang diizinkan, dan bukan penskalaan, maka masih dimungkinkan untuk menggunakan korelasi silang, tetapi Anda harus berkorelasi silang, memutar sumber, menghubungkannya dengan seluruh gambar target, memutarnya lagi, dll untuk semua rotasi.
Perhatikan bahwa ini tidak akan selalu menemukan gambar. Jika gambar sumber adalah noise acak, dan targetnya adalah noise acak, Anda tidak akan menemukannya kecuali jika Anda mencari pada sudut yang tepat. Untuk situasi normal, mungkin akan menemukannya, tetapi itu tergantung pada properti gambar dan sudut yang Anda cari.
Halaman ini menunjukkan contoh bagaimana hal itu akan dilakukan, tetapi tidak memberikan algoritma.
Offset apa pun yang jumlahnya di atas ambang tertentu adalah kecocokan. Anda dapat menghitung kebaikan pertandingan dengan menghubungkan gambar sumber dengan dirinya sendiri dan membagi semua jumlah Anda dengan nomor ini. Pertandingan yang sempurna adalah 1,0.
Ini akan sangat berat secara komputasi, dan mungkin ada metode yang lebih baik untuk mencocokkan pola titik-titik (yang ingin saya ketahui).
Contoh Python cepat menggunakan metode grayscale dan 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
Bitmap 1 warna
Untuk bitmap 1-warna, ini akan jauh lebih cepat. Korelasi silang menjadi:
- Tempatkan gambar sumber di atas gambar target
- Pindahkan gambar sumber dengan 1 piksel
- bitwise-DAN semua piksel yang tumpang tindih
- jumlah semua 1s
- ...
Mengubah gambar abu-abu menjadi biner dan kemudian melakukan ini mungkin cukup baik.
Awan titik
Jika sumber dan target adalah kedua pola titik, metode yang lebih cepat adalah menemukan pusat setiap titik (berkorelasi silang satu kali dengan titik yang diketahui dan kemudian menemukan puncak) dan menyimpannya sebagai satu set titik, kemudian mencocokkan sumber untuk menargetkan dengan memutar, menerjemahkan, dan menemukan kesalahan kuadrat terkecil antara titik-titik terdekat dalam dua set.