sift全景图拼接完整的项目(六)
来源:互联网 发布:宏程序编程入门讲解 编辑:程序博客网 时间:2024/05/16 08:13
如果你能看到这里,说明已经立志学习拼接算法了。在前面的文章中介绍一些原理,苦于没有一个完整的项目。这里就为大家提供一个GitHub的开源项目。该项目是在linux编写,用了很多C++11/14的特性,实测vs2015通过。如果在配置过程中有问题就评论我。
按照惯例,以下完全是参考:http://blog.csdn.net/hc1025808587/article/details/52922308#comments
本文全文翻译自http://ppwwyyxx.com/2016/How-to-Write-a-Panorama-Stitcher/。这是一个关于作者如何编写OpenPano算法的一个总结,OpenPano是一个开源的全景拼接软件。相关代码在github上。
SIFT Feature
Lowe 的SIFT[1]算法实现放在feature/
目录下。这个算法的流程和一些结果在这一章里做简单的介绍。
Scale Space & DOG Space
首先,一个尺度空间(Scale Space)由
高斯模糊通过两个一维卷积实现,而不是一个二维卷积。这将显著地加速该计算过程。
在每个层级(octave),计算每两个相邻的高斯模糊后图片的差值,可以构建一个差分高斯空间(DOG)。DOG空间由
Extrema Detection
在DOG空间中,通过比较相邻的三个方向26个像素来检测所有的极大或极小值:
然后使用抛物线插补(parabolic interpolation)去搜索极值精确的
Orientation Assignment
首先,在尺度空间计算每个点的梯度和方向。在之前的流程中检测到的每个关键点,根据他们的梯度幅度值作为权重,将它的相邻点的方向将累积起来并建立一个方向直方图,权重由它们的梯度的幅度决定,
Descriptor Representation
Lowe建议[1]选择关键点附近的16点来为每个店建立一个方向直方图并且合成为一个SIFT特征。每个直方图使用8个从0到360度的不同的格子。一次结果特征是一个128位浮点向量。因为每个关键点的主方向是已知的,利用相对于主方向的相对方向,这个特征是旋转不变的。
利用论文[2]的建议,利用一个简单修改的SIFT——RootSIFT,鲁棒性更强。
Feauture Matching
这个128维描述子的欧氏距离是两幅图之间特征匹配的距离标尺。如果一个点和他最近邻和次近邻的点之间的距离是相似的会被认定是不可信的而被拒绝。一次匹配的结果如下:
特征匹配被认为是最耗时的一步。所以我使用FLANN library去特征向量中查询两个最临近特征。Intel SSE intrinsics被用来加速去计算两个特征向量的欧氏距离。
Transformation Estimation
Estimate from Match
众所周知,对于任意两幅相机在固定点拍摄的图片,匹配对的齐次坐标都能够由一个单应变换矩阵联系起来,因此对于一对对应的点
单应矩阵是一个不考虑尺度影响的
当拍摄两幅图片时,相机仅存在平行于成像平面的旋转和平移变换时(没有视角申缩),那么它们能够通过一个仿射变换矩阵联系起来:
给定一组匹配点,以上的任何一个方程都能够通过直接线性变换(Direct Linear Transform)估计出来。这些估计方法的实现放在
lib/imgproc.cc
中。具体参照[3]然而这些方法对于噪声的鲁棒性并不强。实际上,由于错误匹配对的存在,RANSAC(Random Sample Consensus)算法[4]经常被用来在变矩阵的求解中剔除噪声。在RANSAC的每一步迭代中,几组匹配点对被随机地选择用来生成一个最佳的变换矩阵,并且和该矩阵一致的点对被看做是内点。在一定量的迭代后,拥有最多内点对的变换被看做最后的结果。该算法实现放在stitch/transform_estimate.cc
中。
Match Validation
在每次矩阵估计后,我对每个矩阵进行了优劣检查(health check),以避免因为错误的匹配对而产生畸变的变换估计。这个过程包括两种检查:(具体参见stitch/homography.hh
中)
- 单应变换
(H3,1,H3,2) 中的尺度参数不能太大。他们的绝对值应不能超过0.002。 - 跳动不能够出现在图像拼接过程中。如果
x
或y
坐标发生了跳动那么这个单应变换是不能够被接受的。
再无限制地拼接中,有必要判断两幅图是否匹配。上面流程中估计得到的大量内点能够作为一个评判尺度。然而,对于高分辨率图片,即使执行了足够多次的RANSAC迭代,也有可能实际上得到了一个有着大量内点的错误匹配。为了解决这个问题,考虑到错误匹配在空间上通常是更加随机分布的,通过设置匹配之间的几何限制条件能够帮助找出错误匹配对出来。因此,在RANSAC完成后会返回一组内点,按照论文[5]中的建议,可以通过一些重叠检测来进一步验证匹配情况。
特别的,知道了一个候选的变换矩阵,通过计算变换对应角点的凸包,我能够找出两幅图之间的重叠区域。在重叠区域被找到后就可以应用两个滤波器了。
- 两幅图的重叠区域不能够区别太大。
- 在重叠区域内,应该有足够大比例的匹配点对是内点。我使用了内点率来描述该匹配的置信度。
由于错误的匹配可能是随机和无规律的,这种方法能够帮助滤除带有错误几何信息的误匹配对。
Cylindrical Panorama
Necessity of Projection
给出一个单向的旋转变换照片输入,按照大多数全景拼接软件的做法,采用平面单应变换会导致垂直畸变,如下图:
这是因为全景实际上是通过柱面或者球面镜投拍摄得到,而并不再试平面镜头。在这种配置下,照片中草地上的面色圆圈其实一条直线。一个很好地解释了这种投影生成原因的demo见此页面。
处理这种问题的方式是在变换估计之前或者之后,通过柱面或者球面投影去畸变图片。这和本系统中的两种模式相对应。在这一节中我们将引入基于pre-warping的流水线方式,它被应用在柱面模式中。尽管需要很多的假设和一些技巧去是它良好的工作,这种流水线方式通常很好。它的实现放在stitch/cylstitcher.cc
目录中。
Warp
我们在拼接的一开始,先将图片投影到柱面,方程如下:
stitch/warp.cc
。一些畸变后的示例图片如下图。注意这要求提前知道相机的焦距,否则不会产生一个好的弯曲结果。
在将所有的图片投影到了相同的柱面上后,可以通过估计图片对之间的仿射变换来简单的拼接图片。并且通过选定一张特定的图片作为主图进行叠加。注意到操场上的白色线变得更直了。
straightening
由于相机的倾斜角度是未知的,上面描述的柱面投影是假设相机是水平的。这个假设会导致扭曲,输出的全景图可能会是弯曲的:
选择中间的图片作为基准有助于解决该问题。我发现了另一种有效地方法,这种方法通过搜索畸变方程中的
由于这种结果是因为相机的倾斜造成的,
单独改变
Camera Estimation Mode
Intuition
使用柱面投影去扭曲图像到圆柱表面时,假设已知相机焦距并且要求所有相机有同样的倾角向量。我们想要摆脱这些约束。
然而,如果只是简单地估计成对的单应变换,去直接拼接它们,在变换后投影大柱面上,将会得到类似于下图的结果:
注意到图片实际上拼接的很好:匹配点对都很好地重叠了。但是整体的几何结构被破坏了。
这是因为
而且,注意刀
相机参数的这种不一致的过度参数化将会导致上述这种过拟合的结果出现,因而打乱了图片潜在的内部几何结构。
人们通常用
Initial Estimation
[6]首先给出了一种粗略估计所有相机焦距的方法。在给出了一张图片所有的焦距和旋转矩阵后,相对应图片的旋转矩阵可以通过我们已经得出的单应变换求得:
因此,该估计算法原理类似于最大生成树算法:在建立一种匹配图后,我首先选择一张有着好的连接性质的图作为基准。然后,在每一步中,选择一张还未被处理的最佳匹配图片(考虑匹配置信度)那么它的旋转矩阵
stitch/camera_estimate.cc
文件中。注意到,由于单应变换
如果不执行捆绑调整,由于初始估计的
为了进一步的改善
Bundle Adjustment
我们通过如下方式规定
这里,
一些迭代方法例如牛顿法,梯度下降法,levenberg-Marquardt算法,都能够被用来解决这个优化问题。假定矩阵
- 梯度下降法:
∇θ=λJTr - 牛顿法:
∇θ=(JTJ)−1JTr - LM算法:
∇θ=(JTJ+λD)−1JTr,且D是对角矩阵
所有的迭代算法都涉及到计算矩阵
- 数值:对于每一个
θi ,振幅为±ϵ ,分别计算r1,r2 。然后计算J[:,i]=r1−r22ϵ - 符号:根据微分运算的链式法则计算
∂r∂θ 。比如,相关的方程如下:∂rk∂pij=−1,若rk=Xi−pij.否则为0 ∂pij∂p^ij=∂[xzyz]∂[x y z]=⎡⎣⎢⎢1z001z−xz2−yz2⎤⎦⎥⎥ ∂p^ij∂fi=∂Ki∂uiRiRTjK−1jXj ∂p^ij∂ui=Ki∂Ri∂uiRTjK−1jXj ∂p^ij∂uj=KiRi(∂Rj∂ui)TRTjK−1jXj ∂K∂f=⎡⎣⎢100010000⎤⎦⎥ ∂R∂ux=ux[u]x+[u×(I−R)ex]×||u||2R
最后一个方程来自于[7]。并且,我发现Lowe的论文[5]给出的方程是错误的:
由于
两种方法的实现都存放在stitch/incremental_bundle_adjuster.cc
。由于符号方式仅仅计算稀疏矩阵
在一组
在优化后,上面的前景图看起来将会更好:
Straightening
校直也是有必要的。按照论文[5]中建议的方式,由于相机倾角不明确,捆绑调整后的结果可能仍然存在波动现象。若假定所有相机的
来解决倾角和修复这种波动效应。
对比上面两张图,注意到草地上的直线被纠正了(它实际上是足球场上中心的一个圆)。
Blending
在完成所有的变换之后最终图片结果的大小就确定了。然后结果图片中的每个像素点的值通过逆变换和相邻区域像素点的双线性插值(可以消除锯齿现象)确定。
对于重叠区域,每个重叠像素到图像中心的距离被用来计算像素值的权值和。为了得到更好的全景图,我仅仅使用了
Cropping
当设置好了CROP
选项后,程序将从原始结果上找到一张最大的合法矩形。
我们使用的算法记作
对于每一行
对于每一个
参考文献
[1]: Distinctive Image Features From Scale-invariant Keypoints, IJCV04
[2]: Three Things Everyone Should Know to Improve Object Retrieval, CVPR2012
[3]: Multiple View Geometry in Computer Vision, Second Edition
[4]: Random Sample Consensus: a Paradigm for Model Fitting with Applications to Image Analysis and Automated Cartography, Comm of ACM, 1981
[5]: Automatic Panoramic Image Stitching Using Invariant Features, IJCV07
[6]: Construction of Panoramic Image Mosaics with Global and Local Alignment, IJCV00
[7]: A Compact Formula for the Derivative of a 3-D Rotation in Exponential Coordinates, arxiv preprint
- sift全景图拼接完整的项目(六)
- opencv 基于sift的多张图片全景图拼接
- 基于SIFT特征的全景图像拼接
- 基于SIFT特征的全景图像拼接
- 基于SIFT特征的全景图像拼接
- 基于SIFT特征的全景图像拼接
- 基于SIFT特征的全景图像拼接
- 基于SIFT特征的全景图像拼接
- 基于SIFT特征的全景图像拼接
- 基于SIFT特征的全景图像拼接
- 基于SIFT特征的全景图像拼接
- 基于SIFT特征的全景图像拼接
- 全景图像的拼接
- 利用opencv2.4.10+VS2012和RobHess的sift特征算法实现全景图像拼接
- opencv全景图拼接
- 360全景图拼接
- 关于全景图像的拼接
- 关于全景图像的拼接
- java PPT 转成PDF 中文乱码解决
- 搭建zookeeper 分布式集群
- 深度学习资料合集
- sscanf函数和正则表达式
- Standard Solar Spectra: MODTRAN ETR Spectra
- sift全景图拼接完整的项目(六)
- NUC123告别裸奔,使用Keil自带RTOS RTX的简单步骤
- BPM实例分享——日期自动计算
- Ubuntu安装git时出错,git-compat-util.h:280:25: fatal error: openssl/ssl.h: 没有那个文件或目录
- 电子词典的实现(一)
- 递归读取文件夹下所有文件
- python2与python3区别汇总
- iOS 代理
- redis面试题总结