仅沿一个方向测量两个图像之间的偏移

Measuring shift between two images along one direction only

我必须测量两个单色图像之间的偏移。

这些图像实际上是校准前的光谱,非常嘈杂并且充满了不需要的特征,但它们基本上看起来如下

知道在不同的图像之间,它们沿 x 方向有偏移,但沿 y 方向没有。我想知道它们之间沿 x 方向的偏移量。

幸运的是我在skimageregister_translation中找到了一个函数,可以用于任意子像素精度。但问题是,我只想知道沿 x 方向的偏移,我希望得到的 y 方向偏移为 0,但程序发现同时偏移到 x 和 y,大概是沿着垂直于特征。 (图中蓝色箭头标注)

所以,我想知道:

  1. python中是否有任何函数或程序包可以测量两个图像之间仅沿一个方向的偏移,甚至可以使用任何先验知识?

  2. 找到两个嘈杂图像之间的偏移的正确方法是什么?在 FFT space 中找到最大互相关值可以完成这项工作吗?

方法一

您可以在两张图片之间使用 convolution 来查找您获得 maximum 的位置。您可以将其设想为将非移位图像从左向右滑动到移位图像上,并且当每张图像的相同部分位于另一个图像的顶部时,卷积将产生对应于场景的最大值。看看 scipy.ndimage.convolution and scipy.signal.convolve,看看哪个更适合您的需求。

方法二

  1. 另一方面,您可以从每个图像中取一个水平切片并找到峰值的位置(假设黑色条带为 1,白色区域为 0)。
  2. 计算每个图像中这些峰的质心。找到这些质心位置之间的差异,这就是您正在寻找的转变。
  3. 为了稳健性,您可以将其应用于图像对的各个行,并且所有此类差异的平均值对于水平偏移的度量将是统计上更可行的结果。

我不肯定它会起作用,但是:开源的好处之一是您可以查看 register_translationimplementation details,然后尝试使其适应您的情况.在您的情况下,我会将 fftn 替换为 fftn(..., axis=1),以便您仅计算沿列轴的 fft。然后,将两个 FFT 信号相乘(这相当于每条线的卷积,如@CypherX 所建议)。最后,您必须找到一种方法来 "coalesce" 将沿每条线发现的偏移转换为单个测量值。一个想法是采用每个班次(沿该线的最大值)并绘制直方图。人们会希望您在真正的 x 位移附近得到一个尖锐的峰值。

如果可行,将 "axis" 关键字参数添加到 register_translation 将对 scikit-image 做出相当大的贡献。您可以阅读 how to contribute guide 并提出相应的更改!

如果 register_translation 给你 xy 位移,在这种情况下应该做一些简单的数学运算,无论是向量形式还是分量形式。如果不存在 y 偏移,您可以计算 x 中所需的移动,这正是您想要的。我正在旅行,所以很遗憾现在不能给你图表,建议你画出三角形。

所需的额外 x 偏移 (x_extra) 定义为:

x_extra = y * tan[arctan(y_shift/x_shift)]

简化为:

x_extra = y_shift^2 / x_shift

因此,x 的总位移为:

x_shift_total = x_shift + x_extra

其中 x_shift 是由 register_translation 提供给您的。

如果您随后将 imageA 移动 x_shift_total,它应该与 imageB 对齐,假设 register_translation 给出的 x_shift 是正确的。

@jni 我很想在 register_translation 中将其作为一个选项来实现!

另一种更快更简单的方法是计算两个图像中相同位置的水平剖面。这将为您提供每个图像的水平一维轮廓。简单的峰值查找将为您提供线条的位置,峰值索引之间的差异将告诉您仅在 x 轴上的偏移。

我经常使用这种方法来进行与您的问题类似的移位检测,它非常非常快、非常简单并且非常可靠。

# pick a row to use
row = 10
x_profile1 = np.mean(image1[row, :], axis=0)
x_profiel2 = np.mean(image2[row, :], axis=0)

# 'get_peaks' is a function to return indices of found peaks - several
# around
peaks1 = get_peaks(x_profile1)
peaks2 = get_peaks(x_profile2)

x_shift = peaks1[0] - peaks2[0]