图像拼接
【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,运行很顺利,速度也很快,但是出现的结果非常不如人意,特征点匹配还算可以,但是拼接的图片完全不能识别出是中山纪念馆,结果如下图
最后的拼接结果如图
为了解决以上问题,我提高了图片的像素(20001500),运行时间非常长,结果如下图
可以看出全景图片左侧拼接良好,但是右侧因为树木较多,所以拼接混乱,最后将像素该成了(1500*1125)
结果如图所示
如上图所示,拼接后的图片可以看出基本建筑,但是还是有些明显的色差竖线等问题存在,以上问题会在今后的学习中继续完善。