匹配蒙版图像

信息处理 图像处理 fft 窗函数 相关性
2022-02-10 14:20:56

假设我有两个图像是同一个更大图像的一部分,使用两个蒙版剪切(为简单起见,我们假设蒙版只是大小相同的矩形)。假定图像重叠。具体的例子是:图像稳定(相同背景的两个不同视图)和对象跟踪(匹配两个图像上的对象)。

我已经阅读了这篇出色的文章http://werner.yellowcouch.org/Papers/subimg/,但它处理的是找到一个小图像的位移,它是一个大图像的一部分,而我想找到两者之间的位移相同大小的图像。我的图像相交,但不包含彼此。

我想找到正确重叠图像匹配部分的平移变换系数。我想使用基于 FFT 的相关匹配之类的东西。简单地使用 FFT 相关有以下问题:

  1. 图像帧的边缘是强特征。如果算法搜索最大化类似的位移 ] ,它只会捕捉图像,以便它们的帧匹配,忽略内容。我听说过窗口化,但我不明白如何在这里应用它。如果每个图像在边缘处呈锥形,则图像在正确定位时将不再匹配。[dx,dy]x,ya[x,y]b[x+dx,y+dy]
  2. 如果我们使用一个相关函数,通过将结果除以位移匹配产生的交集区域来归一化结果,算法只会尝试将交集保持在最小值(~1x1 像素;交集区域越小,越容易它是找到一个几乎完美的匹配。)

如何使用窗口或其他一些技术来解决这个匹配问题?

更新:我知道可以通过丢弃低频信息(采用梯度或应用 Sobel 算子)部分消除该问题。我试图在不丢弃低频信息的情况下解决问题。此外,仅保留高频特征仍然不能解决概述的问题:想象一个图像具有明亮的细水平光束和暗淡的正方形。这些特征是高频的,因此在应用过滤器后仍将保留。互相关将匹配忽略正方形的明亮光束部分。

这是显示匹配问题的示例:

带边框的完整图像:

带边框的完整图像

帧 1 和 2:

第一帧 第 2 帧

基于相关的不正确帧匹配:

基于相关的不正确匹配

1个回答

好的,这是Python中说明的简单方法:

# Correlation is convolution with one input reversed
corr = fftconvolve(img1, img2[::-1, ::-1])

# Get coordinates of peak in x, y pixels
peak = unravel_index(corr.argmax(), corr.shape)
# peak = (199, 189)
# Calculate offset from center point
print array(peak) - 199 # Offset is [  0 -10]

因此,它会找到垂直偏移(10 像素),但不是水平偏移,如您所示(左下角输出)。这是因为当更多的输入图像重叠时,中心的互相关输出更强(即使输入相同,边缘也会变暗)。(找到的峰用红叉表示。)

这是我在评论中描述的方法。我不知道这是否有严格的数学基础,或者它是否有名字,但它产生了正确的结果。它可能与标准化互相关可能相同,也可能不同(我没有费心去解读维基百科的意思):

weighting = fftconvolve(ones(shape(img1)), ones(shape(img2)))
corr = corr / weighting # Normalize
peak = unravel_index(corr.argmax(), corr.shape)[::-1]
# peak = (224, 189)
print array(peak)-199 # Offset of [ 25 -10]

所以这个方法有效。它通过用于计算该元素的重叠像素的数量对输出数组的每个元素进行归一化,因此当只有图像的薄边缘重叠时,它仍然会产生强输出。现在,从暗方块的偏移量不会被白条(图像右下角)淹没。

请注意,虽然这适用于您的示例图像,但此方法不适用于真实图像,因为输出的边缘与中间相比往往变化很大,并且可能产生虚假峰值,但如果您知道偏移量被限制为小于图像宽度,您只能在中心附近的实际位置寻找峰值,忽略边缘,它可以工作。

加权法

维基百科建议一种使用窗口图像的方法,我认为这可能会有所改进,但除非我做错了,否则它不会:

h = hamming(shape(img1)[0]) # 1D Hamming window
ham2d = outer(h, h) # 2D Hamming window

h1 = img1 * ham2d
h2 = img2 * ham2d

corr = fftconvolve(h1, h2[::-1,::-1])
peak = unravel_index(corr.argmax(), corr.shape)[::-1]
# peak = (216, 189)
print array(peak) - 199 # Offset is [ 17 -10]

加窗做得太多,并导致它在前两个结果之间找到一个错误的峰值。

窗口法