一、全景拼接的原理
1.1 SIFT特征匹配
关于sift算法原理请见上一篇博客,此处不多赘述。见:SIFT算法Python
1.2 RANSAC算法
RANSAC的全称是“RANdom SAmple Consensus(随机抽样一致)”。它可以从一组包含“局外点”的观测数据集中,通过迭代方式估计数学模型的参数。它是一种不确定的算法,也就是说它有一定的概率得出一个合理的结果,所以为了提高概率必须提高迭代次数。
(1)步骤
1.随机选择四对匹配特征
2.根据DLT计算单应矩阵 H (唯一解)
3.对所有匹配点,计算映射误差ε= ||pi’, H pi||
4.根据误差阈值,确定inliers(例如3-5像素)
5.针对最大inliers集合,重新计算单应矩阵 H
(2)示例
1.在给定若干二维空间中的点,求直线 y=ax+b ,使得该直线对空间点的拟合误差最小。
2.随机选择两个点,根据这两个点构造直线,再计算剩余点到该直线的距离
给定阈值(距离小于设置的阈值的点为inliers),计算inliers数量
3.再随机选取两个点,同样计算inliers数量
4.循环迭代,其中inliers最大的点集即为最大一致集,最后将该最大一致集里面的点利用最小二乘拟合出一条直线。
(3)参数
在上面原理介绍中,有两个重要的参数需要设置,即采样次数和阈值。
当数据过大的时候,若采集所有样本会造成算法复杂度过高,计算难度加大。Fischler和Bolles通过概率统计的方法得出了采样次数与数据中外点比例和得到一个好样本概率之间的数学关系。
其中K为需要采样的次数,z为获取一个好样本的概率,一般设为99%;w为点集中inliers的比例,一般可以在初始时设置一个较小值,如0.1,然后迭代更新;n为模型参数估计需要的最小点个数,通常设置为2,直线拟合最少需要2个点。
阈值一般根据经验来设定,当观测误差符合0均值和sigma标准差的高斯分布时,则可以计算距离阈值。当inliers被接受的概率为95%时,阈值t2=3.84σ2。
1.3 图像拼接
基于RANSAC算法的图像拼接是利用RANSAC算法估计出的图像间的单应性矩阵,再将所有图像扭曲到一个公共的图像平面上。
通常,这里的公共平面为中心图像平面(否则,需要进行大量变形)。一种方法是创建一个很大的图像,比如图像中全部填充0,使其和中心图像平行,然后将所有的图像扭曲到上面。由于我们所有的图像是由照相机水平旋转拍摄的,因此我们可以使用一个较简单的步骤:将中心图像左边或者右边的区域填充0,以便为扭曲的图像腾出空间。
二、代码
主函数
from scipy.spatial import Delaunay
from numpy import *
from matplotlib.pyplot import *
from scipy import ndimage
from PIL import Image
import warp
import homography
import matplotlib.pyplot as plt
from PCV.localdescriptors import sift
featname = ['img/' + str(i + 1) + '.sift' for i in range(5)]
imname = ['img/' + 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