图像拼接

【SIFT】实例 图像拼接 Image Stitching
在同一位置(即图像的照相机位置相同)拍摄的两幅或者多幅图像是单应性相关的。我们经常用该约束来拼接图像,创建全景图像。
一、原理解释
1、图像拼接流程
①加载图片,提取SIFT特征点
②两张图片的SIFT特征匹配
③估计图片的几何变换(一张图作为模范图,另外一张图作为移动图,也就是对移动图进行拉伸旋转等几何变换)
④图片融合(最大密度投影法等)
2、RANSAC
RANSAC是“RANdom SAmple Consensus(随机一致性采样)”的缩写。它可以从一组包含“局外点”的观测数据集中,通过迭代方式估计数学模型的参数。用来找到正确模型来拟合带有噪声数据的点集,想要提高正确概率必须提高迭代次数。核心思想就是随机性和假设性,随机性用于减少计算,循环次数是利用正确数据出现的概率。所谓的假设性,就是说随机抽出来的数据都认为是正确的,并以此去计算其他点,获得其他满足变换关系的点,然后利用投票机制,选出获票最多的那一个变换。
二、运行过程
代码如下所示

from pylab import *
from numpy import *
from PIL import Image

# If you have PCV installed, these imports should work
from PCV.geometry import homography, warp
from PCV.localdescriptors import sift

"""
This is the panorama example from section 3.3.
"""

# set paths to data folder
featname = ['r' + str(i + 1) + '.sift' for i in range(5)]
imname = ['r' + str(i + 1) + '.jpg' for i in range(5)]

# extract features and match
l = {}
d = {}
for i in range(5):
    sift.process_image(imname[i], featname[i])
    l[i], d[i] = sift.read_features_from_file(featname[i])

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

# visualize the matches (Figure 3-11 in the book)
for i in range(4):
    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

tp, fp = convert_points(2)  # NB: reverse order
H_32 = homography.H_from_ransac(fp, tp, model)[0]  # im 3 to 2

tp, fp = convert_points(3)  # NB: reverse order
H_43 = homography.H_from_ransac(fp, tp, model)[0]  # im 4 to 3

# warp the images
delta = 2000  # 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)

im1 = array(Image.open(imname[3]), "f")
im_32 = warp.panorama(H_32, im1, im_02, delta, delta)

im1 = array(Image.open(imname[4]), "f")
im_42 = warp.panorama(dot(H_32, H_43), im1, im_32, delta, 2 * delta)

figure()
imshow(array(im_42, "uint8"))
axis('off')
show()

首先在中山纪念馆前拍摄了一组照片(五张),像素为1000750,运行很顺利,速度也很快,但是出现的结果非常不如人意,特征点匹配还算可以,但是拼接的图片完全不能识别出是中山纪念馆,结果如下图
图像拼接
图像拼接
图像拼接
图像拼接
最后的拼接结果如图
图像拼接
为了解决以上问题,我提高了图片的像素(2000
1500),运行时间非常长,结果如下图

图像拼接
可以看出全景图片左侧拼接良好,但是右侧因为树木较多,所以拼接混乱,最后将像素该成了(1500*1125)
结果如图所示
图像拼接
图像拼接
图像拼接
图像拼接
图像拼接
如上图所示,拼接后的图片可以看出基本建筑,但是还是有些明显的色差竖线等问题存在,以上问题会在今后的学习中继续完善。