这不是最好的解决方案,但它是一个解决方案。我想学习更好的技术:
如果它们不被旋转或缩放,您可以使用图像的简单互相关。小图像出现在大图像中的任何地方都会有一个明亮的峰值。
您可以使用 FFT 方法加速互相关,但如果您只是将小源图像与大目标图像进行匹配,蛮力乘加法有时(通常不是)更快。
资源:
目标:
互相关:
两个亮点是匹配的位置。
但是您的示例图像中确实有一个旋转参数,因此它本身不会起作用。如果只允许旋转,不允许缩放,那么还是可以使用互相关的,但是需要互相关,旋转源,与整个目标图像互相关,再旋转等等。所有旋转。
请注意,这不一定会找到图像。如果源图像是随机噪声,而目标是随机噪声,则除非您以完全正确的角度进行搜索,否则您将找不到它。在正常情况下,它可能会找到它,但这取决于图像属性和您搜索的角度。
此页面显示了如何完成的示例,但没有给出算法。
总和高于某个阈值的任何偏移量都是匹配的。您可以通过将源图像与其自身相关并将所有总和除以该数字来计算匹配的好坏。完美匹配将是 1.0。
不过,这在计算上会非常繁重,并且可能有更好的方法来匹配点的模式(我想知道)。
使用灰度和 FFT 方法的快速 Python 示例:
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 色位图
不过,对于 1 色位图,这会快得多。互相关变为:
- 将源图像放在目标图像上
- 将源图像移动 1 个像素
- ...
将灰度图像阈值化为二进制然后这样做可能就足够了。
点云
如果源和目标都是点的模式,更快的方法是找到每个点的中心(与已知点交叉相关一次,然后找到峰值)并将它们存储为一组点,然后匹配源通过旋转、平移和找到两组中最近点之间的最小二乘误差来定位。