我正在通过互相关处理图像配准问题,有时会看到奇怪的现象。首先,我通过从每个像素中减去平均图像亮度来预处理每个图像,然后应用余弦窗口来处理我的图像在边缘上不是周期性的事实。
然后我在傅里叶空间中做一个简单的互相关并创建相关表面。我在 Python 中工作,所以这里有一些显示我在做什么的临时代码:
import numpy as np
from scipy.signal.windows import cosine as wind
im1 = np.load(file1)
im2 = np.load(file2)
rows, cols = im1.shape
hr = np.reshape(wind(rows, sym = False), (rows, 1))
hc = np.reshape(wind(cols, sym = False), (cols, 1))
h2d = np.dot(hr, hc.T)
im1 = im1 - im1.mean()
im2 = im2 - im2.mean()
im1 = im1 * h2d
im2 = im2 * h2d
fft1 = np.fft.fft2(im1)
fft2 = np.fft.fft2(im2)
prod = fft1 * fft2.conj()
surface = np.abs(np.fft.ifft2(prod))
当两幅图像之间的相对位移较大时,(0,0) 像素似乎被整体相关表面峰结构所淹没。但是,当相对偏移变小时,(0,0) 像素开始占主导地位,不再是整个表面的平滑部分。这会导致一个简单的峰值查找算法(如 numpys argmax)锁定 (0,0) 的偏移,即使仍然存在微弱的相关峰值表面。
我很好奇什么会导致这样的事情发生?一般来说,一组两个移位的图像会导致 (0,0) 像素占主导地位吗?
编辑 4:我发现了一个名为 match_template 的 scipy 函数,它结合了 JP Lewis 提出的相关表面的归一化。该方法要求模板尺寸小于参考图像。我通过将参考图像零填充到原始图像大小的 2 倍来实现这一点,这样在模板卷积后,整个图像尺寸都包含有效的相关结果。我发现我上面的代码和这个 match_template 方法之间基本上没有区别,并且 (0,0) 峰值仍然是最强的组件,而在某些情况下它不应该是。我认为创可贴解决方案是对 (0,0) 像素进行插值,使其成为整个表面的一部分。我正在记下所有这些,希望这对将来的某人有所帮助,因为这个问题并没有引起太大的关注。
编辑3:经过一些深入的文献回顾,很明显这种互相关方法充其量是归一化互相关的近似值。似乎 NCC 中的分母在傅立叶空间中没有可轻松计算的等价物。此外,对相同大小的图像进行互相关,除了 (0,0) 移位分量之外,不可避免地会导致任何地方的不准确性。这是由于两个图像中的像素在它们相对于彼此移动后不再重叠。在空间上,这可以/必须通过填充图像来解决,以便在任何地方定义相关性。这种填充会导致不准确,但有必要搜索两者之间的所有可能翻译。我有另一个与这一点相关的问题。当像上面的代码那样进行互相关时,应用了什么“填充”?在傅立叶空间中如何处理非重叠部分?我从不定义填充,但我得到的表面与输入图像的大小相同......那么除了 (0,0) 之外的每个像素的幕后发生了什么?
编辑 2:我偶然发现相关表面的 (0,0) 像素始终等于 fft 乘积的平均值。这让我觉得它有点确定性,并且表面中的 (0,0) 像素并没有真正编码任何关于实际偏移的信息?
编辑以添加示例图像,注意底层结构不是以该中心 (0,0) 像素为中心,但它是表面的最大组成部分。此外,此表面已使用 np.fft.fftshift() 进行了移动,以使可视化更容易。