查看原文
其他

最牛全景相机——Facebook Surround360原理解析

sixgod 计算机视觉life 2019-06-23

阅读过前两篇文章《5分钟了解全景相机》《全景相机哪家强?》的亲们应该对全景相机有了个粗浅的认识。前面文章中我提到过,全景拼接算法是整个全景相机研发的核心技术,这篇就说说我认为目前在全景拼接算法方面最牛(不服气的看后面解释)的一款全景相机——Facebook surround 360的算法原理。


Surround360是Facebook一直在研发的一款3D 360°全景视频拍摄系统,在2016年7月Facebook对该系统的软硬件进行了开源,真是喜大普奔啊~


17个相机组成的Surround360


Surround360开源项目包含了从17个相机阵列的硬件设计到图像拼接的软件算法,它在一个系统里实现了3D 360°的端到端的从视频拍摄到视频处理的整个过程。


surround360牛在哪里?


我前面说surround360牛,可能有些人不服气。下面给出我的解释。


虽然目前全景相机种类非常多,但几乎都是没有深度信息的360°全景,相机数目不会太多,这些全景图是由多个二维的图片拼起来的,看起来比较扁平,没有真实世界的立体感。为了表述清楚,我称之为单目全景。这种情况下我们人的两只眼睛看到的是一模一样的全景图像。


如果想要获得更有真实感的3D-360全景图像就没那么容易了,因为相对于单目全景图像,3D-360全景图像需要深度信息(通过视差得到)。

Surround360硬件设计


Surround360用两个相机(相当于左右眼)拍摄同一位置来获得视差,这就要求左右眼要有足够多的重叠部分来计算视差,因此需要使用较多相机(一般10~20个)对周围360°内的每个方向都进行立体拍摄,并且所有相机必须严格地全局同步。最后,需要融合(拼接)所有的相机拍摄的图片成为一张无缝全景图,而且必须进行两次操作:第一次产生左眼全景图、第二次产生右眼全景图。我称之为双目全景。这种情况下用VR眼镜看的时候,两只眼睛看到的是两个不同的具有视差的全景图,在虚拟世界里就和真实世界一样具有层次感。


而要想产生像surround360这样的双目全景图像,需要克服如下困难:


  • 涉及的数据量非常巨大。由于Surround360设备有17个相机之多,而且为了保证最好的图像质量,使用的是原始的未压缩的图像。如果帧率是30FPS的话,每分钟输出的视频将有120GB的数据。这绝对是一个巨大的挑战。


  • 要求非常高的精度,留给出错的空间极小。对于单目的2D的360视频内容来说,一些小的拼接错误是可以容忍的,但是对于双目立体3D360视频来说,必须保证极高的精度达到绝对近乎完美的效果,否则会引起观看者产生眩晕等不适感。


  • 要求较高的处理速度。为了VR视频的实用性要求,需要处理速度尽可能地快,但这常常和高质量地输出效果相矛盾。


传统的单目拼接算法不存在上述问题,它的应用相对简单,只要把相邻图像边缘拼接好就行了。但是双目立体拼接算法面临着很大的挑战,计算的立体视差不准的话,很容易引起用户的不适感,并且破坏了3D的沉浸感。


曾经走过的坑

Facebook在开发其3D360相机的原型机时也走了不少弯路,尝试了很多不同的相机阵列和算法的组合方式。 


其中一个尝试是4对相机分别位于立方体的四个面,每对相机之间距离和人眼间距差不多的距离。然后利用alpha混合(一种平滑的图像混合技术)的方法将左右眼拼接成为一个无缝的全景图。从当时的实验结果来看,每个面的两对相机之间的立体效果很好,但是在立方体的四个拐角处没有立体效果。该方法的另外一个问题就是该设备旋转拍摄时,相机对必须指向不同的方向使得在一个恒定的距离观察物体,这会引起视疲劳。


有很多比alpha混合及拼接算法更加复杂的方法来获得立体全景。其中一种方法是用一个相机绕固定的轴旋转一周拍摄一系列连续的图片,这种方法和基本的拼接方法相比,可以产生合适的朝向以及具有一致深度的全景图。但是无法用于有运动物体的场景。


Surround360在此基础上更进了一步,它使用光流法通过一个圆盘相机阵列的 “视图插值”,来模拟一个旋转的相机,该方法对于场景中有运动物体的情况也适用。但是光流法在计算机视觉领域是一个非常有挑战性的问题,至今都没有非常完美的光流解决方案。因此尽管surround360的效果在大部分情况下可以接受,但是在某些情况(场景中有透明玻璃、细长的物体、曝光差异较大等)下仍然会有比较明显的问题。


全景相机阵列设计

相机阵列可以简单的理解为光线采集设备,采集到的光线与成像平面的交点即像素点。


通常的二维全景要求采集到的所有光线汇于中心视点,而双目立体全景要求两只眼睛分别对应两个不同的视点位置,当头部旋转360°时,两只眼睛转过的轨迹即一个以瞳距为直径的圆(viewing circle),双目立体全景要求采集到的所有光线相切于此圆。左右眼采集到的光线分别与成像面相交形成左眼全景图和右眼全景图。

中间的圆就是viewing circle


另外,相机的数目N、圆盘的半径R、镜头的视场角FOV也不是随便设计的。它们之间要满足如下的约束关系才能产生较好的3D效果:


i >= R * sin(FOV/2 - 360/N) 


其中N 是指侧面相机的数目,视场角FOV也是针对侧面相机镜头的水平视场角。 i = IPD/2。其中IPD是内瞳距。要产生正常的立体视觉,IPD要至少大于6.4cm(普通人眼的间距),因此i >= 3.2cm。

 
以Surround360为例,N=14, R=15cm,侧面相机水平视场角为90°,经过桶型畸变校正后水平视场角变为77°,带入公式可得i=3.32cm > 3.2cm,所以满足3D设计需求。


双目全景拼接算法流程

Surround360全景拼接算法比较复杂,需要经过一系列的图像处理流程。下面细细道来。


RAW图像预处理

首先,所有相机输出RAW Bayer格式的图像。RAW数据经过一系列的图像预处理转换为标准的RGB图像。预处理部分主要包括:摄像头之间的颜色校准、暗角消除、Gamma变化、色调、锐化等。

颜色校准


千万别小看这一步,这一步虽然麻烦了一些,但是对后续拼接算法非常重要。因为通过预处理,surround360能够保证每次待合成的17个相机的17张图像的亮度、色彩分布、色调、色温几乎没有差异。这一步surround360走的非常稳,虽然在此花费了很多时间,从最终结果来看,前期预处理基础打的好,后续拼接会少踩好多雷。


投影展开

下一步就是读取预处理后的图像数据并对每张图做正方形投影展开。


正方形投影是一种在VR领域图像/视频编码中常用的技术。该投影是一种把球面展开到矩形结构图的的方法,就像世界地图一样。正方形图像中的每一列都对应球面的一条经线,每一行都对应球面的一条纬线。 

世界地图的正方形投影展开


Surround360的目标是为左右眼产生正方形全景图,这样每一列像素对应于用户头部的一个具体的朝向。这一列像素就是用户左右眼在双目全景图中实际看到的一列图像。对于给定的头部朝向,有两个相距固定距离(瞳距)的绕着头部中心旋转的虚拟的眼睛。


现在想象上述发生在2D俯视图下的相机内,头部的中心就是相机中心。通过每列像素构建的光线从一个虚拟眼出发,最后从相机圆盘出去。如果该光线正好穿过一个真实的相机,那么从相机图像中的像素我们就能知道它的颜色。但是通常光线穿出相机圆盘时不一定正好穿过真实的相机。这种情况下,我们在两个真实的相机之间利用相邻的相机插值出一个虚拟的相机,然后从插值的视角的像素中得到光线的颜色。



这些正方形投影的矩形结构可以覆盖整个球体。每张图只占整个球体中的一小部分,如下图。



畸变矫正

把原始输入图片投影为正方形时,需要对镜头引起的图像畸变做校正。Surround360使用张正友标定法(如下图),对标定板拍摄多张图片来做标定,可以求得内参和畸变系数用于做畸变校正。



水平矫正

另外,surround360也对相机、镜头、支架系统的旋转、平移错位进行了校正。这些错位会引起垂直方向的视差(会引起重影,破坏3D效果)。为解决该问题,Surround360首先对相邻相机拍摄的图片之间特征点匹配,然后联合起来全局最小化所有侧面相机的垂直视差(同一个物体在左右眼图像中垂直方向的距离差),对每个相机计算出一个透视变换矩阵。

相邻相机特征点匹配对



视差计算

在此提一下视差的概念:距离两个相机无穷远处的同一个物体视差为零,而在有限距离内,两个相机的投影图中同一个物体所处位置的差异就产生了视差。这有益于光流的计算,因为光流的初始假设就是0,正好对应于无穷远处的物体。


如下图左就是相邻相机之间的重叠区域,右图是光流结果。surround360通过计算它们之间的光流来近似模拟视差。


相邻相机重叠区域图像的光流结果


根据左右相机重叠区域的光流计算结果就可以近似得到视差,如下图所示:


用光流来模拟左右眼的视差效果


上下相机的处理

上面介绍了如何得到侧面相机的立体全景图。Google jump就是做到这一步。但是顶部和底部仍会有一定的盲区,像其他几乎所有的全景相机一样,Google jump直接进行了模糊化操作。而Surround360利用顶部1个和底部2个大视场角的鱼眼相机在此做了真正的360°x 180°全景。


Surround360侧面相机的水平和垂直视场角约为90°(经过桶型畸变校正后视场角降低为77°)。所以侧面相机在垂直方向总共180°的范围内在靠近地平线方向占据77°左右的垂直区域,剩下的空缺可以由顶上和底下的180°单目鱼眼相机来填补。实际上,在正对的顶部和底部只能采用单目相机,因为无法对所有头部朝向进行立体校正使之成为一个左/右正方形图像对,所以surround360的立体效果从水平线到两极是逐渐变小的。使用不同的镜头,可以增加水平方向的立体范围,但是这是和图像分辨率之间的折中。


为了无缝拼接顶部的相机拍摄的图片和侧面相机拍摄的图片,并且产生舒适的立体效果,surround360用光流来匹配顶部图片和侧面生成的全景图,通过alpha混合(具有去重影效果)合成最终的图像。


底部有两个相机,所以可以用算法自动从图像中去掉支架。底部的主相机位于圆盘正中心,和顶部的相机完全对称。底部另外一个辅助相机在支架的另一面,所以主相机中被支架遮挡的部分的图像通过辅相机可以看到,反过来也是。


Surround360在底部相机的两张图里利用支架的模板图像,用光流把第2张图恢复为第一张图,然后融合两张图。  


底部两个相机中支架的模板


如下图,两张底部相机的图融合成为一张图,去掉了支架。然后像顶部相机那样,把底部融合出来的一张图拼接到侧面相机生成的全景图里。


两个底部相机融合去掉支架


至此,就得到了真正的去掉支架的360°x180°的双目立体全景图


总结

Surround360双目立体全景拼接算法比较复杂,但是生成的效果具备较高的图像质量、精确的深度、舒适的立体视觉。而且融入顶面和底面相机去除了相机支架,做到了真正的无死角,可以真正提供360°x 180°范围的全景沉浸感。


图像质量方面,Surround360在拼接算法流程中的每一步骤都尽可能地保持较高的图像质量,并且进行了速度优化,目的就是为了在现有的硬件设备上产生和现实世界最精确的逼近。


速度优化方面,为了充分利用多核CPU,上述过程在多线程里进行。每个步骤的处理流程都根据它和其他步骤之间的相互依赖关系进行规划,使得可以充分利用所有的GPU资源。


不得不说Surround360的开发团队真的很棒,该系统的开源代码在github上仍然不定期更新,开源的软硬件给该领域内广大的开发者提供了一个极好的学习机会。



相关文章

5分钟了解全景相机

全景相机哪家强?


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存