ARKit入坑指南--技术实现分析

ARKit简介

iOS11发布了ARKit之后,iPhone瞬间变成了最大的AR平台。一直以来对这块都比较感兴趣,最近简单做了些研究,下面介绍下ARKit基础的一些概念,算是当作入坑路径吧。
ARKit是一种为iOS构建增强现实(AR,augmented reality)App的框架,意在实现将虚拟内容精确且真实地浸入真实世界场景上。ARKit的核心是为一些基本的关键功能提供支持,包括运动跟踪、水平面检测,以及尺度和环境光预测。
有些人认为ARKit是一种SLAM实现,也有人认为是VIO。下面分别简单介绍下对ARKit的技术实现方式的不同理解。

1.Slam的概念

SLAM,全称叫做Simultaneous Localization and Mapping,中文叫做同时定位与建图。就是通过传感器获取环境的有限信息,比如视觉信息、深度信息、自身的加速度和角速度等来确定自己的相对或者绝对位置,并完成对于地图的构建。简单点可以说是一个传感器在不停的运动,还在实时的扫描着周围的地形。
与其说SLAM是一种技术,不如说是一种概念,SLAM可通过多种方法实现。

要实现SLAM,最基础就是传感器,目前传感器分为激光和VSLAM两大类。激光雷达由于精度高、速度快,能方便地实现SLAM功能而被研究得最多,主要用于机器人及无人车(机)领域,但缺点就是价格昂贵。
而VSLAM则主要用摄像头来实现,摄像头品种繁多,主要分为单目、双目(或多目)、RGBD。实现难度正序:单目视觉>双目视觉>RGBD。 单目视觉因为基于一个摄像头,在深度感知上存在问题,无法得到机器人的运动轨迹及地图的真实大小,但这也使得单目SLAM不受环境大小的影响,既可用于室内,又可用于室外。

目前,SLAM技术的实现途径主要包括VSLAM、Wifi-SLAM与Lidar SLAM。

VSLAM (视觉SLAM)

指在室内环境下,用摄像机、Kinect等深度相机来做导航和探索。其工作原理简单来说就是对机器人周边的环境进行光学处理,先用摄像头进行图像信息采集,将采集的信息进行压缩,然后将它反馈到一个由神经网络和统计学方法构成的学习子系统,再由学习子系统将采集到的图像信息和机器人的实际位置联系起来,完成机器人的自主导航定位功能。
但是,室内的VSLAM仍处于研究阶段,远未到实际应用的程度。一方面,计算量太大,对机器人系统的性能要求较高;另一方面,VSLAM生成的地图(多数是点云)还不能用来做机器人的路径规划,需要进一步探索和研究。

Wifi-SLAM

这项技术主要作用是室内定位,指利用智能手机中的多种传感设备进行定位,包括Wifi、GPS、陀螺仪、加速计和磁力计,并通过机器学**和模式识别等算法将获得的数据绘制出准确的室内地图。

该技术的提供商已于2013年被苹果公司收购,苹果公司是否已经把 Wifi-SLAM 的科技用到iPhone上,使所有 iPhone 用户相当于携带了一个绘图小机器人,这一切暂未可知。毋庸置疑的是,更精准的定位不仅有利于地图,它会让所有依赖地理位置的应用(LBS) 更加精准。

Lidar SLAM

指利用激光雷达作为传感器,获取地图数据,使机器人实现同步定位与地图构建。该技术是目前最稳定、最可靠、高性能的SLAM方式。就技术本身而言,经过多年验证,已相当成熟,但Lidar成本昂贵这一瓶颈问题亟待解决。
Google无人驾驶汽车正是采用该项技术,车顶安装的激光雷达来自美国Velodyne公司,售价高达7万美元以上。
这款激光雷达可以在高速旋转时向周围发射64束激光,激光碰到周围物体并返回,便可计算出车体与周边物体的距离。
计算机系统再根据这些数据描绘出精细的3D地形图,然后与高分辨率地图相结合,生成不同的数据模型供车载计算机系统使用。激光雷达占去了整车成本的一半,这可能也是 Google 无人车迟迟无法量产的原因之一。
对于 AR/VR 使用场景的室内空间定位,我们可以通过蓝牙,路由器等建立标准点,或者通过红外线进行室内扫描来进行判定。但是一旦将室内定位与 VR 联系起来,就无法通过其它设备进行辅助了。目前我们已经能通过 Oculus 和 HTC Vive 的摄像头和「base station」做到进行小范围内的室内定位,但在移动 VR 领域里,空间定位一直是难题,目前还没有任何一个消费者级移动 VR 设备能够做到空间移动。

2. VIO系统

另一种理解是,从技术角度说,ARKit是一种具备简单2D平面检测(Plane detection)能力的视觉惯性里程计(Visual Inertial Odometry,VIO)系统。VIO意味着可以通过软件实时追踪用户在空间中的位置(用户的6dof姿态),例如在屏幕每刷新一帧的过程中重新计算用户姿态,这种操作每秒钟大约进行30次或更高频率。这种计算工作会并行进行两次。用户姿态可通过视觉(摄像头)系统进行追踪,为此需要将现实世界中的点与相机传感器拍摄的每一帧画面上的一个像素进行匹配。此外还需要通过惯性系统(加速计和陀螺仪,统称为惯性测量装置[Inertial Measurement Unit],即IMU)追踪用户姿态。随后这些系统的输出结果会通过Kalman Filter合并,进而确定其中哪个系统能对用户的“实际”位置(也叫做地表实况[Ground Truth])提供最佳估测,并通过ARKit SDK发布位置更新。与汽车中统计行驶距离的里程表类似,VIO系统会追踪iPhone在6D空间中的移动距离,6D代表3D世界中的xyz移动(转换),外加俯仰(Pitch)/偏航(Yaw)/翻滚(Roll)的3D移动(旋转)。

AR_6dof

VIO最大的优势在于,IMU的读数每秒可更新大约1000次,其数值完全基于加速度(用户的移动)。以往主要使用航位推算(Dead Reckoning)技术测量设备在两个IMU读数之间的移动,但这种技术只能进行猜测,就比如我让你迈出一步,随后猜测你的一步有多长距离一样,此时只能用航位推算技术来估测距离。
惯性系统的误差会逐渐累积,因此两个IMU帧之间的时间间隔越长,或者惯性系统不通过视觉系统进行“重置”一直使用的时间越长,追踪结果与地表实况之间的误差就越大。视觉/光学测量的频率可与摄像头的帧率保持一致,通常为30fps,并且完全基于距离(两个帧之间的场景变化)。光学系统的误差通常会随着距离而累积(时间的影响反而比较小),因此移动的距离越长,误差就会越大。 好在两种系统固有的优势结合在一起可以相互弥补劣势。

视觉和惯性追踪系统基于截然不同的测量系统,相互之间不存在依赖性。这意味着就算摄像头被遮挡或只能看到光学特征极为有限的场景(例如白色墙壁),惯性系统依然可以在少数几帧的范围内继续测量。或者设备可能处于静止状态,此时视觉系统可以提供比惯性系统更稳定的姿态检测。Kalman过滤器始终会选择最佳质量的姿态,进而实现最稳定的追踪。

ARKit的第二个主要功能是平面检测。正是因为有了这个功能,我们才有了用于放置内容的“表面”,否则所有内容只能悬浮在空间里。平面是由光学系统检测到的特征计算而来的(也就是演示里看到的那些小点),算法通过取平均值,即可用任意三个点定义一个平面,如果将这个操作执行多次,即可估算出现实中的平面到底在哪里。另外,这些点通常也被称之为“点云(Point cloud)”,这个概念也经常会被人混淆。所有这些点结合在一起可以形成一个稀疏点云,进而可用于光学追踪。通过稀疏点云进行追踪需要的内存和CPU运算量都比较少,同时辅以惯性系统的支持,光学系统即可在只需要很少量追踪点的情况下有效运作。

而SLAM是一个很宽泛的术语,类似我们说的“多媒体”。追踪这个词本身也是一个宽泛的称呼,如果使用“量距(Odometry)”就具体多了,但在AR方面这两个词实际上意思比较接近。这一点可能会让人混淆。SLAM的实现方法有很多,追踪仅仅是整个SLAM系统所包含的组件之一。其实ARKit可以看作一种轻量级的简单SLAM系统。

“如何通过一个镜头获得3D场景?”,以及“如何确定计量尺度(例如量尺的演示)?”。此处的秘诀在于以真正足够好的方式消除IMU误差(例如提高航位推算的猜测精确度)。做到这一点后,就可以:

若要获得3D场景,只需从两个不同位置获得同一场景的两个视图,并对位置进行立体计算即可。我们的眼睛也是通过这种方式看到3D场景的,而这也是某些追踪系统需要使用双摄像头的原因。如果有两个摄像头,因为摄像头间距离已知,并且两帧画面是同时捕获的,此时计算工作将非常容易。如果只有一个摄像头,只需捕获一帧,移动少许位置,再捕获第二帧就行了。通过使用IMU航位推算,我们可以计算两帧画面移动的距离,随后照常进行立体计算(实际可以通过更多帧来计算,获得更精确的结果)。如果IMU足够精确,那么两帧之间哪怕为了保持手部固定产生的轻微肌肉活动导致的“移动”也可以顺利检测出来!这简直就是魔法。

为了确定计量尺度,系统也需要依赖IMU提供精确的航位推算。通过IMU提供的加速度和时间测量值,我们可以后向合并以计算速率,并再次合并回来以获得IMU帧之间的位移。计算过程并不难,难点在于消除IMU的误差以得到近乎完美的加速度测量值。任何微小的错误,如果每秒钟出现1000次,在移动手机的过程中持续数秒钟,最终都会累积造成30%甚至更高的尺度误差。Apple能将这个误差降低到个位数百分率,这真是让人佩服。

Tango、Hololens、Vuforia等产品又如何呢?

Tango其实是一个品牌,并不是某个具体的产品。其中包含了硬件参考设计(RGB、鱼眼、深度摄像头,以及某些CPU/GPU规格)和软件栈,可提供VIO(动作追踪)、Sparse Mapping(区域学习),以及Dense 3D重建(深度感知)等功能。

Hololens具备完全相同的软件栈,但还包含一些ASIC(被称之为Holographic Processing Unit,全息处理单元),借此分摊CPU/GPU的处理任务以降低能耗。
Vuforia几乎也是相同的,但不依赖特定的硬件。

上述三种技术使用了相同的VIO系统(Tango和ARKit甚至使用了同一套最初由FlyBy开发的代码!)。Hololens和Tango都没有使用深度摄像头进行追踪(但可能觉得为了解决某些边缘案例,他们正在着手这样做)。那么为何ARKit的表现会这么好?

答案在于,ARKit其实并不比Hololens好到哪里去(甚至可以说Hololens的追踪系统是市面上最棒的),但Hololens硬件的普及率太低了。微软本应将Hololens的追踪系统包含在Windows智能手机中,但可能他们是出于商业方面的考虑并未这样做(例如可能导致成本增高,需要花时间对手机传感器进行校准,设备销量太小,而微软提供类似ARKit的方案并不足以将开发者从iOS/Android平台策反过来)。

过去一年多的时间里,Google本来也可以很轻松地将Tango的VIO系统包含在出货量巨大的Android手机中,但他们也没有这样做。如果当时真这么做了,反而会让ARKit成为“跟风者”,而非“引领者”。可能是因为每家OEM厂商不想自己分别进行繁琐的传感器校准,进而导致每个OEM版本的Tango实际使用效果各异,而对于设备出货量足够大,值得这么做的少数OEM厂商(三星、华为等),Google也并不希望过于讨好他们。因而他们等于在告诉OEM厂商:“硬件参考设计是这样的,用不用随意”。随着Android智能手机硬件逐渐变得商品化,摄像头和传感器已成为不同厂商差异性最主要的来源之一,OEM厂商们怎么可能为Google做嫁衣!Google还强制要求必须使用深度摄像头,这会导致厂商的手机物料成本(以及耗电量)大幅增加,这也成了OEM厂商拒绝的另一个原因。但随着ARKit的发布,情况截然不同了……

使得ARKit如此出色的主要原因依然在于,Apple可以承担这样做的成本,将VIO算法与传感器紧密集成,并投入大量时间进行校准以消除姿态计算过程中的误差/不确定性。

好了,上面简单介绍了对ARKit技术实现方式的理解,不过看起来第二种更可信,之后我会继续分享一些ARKit的实践。

参考文档 
  1. https://medium.com/super-ventures-blog/why-is-arkit-better-than-the-alternatives-af8871889d6a
  2. https://developer.apple.com/documentation/arkit 官方API
  3. https://developer.apple.com/documentation/arkit/understanding_augmented_reality
坚持原创技术分享,您的支持将鼓励我继续创作!