我们从用户移动相机对冲印照片拍摄的一系列照片开始谈起。第一张照片——“基准帧”——定义所需的输出视点。随后用户按照指示再拍摄四帧照片。在额外拍摄的每一帧上,我们都检测到稀疏的特征点(我们计算 Harris 角点上的 ORB 特征),并利用它们来建立单应矩阵,将每个帧都映射到基准帧。
▲ 左侧:基准帧和每个其他帧之间检测到的特征匹配(左侧),以及依据估算的单应矩阵生成的翘曲帧(右侧)。
尽管这项技术可能看似简单明了,但存在一个局限性:单应矩阵只能对齐平坦图像。但冲印的照片通常并不完全平坦(正如上面显示的示例所示)。因此,我们采用光流法——一种基本计算机视觉运动表示法,用于建立两幅图像之间的逐像素映射——来纠正不平整问题。我们以单应矩阵对齐帧为基础计算“流场”来翘曲图像并进一步优化配准。在下例中,请注意在仅使用单应矩阵配准帧后,左侧照片的角部的轻微“移动”情况。右侧照片显示的是利用光流法优化配准后照片对齐得到优化的效果。
▲ 使用单应矩阵获得的翘曲帧(左侧)与采用光流法做进一步翘曲优化后的翘曲帧(右侧)之间的对比。
配准上的差异很细微,对最终结果的影响却很大。请注意微小的不重合在结果中呈现为重复图像结构的效果,以及进一步的光流优化对这些伪影的缓解效果。
▲ 采用光流法优化的眩光去除效果(右侧)与不采用光流法优化的眩光去除效果(左侧)之间的对比。在只使用单应矩阵的结果(左侧)中,请注意人物眼睛、鼻子和牙齿周围的伪影,以及织物上重复的茎和花瓣。
在这里,难点同样是让光流法这种天生的慢速算法能够在手机上非常快速地运行。我们没有按照传统方式计算每个像素处的光流(计算的流矢量数与输入像素数相等),而是用数量更少的控制点表示一个流场,并将图像中每个像素处的运动表示为控制点处运动的函数。具体地讲,我们将每个图像分成平铺而又不重叠的单元格,形成一个粗网格,并将单元格中像素的流动表示为包含它的单元格四角流动的双线性合并。
▲ 网格光流法的网格结构。p 点表示为包含它的单元格四个角点的双线性插值。
▲ 左侧:在其中一个帧上计算的流场图。右侧:流颜色编码:屏幕方向和大小分别以色调和饱和度表示。
这可以显著降低待解决问题的严重程度,因为需要计算的流矢量数现在与网格点数相等,而后者通常远小于像素数。这一过程在本质上类似于 Szeliski 和 Coughlan(1997 年)介绍的样条式图像配准。采用这一算法,我们得以在 Pixel 手机上将光流计算时间缩短大约 40 倍!
▲ 单应矩阵配准帧与叠加在(干净)基准帧上的流优化翘曲帧(使用以上流场)之间的翻动图,它显示了计算的流场如何通过将图像部分与基准帧中的相应部分“对齐”来改善配准。
最后,为了形成无眩光输出,对于已配准帧中的任何给定位置,我们都会检查像素值,然后使用软最小值算法来获得最暗的观测值。更具体地讲,我们通过为靠近(翘曲)图像边界的像素分配较小权重来计算已配准帧上最低亮度的预期值。我们之所以采用这一方法,而不是直接计算各帧的最小值,是因为各帧对应像素的亮度可能略有差异。因此,每像素最小值会因重叠图像边界处的密度骤变而产生明显的接缝。
▲ 已配准帧上的普通最小值(左侧)与软最小值(右侧)的对比。
该算法可支持各种扫描条件——哑光和光面冲印照片、相册内部或外部照片、杂志封面。
输入 2. 已配准 3. 无眩光
为获得最终效果,Google 相册团队开发了一种方法,这种方法可自动检测和裁剪照片区域,并将其校正为正面照。由于透视畸变的缘故,扫描的矩形照片通常在图像上呈现为一个四边形。该方法通过分析图像信号(例如颜色和边缘)计算出原始照片在扫描图像上的确切边界,然后应用几何变换对四边形区域进行校正,使其恢复原始矩形形状,从而生成高质量无眩光的数字版照片。
因此,总的说来,尽管后台的计算量相当大,但在您的手机上这些计算几乎瞬间即可完成!要试用 PhotoScan,请下载该应用的 Android 或 iOS 版。
了解更多细节,查看文内所有链接,请点击文末“阅读原文”。
点击「阅读原文」,查看文内链接