使用python和互相关进行图像配准

时间:2012-02-10 09:21:18

标签: python image cross-correlation

我得到了两张图片,显示了相同的内容:2D高斯形斑点。我把这两个16位的png文件称为“left.png”和“right.png”。但是,通过稍微不同的光学设置获得它们,相应的斑点(物理上相同)出现在略微不同的位置。意味着右边以非线性方式略微拉伸,扭曲或左右。因此,我希望从左到右进行转换。

因此,对于左侧的每个像素,其x和y坐标,我想要一个函数,给出位移矢量的分量,指向右侧的相应像素。

在前一种方法中,我试图获得相应斑点的位置以获得相对距离deltaX和deltaY。然后我将这些距离拟合到taylor扩展到T(x,y)的二阶,给出了左边每个像素(x,y)的位移矢量的x和y分量,指向相应的像素(x',y')在右边。

为了得到更一般的结果,我想使用归一化的互相关。为此,我将左边的每个像素值与右边的相应像素值相乘,并将这些乘积相加。我正在寻找的转换应该连接最大化总和的像素。因此,当总和最大化时,我知道我将相应的像素相乘。

我真的尝试了很多,但没有管理。我的问题是,如果你们中的某个人有想法或做过类似的事情。

import numpy as np
import Image

left = np.array(Image.open('left.png'))
right = np.array(Image.open('right.png'))

# for normalization (http://en.wikipedia.org/wiki/Cross-correlation#Normalized_cross-correlation)    
left = (left - left.mean()) / left.std()
right = (right - right.mean()) / right.std()

如果我能更清楚地说明这个问题,请告诉我。我仍然需要查看如何使用乳胶发布问题。

非常感谢您的投入。

left right

[left.png] http://i.stack.imgur.com/oSTER.png [right.png] http://i.stack.imgur.com/Njahj.png

我担心,在大多数情况下,16位图像看起来只是黑色(至少在我使用的系统上):(但当然有数据存在。

更新1

我试着澄清我的问题。我正在寻找一个矢量场,其位移矢量从left.png中的每个像素指向right.png 中的相应像素。我的问题是,我不确定我的约束。

enter image description here

其中向量r(分量x和y)指向left.png中的像素,向量r-prime(分量x-prime和y-prime)指向right.png中的对应像素。每一个r都有一个位移矢量。

我之前做的是,我手动找到了矢量场d的组件并将它们拟合到第二度的多项式:

enter image description here

所以我适合:

enter image description here

enter image description here

这对你有意义吗?是否有可能得到所有delta-x(x,y)和delta-y(x,y)的互相关?如果相应的像素通过位移矢量连接在一起,那么互相关应该最大化,对吧?

更新2

所以我想到的算法如下:

  1. Deform right.png
  2. 获取互相关的值
  3. Deform right.png进一步
  4. 获取互相关的值并与之前的值进行比较
  5. 如果它更大,那么良好的变形,如果没有,重做变形并做其他事情
  6. 在对互相关值进行最大化后,知道有什么变形:)
  7. 关于变形:可以首先沿x和y方向移动以最大化互相关,然后在第二步拉伸或压缩x和y依赖性并且在第三步中变形二次x-和y - 依赖并重复此过程iterativ ??使用整数坐标我真的有问题。你认为我必须插值图片以获得连续分布?我必须再考虑一下:(感谢大家参与:)

3 个答案:

答案 0 :(得分:2)

OpenCV(以及它的python Opencv绑定)有一个StarDetector类,它实现了this algorithm

作为替代方案,您可以查看OpenCV SIFT类,它代表Scale Invariant Feature Transform。

<强>更新

关于你的评论,我理解&#34;对&#34;转换将最大化图像之间的互相关,但我不明白你如何选择最大化的转换集。也许如果您知道三个匹配点的坐标(通过一些启发式或通过手工选择它们),并且如果您期望亲和力,您可以使用cv2.getAffineTransform之类的东西来为您的最大化过程进行良好的初始转换。从那里你可以使用小的额外转换来设置最大化的集合。但在我看来,这种方法似乎重新发明了SIFT可以照顾的东西。

要实际转换测试图像,您可以使用cv2.warpAffine,它也可以处理边框值(例如,填充0)。要计算互相关,您可以使用scipy.signal.correlate2d

<强>更新

您的最新更新确实为我澄清了一些观点。但我认为位移的矢量场不是最自然的东西,这也是误解的来源。我正在考虑更多的全局转换T,它应用于左图像的任何点(x,y)给出(x&#39;,y&#39;)= T(x ,y)在右侧,但T对每个像素具有相同的分析形式。例如,这可能是位移,旋转,缩放,也许是某些透视变换的组合。我不能说希望找到这样的变换是否现实,这取决于你的设置,但如果双方的场景在物理上是相同的,我会说期望一些仿射变换是合理的。这就是我建议cv2.getAffineTransform的原因。从这样的T计算位移矢量场当然是微不足道的,因为这只是T(x,y) - (x,y)。

最大的优势在于你的变换只有很少的自由度,而不是我认为,位移矢量场中的2N自由度,其中N是亮点的数量。

如果确实是仿射变换,我建议使用这样的算法:

  • 在左侧找出三个明亮且隔离良好的斑点
  • 对于这三个点中的每一个,定义一个边界框,以便您可以在右图中识别其中的相应点
  • 找到相应斑点的坐标,例如使用cv2.matchTemplate中实现的一些相关方法,或者只是找到边界框内最亮的点。
  • 一旦你有三对匹配的坐标,计算仿射变换,用cv2.getAffineTransform将一组转换成另一组。
  • 将此仿射变换应用于左图像,作为检查是否找到了正确的一个,如果整体归一化互相关高于某个阈值则可以计算,或者如果相对于另一个图像移位一个图像则显着下降。 / LI>
  • 如果您愿意并且仍然需要它,请从转换T中简单地计算位移矢量场。

<强>更新

似乎cv2.getAffineTransform需要一个笨拙的输入数据类型&#39; float32&#39;。我们假设源坐标为(sxi,syi),目标(dxi,dyi)i=0,1,2,那么您需要的是

src = np.array( ((sx0,sy0),(sx1,sy1),(sx2,sy2)), dtype='float32' )
dst = np.array( ((dx0,dy0),(dx1,dy1),(dx2,dy2)), dtype='float32' )

result = cv2.getAffineTransform(src,dst)

答案 1 :(得分:1)

我不认为互相关在这里会有所帮助,因为它只会为整个图像提供单一的最佳转换。我会考虑三种选择:

  1. 对点的子簇进行互相关。例如,右上角的三个点,通过互相关找到最佳的x-y偏移。这为您提供左上角的粗略变换。尽可能多地重复聚类以获得合理的转换图。适合你的泰勒扩展,你可能会合理地接近。但是,为了使您的互相关以任何方式工作,斑点之间的位移差异必须小于斑点的延伸,否则您永远无法使集群中的所有斑点与单个位移同时重叠。在这些条件下,选项2可能更合适。

  2. 如果位移相对较小(我认为是选项1的条件),那么我们可以假设对于左图中的给定点,右图中最近的点是相应的点。因此,对于左图中的每个点,我们在右图中找到最近的点并将其用作该位置的位移。从40个分布均匀的位移矢量中,我们可以通过拟合泰勒展开来获得实际位移的合理近似值。

  3. 这可能是最慢的方法,但如果你有大的位移(并且选项2不起作用)可能是最强大的方法:使用类似进化算法的东西来找到位移。应用随机变换,计算剩余误差(您可能需要将其定义为原始图像和变换图像中斑点之间最小距离的总和),并使用这些结果改进转换。如果您的位移相当大,您可能需要进行非常广泛的搜索,因为您可能会在您的景观中获得大量的局部最小值。

  4. 我会尝试选项2,因为看起来你的位移可能很小,很容易将左图像中的一个点与右图像中的一个点相关联。

    更新

    我认为你的光学系统会引起非线性失真并且有两个独立的波束(每个波场中不同的滤波器?)会使两个图像之间的关系更加非线性。 PiQuer建议的仿射变换可能会给出一个合理的方法,但可能永远不会完全覆盖实际的扭曲。

    我认为你的拟合低阶泰勒多项式的方法很好。这适用于具有类似条件的所有应用程序。最高订单可能应该是xy ^ 2和x ^ 2y;任何高于你不会注意到的东西。

    或者,您可以先校准每张图像的失真,然后进行实验。这样,您不依赖于点的分布,而是可以使用高分辨率参考图像来获得转换的最佳描述。

    上面的选项2仍然是我的建议,让两个图像重叠。这可以完全自动化,当您想要更一般的结果时,我不确定您的意思。

    更新2

    您评论说您在两张图片中匹配点时遇到问题。如果是这种情况,我认为您的迭代互相关方法也可能不是很强大。你有很小的点,所以只有当两个图像之间的差异很小时才会出现重叠。

    原则上,您提出的解决方案没有任何问题,但它是否有效取决于您的变形大小和优化算法的稳健性。如果您从很少的重叠开始,那么可能很难找到优化的良好起点。然而,如果你有足够的重叠开始,那么你应该能够首先找到每个点的变形,但在评论中你指出这不起作用。

    也许您可以选择混合解决方案:找到点簇的互相关以获得优化的起点,然后使用您在更新中描述的过程来调整变形。因此:

    1. 对于NxN像素段,找到左右图像之间的偏移
    2. 重复,例如,其中16个
    3. 使用这16个点
    4. 计算变形的近似值
    5. 将此作为优化方法的起点

答案 2 :(得分:0)

您可能希望了解bunwarpj已经完成了您正在尝试做的事情。它不是python,但我在这种情况下使用它。您可以导出纯文本样条线转换,并在需要时使用它。

相关问题