提问者:小点点

使用OpenCV(Python)缝合多个图像


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

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

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

编辑:

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

有人能告诉我,我在这方面是否使用了正确的方法,或者有人能发现错误或者看到我做错了什么吗。


共3个答案

匿名用户

一步一步地,假设您想要缝合四幅图像,I0I1I2I3,您的目标是计算同音字H_0H_1H_2H_3

  1. 计算所有成对同形词H_01H_02H_03H_12H_13H_23,其中单形词H_01将图像I0扭曲为I1,等等
  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. 进行捆绑调整以全局优化对齐

请参阅本论文的第4节使用不变特征进行自动全景图像拼接,以获得更深入的解释。

匿名用户

根据您编写的函数,最简单的方法(虽然不是超高效的)是通过将全景图像与每个连续图像缝合来增加全景图像。类似这样的伪代码:

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

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

另一个选择,如果你知道你想要缝合的顺序,是找到从一个图像到下一个图像的单应性,然后将它们相乘。结果是该图像到图像0的单应性。

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

有关为什么要乘转换的背景信息,请参阅:转换和矩阵乘法,特别是“转换的组成”部分。

匿名用户

我也有类似的问题,图像之间的差距。您应该做的第一件事是在第一帧将累积单应性矩阵初始化为恒等式。然后,对于每一个新帧,你应该将它乘以当前帧和下一帧之间的单应性矩阵。请注意使用Numpy矩阵,而不是Numpy数组。但是它们有不同的乘法例程。

这是我的密码:

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

图像A是当前的,图像B是下一个。

希望这有帮助。