iOS-初识ARKit

2017-06-29

初识ARKit

Apple在2017WWDC发布会上带来了全新的iOS11,其中最令人瞩目的是引入了ARKit,这是一个新框架,可以让开发者轻松创建无与伦比的iPhone和iPad增强实现体验。通过将虚拟场景与周围的环境融合,ARKit将应用程序超越屏幕,让它们以全新的方式与现实世界进行交互。

架构图

用一张图来展示ARKit框架在应用架构中所处在的位置和功能说明:
ARKit框架在应用架构中所处的位置

从上图可知,Apple提供的AR平台底层主要分为2部分:数据分析处理和渲染。
ARKit负责数据分析处理,生成AR体验必要的支撑数据,渲染部分Apple提供了3个框架来支持,它们分为两部分:
标准渲染视图:SceneKit和SpriteKit,前者提供3D渲染支持,后者提供2D渲染支持。
自定义渲染视图:如果觉得Apple提供的标准渲染视图不满足自己的需求,Apple提供了Metal自定义渲染视图框架,来支持自定义渲染视图。

再来看看ARKit的架构图:
ARKit框架图

从上图可知,ARKit框架底层主要功能为追踪,分为2块:摄像头画面实时捕捉视频帧;设备感应硬件检测到的动作数据。
ARKit将这2者的数据结合起来分析,生成最终结果,再配合渲染库将2D和3D元素内容实时的显示到用户设备实时的摄像画面中,能使用户体验到AR的错觉乐趣,这些2D或3D元素内容从画面中看上去就像是真实世界中的一部分。

架构图看完后,再看看ARKit数据处理的主要流程图:
ARKit数据处理流程图

从上图流程图中可知,ARKit的核心是ARSession,它管理着AVCaptureSession和CMMotionManager。
AVCaptureSession是AVFoundation的核心类,主要用于捕捉视频和音频,协调视频和音频的输入、输出流。
CMMotionManager是用于对设备运动识别的,它有2种采样方式:

PUSH:实时采集所需数据,采样频率高。
PULL:在有需要的时候,才去采集数据。
要运行一个Session,必须要传入一个ARSessionConfiguration配置,运行中的Session会连续地从AVCaptureSession中捕获实时的摄像画面,再结合CMMotionManager提供的运动数据,最终预测出设备的实际位置。

场景识别

Apple在WWDC大会上展示了ARKit强大的场景识别能力,视频中有两个让人印象特别深刻的地方:
1.演讲者使用一个iPhone手机演示将一个逼真的AR战地场景展示在现场桌面上,其中一个小人为了躲避飞机扔下的炮弹,从桌上跳了下去,刚开始以为这仅仅是WWDC现场演示时Demo故意给人错觉的一种演讲效果,但后来回看了下官方文档,确实有提及ARKit是可以捕捉到多个平面的,以及在后来的演示中有看到DEBUG工具展示多个平面网格。
2.另一个SpriteKit大会讲解视频(PS:在视频24分)时,视频中游戏演示的小人跳到了桌面上的平层,能够在真实世界的平层上来回走动,是不是很震惊!!!

从官方的PPT上看到ARKit在场景识别中有3项重要的技术,分别是:

  • 平面检测(Plane detection)
  • 碰撞测试(Hit-testing)
  • 亮度估量(Light estimation)

平面检测(Plane detection)

PPT中概括了4点:

  1. 能检测到相对于重力的水平面,即它能检测的出平面的高低落差层次。
  2. 可以运行多个帧,如果没理解错的话,应该就是可以同时分析检测出多个平面。
  3. 可以对齐置平面的表面上,即当你放置3D精灵视图时,能自动的将3D精灵视图平放到对应的平面上,使它看上去就是像现实中物体放在平面上一样。
  4. 进行平面合并。

上述可能不是很好理解,用一张图来概括:
ARKit数据处理流程图

开启平面检测很方便,代码如下:

1
2
3
4
5
6
7
8
9
10
// Enable plane detection on a session

// Create a new world tracking configuration
let configuration = ARWorldTrackingSessionConfiguration()

// Enable plane detection
configuration.planeDetection = .horizontal

// Change configuration on currently running session
mySession.run(configuration)

ARWorldTrackingSessionConfiguration类是ARSessionConfiguration类的子类。
翻看官方文档可知:
ARSessionConfiguration类提供3个自由度(DOF)追踪设备的运动:具体来说,三个旋转轴(滚动,俯视和偏航),它支持所有iOS设备上使用ARKit。
ARSessionConfiguration 3DOF

ARWorldTrackingSessionConfiguration类是AR体验增强类,对iOS设备要求比较高,需要CPU不低于A9,也就是目前市面上最低iPhone 6s,它提供6个自由度(DOF)追踪设备的运动,比其父类多了3个自由度:三个坐标系(在x、y、z轴上运动)。
ARWorldTrackingSessionConfiguration 6DOF

碰撞测试(Hit-testing)

PPT中概括了4点:

  1. 使用真实世界的相交射线。
  2. 使用场景信息。
  3. 结果按照远近距离排序。
  4. 有4种碰撞测试类型来帮助判断碰撞测试结果。

Hit-testing会去检测分析出相机图像中的水平面,然后生成其位置和大小的数据。可以把它想象为,摄像头发射一个射线出去,射线碰撞检测到一个点,那么收集到足够多的点就能分析出平面,最终生成返回数据。

如图所示:
Hit-testing

基于Hit-testing建立一个锚点,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Adding an ARAnchor based on hit-test
let point = CGPoint(x:0.5, y:0.5) // Image center

// Perform hit-test on frame
let results = frame.hitTest(point, types:[.existingPlane, .estimatedHorizontalPlane])

// Use the first result
if let closestResult = results.first {

// Create an Anchor for it
let anchor = ARAnchor(transform: closestResult.worldTansform)

// Add it to the session
session.add(anchor: anchor)
}

ARSKView、ARSCNView、ARFrame类中提供了hitTest方法,用于碰撞测试检测分析出平面,方法返回一组ARHitTestResult对象,该方法传入2个参数,第一个参数为CGPoint点,第二个参数为检测碰撞结果的类型,有4种:

  1. ARHitTestResult.ResultType.featurePoint,根据距离最近的特征点检测出来的连续表面。
  2. ARHitTestResult.ResultType.estimatedHorizontalPlane,非精准方式计算出来与重力垂直的平面。
  3. ARHitTestResult.ResultType.existingPlane,已经检测出来的平面,检测时忽略平面本身大小,把它看做一个无穷大的平面。
  4. ARHitTestResult.ResultType.existingPlaneUsingExtent,已经检测出来的平面,检测时考虑平面本身的大小。
    这4种类型可以用|来同时传入。

高光估算(Light Estimation)

在AR增强视觉体验中,如果虚拟内容的高光与环境不符,那还是挺容易看得出这就是一个虚拟物体的。
ARKit提供来一个检测视频图像环境光照强度的功能,主要是为了让3D模型的光照与环境的光照强度保持一致。
ARKit默认开启了这项检测,且流明度默认值为1000。

用图来展示ARKit强大的魅力:
Light Estimation 1
Light Estimation 2

Demo

官方3D飞机模型AR体验

在Xcode9 beta1中,官方在模板工程中提供了2个示例:SceneKit和SpriteKit,前者3D,后者2D。
在Xcode9 beta2中,官方在模板工程中又新增了1个Metal的示例,可以使用Metal技术来自定义渲染视图,该种实现方式比SceneKit和SpriteKit这两种方式复杂的多,具体细节请参阅官方文档

你可以新建一个工程,选择AR模版,在Content Technology中选择使用SceneKit或SpriteKit或Metal,这里选用SceneKit。
Demo 1
Demo 1

模板工程很简单,如下图所示:
Demo 1

art.scnassets为AR素材资源目录,官方提供了一个飞机建模:
Demo 1

ViewController.swift中的代码如下(删去了暂时无用的空代理回调方法):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import UIKit
import SceneKit
import ARKit

class ViewController: UIViewController, ARSCNViewDelegate {

@IBOutlet var sceneView: ARSCNView!

override func viewDidLoad() {
super.viewDidLoad()

// Set the view's delegate
sceneView.delegate = self

// Show statistics such as fps and timing information
sceneView.showsStatistics = true

// Create a new scene
let scene = SCNScene(named: "art.scnassets/ship.scn")!

// Set the scene to the view
sceneView.scene = scene
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)

// Create a session configuration
let configuration = ARWorldTrackingSessionConfiguration()

// Run the view's session
sceneView.session.run(configuration)
}

override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)

// Pause the view's session
sceneView.session.pause()
}
}

代码解读:

  1. 渲染模块使用ARSCNView视图,它支持3D模型渲染。
  2. 在viewDidLoad中设置sceneView的代理,以及现实FPS状态,然后加载飞机3D模型,并将其设置为sceneView的scene属性。
  3. view即将展现时,配置一个ARWorldTrackingSessionConfiguration对象(支持6DOF),将使用该配置来运行Session。
  4. view即将消失时,暂停Session的运行。

当你使用A9+设备运行该工程时,会在摄像画面的水平正前方出现一架飞机3D模型,可以像正常拍摄一个物体一样360度查看它,如下图所示:
ARKit-SceneKit-Demo

简简单单的几行代码便将一个飞机3D模型实时渲染到了实时的视频画面中,还支持6轴运动,不得不说ARKit将AR门槛降低了非常多,使得开发者很轻松地创建出AR体验APP。

官方提供了一个较为复杂的ARDemo,可以放置一些家具的,画面很逼真,并提供了DEBUG的工具来帮助开发者理解ARKit相关特性,如图所示:
ARKit-SceneKit-Demo
ARKit-SceneKit-Demo

总结

ARKit支持所有的设备,在CPU A9以下的设别,提供基础的3DOF(滚动,俯视和偏航)支持,在CPU A9及以上,提供6DOF(滚动,俯视和偏航,以及三个坐标系(在x、y、z轴上运动))支持。

ARKit提供了强大的数据分析能力,将实时画面帧与设备运行数据结合,为开发者创建无比惊艳的AR体验APP提供了强大的数据支撑。要开发AR体验APP,需要开发者具备以下知识:

  1. 线性代数-矩阵计算,推荐一个视频:线性代数的本质 - 系列合集
  2. 熟悉ARKit框架。
  3. 熟悉SceneKit、SpriteKit,这是Apple提供的标准渲染视图,内部处理了绝大部分的渲染处理,能帮助开发者降低渲染AR所具备的知识。
  4. 如果要自定义渲染,可以使用Apple提供的Metal框架,今年会发布Metal2,性能进一步提升。

可以预测到iOS11正式发布时,将会有众多应用会借势ARKit上首推,特别是游戏类APP,譬如以前大火的植物大战僵尸、水果忍者、宠物精灵、飞行游戏、养成类游戏等等,一般应用中大多数是活动场景,好比:AR抢红包、寻宝、展示等等。

目前正处于Beta阶段的AR体验还有待改进,真机体验的时候,还是能很明显的感受到虚拟物品会漂移或不自然的抖动,慢慢静待Apple的修正吧。