【问题标题】:Stitch multiple images using OpenCV (Python)使用 OpenCV (Python) 拼接多个图像
【发布时间】:2014-07-03 20:55:10
【问题描述】:

您好,已经看过很多关于如何使用两张照片进行简单图像拼接的教程,这没问题。
但是当我想从 4-6 张或更多图片中制作全景图时该怎么办?

我有接收图像文件列表的代码(图像按顺序从序列中的第一个图像到最后一个图像)。然后对于每个图像,我计算 SIFT 特征描述符 .但是后来我被卡住了,对于两个图像,我会使用 FLANN kd-tree 设置一个匹配器并找到图像之间的匹配并计算 Homography。类似于本教程http://docs.opencv.org/trunk/doc/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.html#py-feature-homography

但我没有在最后显示特征点之间的线条,而是使用了这个https://stackoverflow.com/a/20355545/622194 函数从 2 张图像中制作全景图。但是当我想将第三张和第四张图片添加到全景图时,我不确定该怎么做。

编辑:

从答案中,我尝试实现我的图像拼接脚本来计算图像序列中彼此相邻的图像之间的单应矩阵。所以如果我有 I1 I2 I3 和 I4 我现在有 H_12、H_23 和 H_34。然后我开始使用 H_12 缝合 I1 和 I2。然后我想找到累积单应性将 I3 拼接到当前全景图。我 fing H_13 = H_12*H_23 并将图像 3 拼接到当前全景图,但在这里我的全景图像中有非常明显的间隙,当缝合下一张图像时,间隙更大并且图像非常拉伸。

谁能告诉我我是否为此使用了正确的方法,或者有人可以发现错误或查看我做错了什么。

【问题讨论】:

  • 线程中注释代码的链接已被禁用
  • pastebin 链接不再有效。您介意再次提供代码吗?

标签: opencv computer-vision image-stitching


【解决方案1】:

一步一步,假设你想拼接四个图像I0I1I2I3,你的目标是计算单应性H_0H_1H_2、@987654329 @;

  1. 计算所有成对的单应性H_01H_02H_03H_12H_13H_23,其中单应性H_01将图像I0扭曲成@987654338等...
  2. 选择一个锚图像,例如I1 哪个位置将保持固定,即H_1 = Identity
  3. 根据最大数量找到更符合I1 的图像 一致的匹配,例如I3
  4. 更新H_3 = H_1 * inv(H_13) = inv(H_13) = H_31
  5. 查找与I1I3 更好匹配的图像,例如I2 匹配I3
  6. 更新H_2 = H_3 * H_23
  7. 同上图I0
  8. 进行捆绑调整以全局优化对齐

请参阅这篇开创性论文Automatic Panoramic Image Stitching using Invariant Features 的第 4 部分以获得深入的解释。

【讨论】:

  • 如果我尝试进行 360° 全景拍摄,同样的方法是否有效?我知道图像img0,img1 ... imgN的顺序。那么足以存储img0-img1,img1-2和imgN-1-imgN之间的单应性然后找到找到img0-img1之间的变换我使用H_01和(img0-img1)-img2我会我们H_02 = H_01*H_12 ?那行得通吗?我感觉到您的方法假设我不知道图像应该匹配在一起。如果我知道图像序列,我相信在 img0 和 img5 之间存储 Homography 是没有用的,因为它们匹配很差。
  • 是的,它适用于 360° 全景。束调整对于校正全局对齐和正确包裹全景图至关重要。当然,如果您正在为特定全景图创建算法并且您知道某些图像匹配不佳,您可以避免计算它们之间的单应性
  • @memecs 论文链接失效了。
  • 你能详细一点吗?做捆绑调整以全局优化对齐?
【解决方案2】:

Hack 方法

考虑到您编写的函数,最简单的方法(虽然不是超级高效)是通过将全景图像与每个连续图像拼接来扩大全景图像。类似这样的伪代码:

panorama = images[0]
for i in 1:len(images)-1
    panorama = stitch(panorama,images[i])

此方法基本上尝试将下一张图像与当前全景图的任何部分进行匹配。假设每张新图像都位于当前全景图的边界上,并且没有太多的透视失真,它应该工作得很好。

数学方法

如果您知道要缝合的顺序,另一种选择是从一个图像到下一个图像中找到 Homography,然后将它们相乘。结果是从该图像到图像 0 的 Homography。

例如:将图像 3 转换为与图像 0 对齐的 H 为 H_03 = H_01 * H_12 * H_23。其中 H_01 是将图像 1 转换为与图像 0 对齐的 H。(根据他们的代码定义 H 的方式,您可能需要颠倒上述乘法顺序。)因此,您将乘以得到 H_0i,然后使用它来转换图像 i 与图像 0 对齐。

有关为什么将转换相乘的背景,请参阅:Transformations and Matrix Multiplication 特别是“转换的组成”部分。

【讨论】:

  • hacky 方法的问题在于,一旦图像变形,就很难可靠地估计匹配特征。
  • @memecs - 绝对正确。 (这就是我所说的透视失真。)
  • 好的,不确定我这样做是否正确,但这是我的代码:pastebin.com/HLAnF62p 但这不起作用。前两个图像被正确拼接,但是当我添加第三个图像时,我得到了一些奇怪的东西,窗口变得非常大,我只看到前两个图像的一部分缝合在一起,而第三个图像什么也看不到。这很接近,但我只需要找出如何正确转换第三个以上的图像。如果我乘以单位矩阵,则图像只是以较小的平移叠加在彼此之上。
【解决方案3】:

我在图像之间的间隙方面遇到了类似的问题。 您应该做的第一件事是在第一帧将累积的单应矩阵初始化为身份。 然后,对于每个新帧,您应该将其乘以当前帧和下一帧之间的单应矩阵。请注意使用 numpy 矩阵而不是 numpy 数组。 IDK 为什么,但它们有不同的乘法例程。

这是我的代码:

def addFramePair(self, images, ratio=0.75, reprojThresh=4.0, showMatches=False):        
    (imageA, imageB) = images
    (kpsA, featuresA) = self.detectAndDescribe(imageA)
    (kpsB, featuresB) = self.detectAndDescribe(imageB)

    H = self.matchKeypoints(kpsA, kpsB, featuresA, featuresB, ratio, reprojThresh)
    self.accHomography *= np.asmatrix(H)
    result = cv2.warpPerspective(imageA, np.linalg.inv(self.accHomography), (1600, 900))
    return result

imageA 是当前的,imageB 是下一个。

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2020-03-10
    • 2023-03-17
    • 2011-12-26
    • 2011-08-26
    • 2021-10-03
    • 1970-01-01
    • 1970-01-01
    • 2019-01-01
    • 2012-12-01
    相关资源
    最近更新 更多