欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

全景图像的拼接

程序员文章站 2022-07-15 07:54:38
...

一、全景图像的拼接原理和步骤

1.1 全景图像的拼接相关原理

图像全景拼接涉及到了SIFT特征匹配和RANSAC算法。

1.1.1 SIFT特征匹配

为了匹配特征点,为后续图像拼接做准备。(详细原理请看https://editor.csdn.net/md/?articleId=104726476)

1.1.2 RANSAC算法匹配

在图像拼接中采用SIFT进行图像的特征匹配时,经常会出现匹配错误的连线,这会导致图像拼接的时候出现偏差,便不能成功拼接图像,这时候使用RANSAC算法。RANSAC算法会从匹配的数据集中随机抽出几个样本并保证抽出的样本之间不共线,计算出样本单应性矩阵,然后利用这个模型测试所有的匹配数据,并计算满足这个模型数据点的个数与投影误差(即代价函数),若此模型为最优模型,则对应的代价函数最小。这样便可以剔除匹配错误的特征点匹配对,采用不断迭代的方法,寻找到一个较为稳健的单应性矩阵,并且使得满足该矩阵的数据点个数最多。
:单应性矩阵是要实现图像拼接重要方法。它表示了两张图象之间的对应特征点的变换关系。有了这个关系,我们就可以实现图像正确的拼接到另一张图像上。

1.2 全景图像的拼接步骤

图像全景拼接的整体流程如下

1、根据给定的图像集,实现图像之间的特征匹配;

2、通过匹配特征,计算图像之间的变换结构;

3、利用图像的变换结构,实现图像间的映射;

4、针对叠加后的图像,采用相应算法,对齐特征点;

5、通过图割的方法,自动选取拼接缝;

6、图像进行融合。

二、全景图像的拼接实现

2.1 全景图像的拼接相关代码

2.1.1 代码分析

1、用RANSAC算法实现针对固定点位拍摄多张图片,以中间图片为中心的图像的拼接融合拼接3张图片
2、代码中有个参数delta。这个参数是针对你拍摄图像时,你相对平移的距离的变量,当你拍摄近景时候,这个参数尽量该小,远景相反。
3、dpi是图像精细度的变量,可以通过修改来改变图像的分辨率,数值越大表示图像越精细,即分辨率越高。

2.1.2 代码实现

# RANSAC算法拼接3张图片
from pylab import *
from numpy import *
from PIL import Image
from PCV.geometry import homography, warp
from PCV.localdescriptors import sift

featname = ['C:/images' + str(i + 1) + '.sift' for i in range(3)]
imname = ['C:/images' + str(i + 1) + '.jpg' for i in range(3)]

l == {}
d = {}
for i in range(3):
    sift.process_image(imname[i], featname[i])
    l[i], d[i] = sift.read_features_from_file(featname[i])

matches = {}
for i in range(2):
    matches[i] = sift.match(d[i + 1], d[i])

# visualize the matches (Figure 3-11 in the book)
for i in range(2):
    im1 = array(Image.open(imname[i]))
    im2 = array(Image.open(imname[i + 1]))
    figure()
    sift.plot_matches(im2, im1, l[i + 1], l[i], matches[i], show_below=True)


# function to convert the matches to hom. points
def convert_points(j):
    ndx = matches[j].nonzero()[0]
    fp = homography.make_homog(l[j + 1][ndx, :2].T)
    ndx2 = [int(matches[j][i]) for i in ndx]
    tp = homography.make_homog(l[j][ndx2, :2].T)

    # switch x and y - TODO this should move elsewhere
    fp = vstack([fp[1], fp[0], fp[2]])
    tp = vstack([tp[1], tp[0], tp[2]])
    return fp, tp


# estimate the homographies
model = homography.RansacModel()

fp, tp = convert_points(1)
H_12 = homography.H_from_ransac(fp, tp, model)[0]  # im 1 to 2

fp, tp = convert_points(0)
H_01 = homography.H_from_ransac(fp, tp, model)[0]  # im 0 to 1

# warp the images
delta = 500  # for padding and translation

im1 = array(Image.open(imname[1]), "uint8")
im2 = array(Image.open(imname[2]), "uint8")
im_12 = warp.panorama(H_12, im1, im2, delta, delta)

im1 = array(Image.open(imname[0]), "f")
im_02 = warp.panorama(dot(H_12, H_01), im1, im_12, delta, delta)

figure()
imshow(array(im_02, "uint8"))
axis('off')
savefig("ps.jpg", dpi=300)
show()

2.2 全景图像的拼接实现结果

实验对不同场景进行对比:

2.2.1 场景一

要拼接的原图像
全景图像的拼接
先对图像进行特征点匹配
全景图像的拼接
全景图像的拼接
拼接后的图像
全景图像的拼接
分析:室内的近景拍摄图像拼接出来的效果存在问题,大概率是因为室内近景拍摄的距离过近,导致在拼接时候边缘的图像会过分的拉伸而使拼接出现问题。当我们拍摄图像时,我们所拍摄的目标和我们的相机之间存在某个物体,上图为存钱罐和花盆后面的花瓶。这样我们在旋转拍摄角度的时候,物体和目标之间在相机偏差的位置就会有变化,这样导致在拍摄的图像中目标和物体的位置就会有差距,这样的图像做全景图像的拼接就会有重影产生。重影的消除,我们可以采用图割法或者最大流最小割

2.2.2 场景二

要拼接的原图像
全景图像的拼接
拼接后的图像
全景图像的拼接

2.3 实验分析与总结

从以上实验结果我们可以发现:拍摄室内的图像,由于室内近景拍摄的距离过近就会对匹配的结果产生一定程度的影响。拍摄于室外景深复杂的图像,拼接的效果较好。
(1)尽量拍摄场景清晰,有较明显特征的图像,因为图像内容繁杂会影响拼接结果。
(2)实验中,为了图像美观以及方便阅览,我们需要自行调整代码中delta的值,使得最后的拼接图像呈现一个合理的大小。
(3)实验中,要拼接的图像大小会影响的程序的速度,所以在拍摄图像上传到电脑时候尽量别上传原图。

三、实验遇到的问题

1、问题1:全景图像的拼接
解决方法:
第一步:
import matplotlib.delaunay as md改成from scipy.spatial import Delaunay
第二步:
进入到PCV\geometry\warp.py,把triangulate_points(x,y)里面的代码替换成tri = Delaunay(np.c_[x,y]).simplices

2、问题2:
全景图像的拼接
解决方法:python3要求print后面加括号

3、问题3:出现 ValueError: did not meet fit acceptance criteria 的错误,这是由于拍摄的图像水平落差比较大,你需要重新拍摄一组图像。