在此前了解了SIFT的特征点的提取与匹配,并且在SIFT的基础上,采用RANSAC算法对图像变换矩阵进行求解与精炼,删除错配。全景拼接需要在此基础上完成。
1.在连续图像对间使用sift特征寻找匹配对应点对
2.进行可视化匹配,匹配两幅图像之间的特征
3.将匹配转换成齐次坐标点的函数,估计单应性矩阵
4.通过估计出图像间的单应性矩阵,将所有的图像扭曲到一个公共的图像平面上
要实现两张图片的简单拼接,其实只需找出两张图片中相似的点 (至少四个,因为 homography 矩阵的计算需要至少四个点), 计算一张图片可以变换到另一张图片的变换矩阵 (homography 单应性矩阵)拟合成一个单应性矩阵。对每个对应点对使用该单应性矩阵,然后返回相应的平方距离之和。用这个矩阵把那张图片变换后放到另一张图片相应的位置 ,从而实现全景拼接
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 = ['C:/Users/Administrator/Desktop/pythonhomework/pingjie4/'+str(i+1)+'.sift' for i in range(5)]
imname = ['C:/Users/Administrator/Desktop/pythonhomework/pingjie4/'+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([fp[1],fp[0],fp[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 = 1200 # 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')
savefig("example.png",dpi=300)
show()
起初没有注意代码逻辑需要从右往左编写图片序号,导致最后拼接结果出现问题,
错误的结果:
发现问题后,改变图片顺序,按照拍摄从右往左的顺序进行编号,正确的结果:
图片拼接效果不理想,如果以建筑物,或者树木为参照物,在照片交接处有很明显的明暗差,但是拼接的位置基本正确。如果以天台的护栏为参照物,可以看到图片已经扭曲的很厉害了。我觉得主要原因是拍摄地点位于天台,拍摄的时候有充足的阳光,并且从左侧往右侧照射。可以看到最右侧的一张图,建筑物的照射很明显,但是左侧的光照就相对较少。导致画面有很明显的明暗差。图片拼接后出现扭曲是因为APAP算法是对每个小格做单应性变换,从单个小格看是没有特征的,所以拼接起来会出现扭曲的现象。
因为图片集1出现了明暗差明显的问题,拍摄图片集2我选择在房间内拍摄,拍摄位置固定在左侧的窗户边,让光线充分的照射整个房间。可以看到最后得出来的拼接效果相对图片集1好了很多,还有瑕疵的地方就是相对于窗户最深处,书架书桌的位置光线与衣柜相比还是相对较暗。仍然存在图片扭曲
图片是围绕着面前两盆植株进行拍摄的,可以看到每张图片,植株与后面的建筑物的相对位置是不断变化的。在不同角度能观测到同一个特征点,但是不同角度的图片进行重叠的时候,显然是不能吻合的。
1、进入warp.py中可以看到导入的错误包
2、将 import matplotlib.delaunay as md 改成 from scipy.spatial import Delaunay
3、将函数里把triangulate_points(x,y)里面的代码替换成
tri = Delaunay(np.c_[x,y]).simplices
1、由于Apap将图像切割成无数多个小方块,对每个小方块进行单应性矩阵变换,显然图片像素越高,所需的运行时间就越久。因此可以对图片进行等比例缩放,缩短运行时间。
2、因为APAP算法是对每个小格做单应性变换,从单个小格看是没有特征的,所以拼接起来会出现扭曲的现象。
3、在图片拍摄地点的选取上,可以选择背对光源的位置进行拍摄,减少明暗差,拼接效果会更好。
4、图片拍摄的位置需要固定,若变更拍摄位置,在图片重叠的时候会严重扭曲图像。