图像拼接
在同一位置拍摄的两幅或者多幅图像是单应性相关的,我们就可以使用该约束将很多图像缝补起来,拼成一个大的图像来创建全景图像。
RANSAC方法是用来找到正确模型来拟合带有噪音数据的迭代方法。给定一个模型,例如点集之间的单应性矩阵,RANSAC基本的思想是,,数据中包含正确的点和噪声点,合理的模型应该能够在描述正确数据点的同时摒弃噪声点。
from array import array
from matplotlib.pyplot import figure, imshow, axis, show
from numpy.core import vstack
from numpy.ma import dot
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
# 将匹配转换成齐次坐标点的函数
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
if __name__=='__main__':
featname = ['jmu0' + str(i + 1) + '.sift' for i in range(5)]
imname = ['jmu0' + str(i + 1) + '.jpg' for i in range(5)]
im = [array(Image.open(imname[i]).convert('L')) for i in range(5)]
l = {}
d = {}
for i in range(5):
# 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])
# figure()
# gray()
# for i in range(4):
# sift.plot_matches(im[i + 1], im[i], l[i + 1], l[i], matches[i], show_below=True)
# figure()
# show()
# 估计单应性矩阵
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
# 扭曲图像
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()
以下五张图是嘉庚图书馆的后面
可以看到拼接后的图片只有在靠进体院操场和天空的那一块算是拼接得比较好的,但是拼接缝隙也较为明显,而偏向图书馆后面的那些树的部分则变形严重,甚至出现外扩的现象,而且模糊严重。可能是因为我拍摄的角度有问题,也可能是这个算法还不够完美,又或者是树这个元素的变量太多了,树叶分布、密度、颜色等容易对算法造成影响,所以导致了拼接之后的样子不理想。
然后我又拍了几张室内的图像,我发现一个问题,室内的图像相比于室外的图像,更不容易拼接成功,代码容易报错,我觉得是不是因为室内景深太浅,导致内容不够多造成的。然后我拍了好多次,下面是几张床铺的照片
可以发现,还是有几张图片被拼接起来的,但是可以发现有明显的畸变,而且拼接缝隙也非常不美观,并且非常模糊,具体原因可能是因为室内光线以及室内元素过少。