图像和视频缝合 在全景图生成、360°全景相机以及VR全景领域有非常多的应用,常用的图像缝合工具有Microsoft的ICE、PTGui、开源软件Hugin等,基于视频的拼接可以参考VideoStitch、StitcHD (github.com/lukeyeager/StitcHD)以及stitching_with_cuda。
图像缝合的算法步骤可以描述为:
Step1. 定义映射模型,常用的包括:球面、柱面、平面,其中球面映射应用最为广泛;
Step2. 根据输入图像,提取特征点,对特征进行匹配,得到输入图像之间的映射关系T;
Step3. 根据映射关系T进行图像的Warp变换,对齐图像;
Step4. 包括利用颜色调整来消除图像间的色差,和采用图像融合来消除拼缝。
算法流程图描述为:
我们对算法每一步进行展开,并在此基础上进行讨论。
• 映射模型
映射模型可以看作是用于图像映射的载体,相当于二维图像映射到三维空间的一种变换,如下图所示:
其对应缝合效果如下图所示:
选择合适的映射模型非常重要,需要与你的图像采集场景以及应用方式相匹配,一般对于水平拼接,采用柱面映射描述性最佳,而对于360°全景,球面映射或者立方体(多面体)映射的效果更好。
上图中我们采用的即是三张平行拍摄图片,由于垂直方向张角较小,因此球面模型与柱面模型的效果实际差异不大,大家可以用OpenCV的Stitching模块自己感觉一下。
• 特征点提取与匹配
对于自动拼接来讲,特征点提取是必不可少的一步操作,结合前面所提到的特征,选取常用的特征描述子(可以选择SIFT、Surf、Orb等),大部分图像缝合不涉及尺度问题,从速度考虑ORB通常是比较好的选择。
特征匹配用来计算图像之间的映射关系(采用RANSAC或者概率模型),得到每个匹配图像对之间的单应矩阵,结合上一步的映射模型,我们可以得到最终的图像变换序列 T1T2T3…。
在计算映射变换之后,实际上我们就得到了图像之间的全景变换关系,或者叫做相机变换参数(参照OpenCV里的detail::CameraParams),对于视频拼接来讲,这个变换参数通常是不变的。
另外也可以利用手动的方式进行调整,只要确保图像之间的对齐即可,因此特征的提取与匹配并不是必选项。
• 图像Warp变换
采用矩阵的形式描述为:
矩阵H 被称为投影变换矩阵。对上式进行分解化简,即是通常所谓的单应性变换:
图像Warp变换是一项耗时的操作,相当于对里面每一个像素点进行一次变换,像素之间的操作相互独立,因此操作通常放在GPU上来并行处理,对于CUDA来讲,透视变换相当于将输入图像的索引坐标值映射到纹理坐标。
• 色差调整
关于色差调整文献较多,可以从自动白平衡方向入手,也可以手动调整色温,其基本思路都是通过统计每幅图的颜色区间分布,对于不同的颜色进行调整到与参考颜色一致的空间内。
比较常用的是Reinhard方法,将图像 I 转换到lab 空间(降低三原色之间的相关性),通过图像的统计分析,利用目标图像 I' 的 均值 及 标准差 进行线性调整,公式描述为:
线性变换(方差作为斜率)能够保证源图像能够与目标图像在 lab 颜色空间具有近似相同的均值和方差。通常我们可以选定一副图像作为调整基准,当然也可以计算需要变换的所有图像的均值作为一个目标值,需要由使用者来决定。
• 图像融合
融合目的在于拼缝消除,这里考虑常用的三种方式,Alpha平均、羽化融合和Multi-Band融合方法。从效果上来讲,Multi-Band能够达到比较好的融合效果,当然效率也低,这里我们采用的方法称为Laplacian(拉普拉斯)金字塔。可以理解为通过对相邻两层的高斯金字塔进行差分,将原图分解(Reduce)成不同尺度(频率)的子图,对每一个之图(对应不同频带)进行加权平均,得到每一层的融合结果,最后进行金字塔的反向重建(Expand),得到最终融合效果。
关于图像融合,可以搜到很多现成的代码,这里不再过多描述。对于融合的关键在于选择用于融合的子图像区域部分,要注意图像过大导致的效率问题,也要避免图像较小带来的信息缺失。
OpenCV的代码是视频缝合比较好的入门材料,大家可以前期参考,当然后面可以根据自己的侧重对代码进行效率或者效果上的优化,比如打造一个轻量级的Stitching库、采用CUDA或者OpenCL进行高效的实现等等。
OpenCV的流程框架图如下:
OpenCV代码实现及注释: