这篇文章翻译自Basics of AR: Anchors, Keypoints & Feature Detection
开发具有增强现实 (Augmented Reality) 功能的 APP 需要开发者掌握一些关于图像处理的算法的背景知识。其中最基础的概念之一是锚点 (Anchors)。锚点的概念又依赖于从现实世界中检测到的关键点 (Keypoints) 及其描述符。
1 将虚拟物体锚定到现实世界
AR 开发的 API 隐藏了海量的复杂性细节。作为一个开发者,你所要做的工作只需要时简单地将虚拟物体锚定到现实世界。这个操作确保了虚拟物体的全息影像能够保持到你放置的物理位置上。
即便是系统随着时间的推进学习到了关于现实世界的更多知识,虚拟的物体仍然可以保持位置不变。例如,你将一个虚拟物体放置到距离你 2 米的墙上面。然后你逐渐走向这面墙。这个过程中,传感器可以进行更加精确的测量,系统会认识到你的初始位置距离墙的距离实际上可能是 2.1 米。AR 引擎需要能够在 3D 的物体位置上反应这些新的知识。
在传统的单一世界坐标体系中,每个物体会有一个固定的 x, y, z 坐标。锚点系统则取代了这种附属到 3D 物体上的显式的坐标、旋转变换量。系统感知到的物理世界相比于静态的坐标体系具有更高的优先级。
这个 Section 中作者主要想说明坐标系统和锚点系统之间的区别。在 AR 应用中,坐标系本身是变化的,因此基于坐标系定义的坐标体系是不可靠的。这是引入锚点体系的原因。锚点的定位是相对于环境的,而非坐标的。以上文的例子为例,在开始系统判断墙面的距离是 2 米,随后修正为 2.1 米。如果用坐标体系,那么在墙面位置修正之后,之前放置的物体就会脱离墙面。而如果使用锚点系统,锚点的定位是相对于墙面这个现实物体的,那么之后的坐标修正不会影响锚点和墙面的相对位置关系。
2 锚点时如何进行锚定的
那么锚点是如何实现将物体固定到一个现实世界中的位置的呢?
Google ARCore 的文档中显示,锚点类是基于一个名为 trackable
的类型的 -- 即检测出来的特征点和平面。由于平面其实是一组同平面的特征点,最后本质上还是建立在识别的特征点之上。
下面这段动图显示了由 Google ARCore 的检测出来的特征点。
3 计算机视觉中的特征点
什么是特征点呢?简而言之,特征点是图像中的一些具有特色的点,例如角落、斑点、T形连接处等是常见的特征点的候选项。不过仅仅这些信息还不足区分不同的特征点,或者确保在同样的场景下总能可靠地发现同样的特征点。因此,特征点的邻近区域也被分析,并且存储为特征点的描述符。
好的特征点的最重要的特征是「可靠性」(Reliability)。算法必须要保证在不同的观察条件下下能够发现同样的特征点。在使用 AR 的过程中,这些不断变化的观察条件包括:
- 摄像头角度
- 旋转
- 缩放
- 光照
- 由于运动或者变焦导致的模糊
- 图像噪声
4 寻找可靠的特征点
AR 框架如何发现特征点呢?微软的 HololLens 运行时拥有非长多的传感器数据,特别是基于反射结构红外光 (reflected structured infrared light) 的深度信息尤其宝贵。类似 Google 的 ARCore 和苹果的 ARKit 的移动 AR 平台就只能依赖于 2D 彩色摄像头的数据。
寻找独特的特征点长期以来都是一个研究的热点领域。其中最有影响力的是 SIFT (Scale Invariant Feature Transform) 算法。这个算法在 2004 年由 David G. Lowe 研究并发表。另一个「传统」的方法为 SURF (Speeded up robust features),有 H.Bay 等人提出。这些方法现在都得到了使用。不过这两个方法都是专利方法,而且运行到实时的移动平台时速度比较缓慢。
目前尚不清楚具体而言微软的混合现实 (Mixed Reality)、ARCore 和 ARKit 在底层到底使用了什么样的特征点算法,不过现实中还是存在一些鲁棒的、未被专利保护的算法。
一个很好的候选项是有 Leutenegger 等人提出的 BRISK (Binary Robust Invariant Scalable Keypoints) 算法。这个算法的速度和效率足以作为 SLAM (Simultaneouly locaiton and mapping) 应用的基础。
5 如何探测并存储特征?使用 Keypoints
特征检测是一个多步骤过程。具体的组成步骤在不同的算法中不同,这里给出一个简单的、典型的算法流程。
5.1 关键点检测
这类关键点检测的例子可以是检测画面中有别于邻居像素的拐角。
为了让特征点与缩放无关,且能够降低对噪声影响,通常算法会模糊 (Blur) 输入图像。引入图像的不同缩放程度的版本改善算法对于缩放比例的独立性。这个现象的一个解释是,一般来说将一棵树识别为一个整体,tracking 的效果要好于识别出一段一段的木头。SIFT 和 SURF 算法使用了这个方法。
不过,图像模糊的计算成本是比较高的。对于实时应用场景。其他的算法,如 BRISK 可以提供更好的整体性能。这些算法通常依赖于变种的 FAST 算法 (Rosten 和 Rummond 等人提出)。
FAST 算法分析每个像素 \(p\) 的周围的圆型区域。周围像素的亮度是比 \(p\) 高还是低(达到一定的阈值)?如果特定数量的连续像素达到这个标准,那么算法就发现了一个拐点。下面的图中给出了一个像素分析的例子。图中的像素 7 - 10 比 \(p\) 要暗,其他的像素则要更亮。
在 BRISK 算法中,在 16 像素组成的圆圈中,至少要有 9 个连续像素显著的更亮或者更暗才能将像素点认为是拐点。另外,BRISK 算法也是用了缩小尺寸的图像 (down-sized images (scale-space pyramid)) 来取得更好的针对缩放程度的独立性 -- 甚至到到次像素的精度。
5.2 关键点描述
所有检测到的关键点中,每个都应该成为一个唯一的指纹。在令一个不同的图像中(不同角度),算法也应该能够发现同样的特征点。可能是不同的拍摄角度,光照条件等。即便在这些要素发生变化的情况下,特征点的检测也要保持可靠。
BRISK 描述符是一个 512 比特的二进制字符串。本质上这个字符串是关键点同周围的点的是像素的亮度对比结果。
如下图所示,蓝色点代表了采样圆圈的中心点。红色圆圈则代表了采样区域,这些采样区域进行了高斯平滑以避免锯齿效应。
基于这些采样点,可以计算出亮度对比结果 -- 取决于采样是更亮还是更暗一些,计算出 0 或者 1。
另外,BRISK 通过计算特征方向来确保旋转无关性。这取决于两个较远的采样之间的最大梯度方向,其意思是从那个方向到那个方向会产生最大的亮度衰减。
6 代码尝试
作者这里用 OpenCV 尝试了一下 BRISK 算法。由于我关注的一些原理性质的东西,所以这个部分我并不太关注。感兴趣的读者可以自己去看看原文对应章节。
7 总结
在这篇文章中,我们讨论了 AR 锚点技术中最重要的背景技术之一。使用这些技术,你的 APP 可以在现实空间中建立锚点,并将虚拟的物体固定到这些锚点上。
例如,将很多虚拟的图片放置到墙面上通常会导致很糟糕的 AR 体验 -- 在一个平坦的表面比较难以获得较多的关键点。此时追踪现实世界就容易失真,而虚拟物体的全息影像也无法固定到现实世界的一个固定位置。
反之,如果你的 APP 主要是将物体放置到靠近地板或者桌面的角落位置,那么 APP 工作起来会更准确一些。这些设计可以确保算法总是可以在锚点周围发现足够多的关键点。
另外,阅读微软和 Google 的关于使用空间锚点的说明,其中的重要信息有下面两点:
- 如果你不需要一个锚点了,尽快释放掉它:每个空间锚点都需要耗费 CPU 时间。AR 框架会优先处理锚点区域以获得稳定的追踪性能。
- 让物体靠近锚点:不要使用变换矩阵让虚拟物体离开锚点的位置太远。微软推荐的是最多 3 米。考虑到手机平台的精度更低,那么手机平台的 AR 应用中对应的阈值应该更低。