理解苹果ARKit 1和2

DEMO
包含功能平面检测、环境纹理、物体操作(添加、选中、拖动、缩放、旋转)、图像识别、环境音效

什么是ARKit

AR(Augmented Reality)运用计算机技术,将虚拟的信息应用到真实世界,被人类感官所感知。给人一种虚拟物体存在于现实世界的错觉。而ARKit整合运动传感器数据,相机数据,相机捕捉到的图像分析数据,用于建立现实场景和建模AR内容的虚拟场景的对应关系,为这种错觉提供数据基础,简化构建AR体验。

构建AR体验的三驾马车

Tracking

通过Tracking,我们可以:

  • 获得相机在现实世界中的位置。
  • 将相机图像和运动数据整合,形成AR视图。
  • 追踪特征点,构建AR场景。追踪人脸,图像,物体等。

AR追踪的单位为m。因此在制作AR模型时,需要按照物体实际在现实世界中的屋里比例来制作。这样物体不至于过大或过小,呈现会更真实。
在iOS开发中,Tracking通过AVFoundation来获取场景图像,CoreMotion来获取运动数据。结合两者形成AR视图。

Tracking质量

要保证高质量的追踪Tracking数据,需要高质量的特征点。需要满足以下条件:

  • 持续的相机数据和传感器数据
  • 环境纹理要足够明显。需要处于一个光线充足并且纹理明显的环境当中,这样ARKit更容易提取特征点,建立空间对应关系。
  • 静态场景。动态场景会导致视觉数据和运动数据不相符,影响追踪质量。

Scene Understanding

  • 平面检测
  • hit-testing
  • 光线估计

Rendering

对iOS开发者来说,最便捷的渲染方式是SceneKit。ARKit负责收集数据,渲染负责展示AR模型。
支持的渲染方式如下:

  • SceneKit
  • SpringKit
  • OpenGL/Metal

下面这幅图展示了ARKit在一个AR应用中的角色。

image

三步创建你自己的AR体验

创建AR体验只需要三步:


image

ARSession通过ARSessionConfiguration开启,由Delegate回调ARFrame信息数据进行展示。

相关代码如下:

初始化Configuration

// Start the view's AR session with a configuration that uses the rear camera,
// device position and orientation tracking, and plane detection.
let configuration = ARWorldTrackingConfiguration()
configuration.planeDetection = [.horizontal, .vertical]

运行ARSession

sceneView.session.run(configuration)

获取委托数据。ps:如果使用SceneKit来渲染,则不用关心Session回调,只需要关心SceneKitNode相关操作和回调。

// Access the latest frame
func session(_: ARSession, didUpdate: ARFrame)

接下来我们就来了解一下ARKit中几个重要的类。

ARSession

AR体验通过ARSession来开启。它管理着Tracking时所有的进程,是管理设备相机和动作处理的共享对象。ARSession整合运动传感器数据,相机数据,相机捕捉到的图像分析数据,用于建立设备所在场景和建模AR内容的虚拟场景的对应关系。
每一个AR 体验都需要一个ARSession对象。如果使用ARSCNView或者ARSKView来渲染展示部分,View对象包含一个ARSession实例。如果使用你自己的渲染器,你需要实例化并维护一个ARSession对象。

ARSession对象需要通过ARConfiguration子类来运行,这个配置决定ARKit如何追踪设备相对于现实场景中的位置及动作。

/**
     Runs the session with the provided configuration and options.
     @discussion Calling run on a session that has already started will
     transition immediately to using the new configuration. Options
     can be used to alter the default behavior when transitioning configurations.
     @param configuration The configuration to use.
     @param options The run options to use.
*/
open func run(_ configuration: ARConfiguration, options: ARSession.RunOptions = [])

ARConfiguration

ARSessionARConfiguration子类来开启。不同Configuration有不同的特性,都是通过环境中的特征点来进行追踪。

ARWorldTrackingConfiguration - iOS 11.0+ - 6DOF

使用后置摄像头精确跟踪设备的位置和方向,并允许平面检测、hit-testing、基于环境的光线估计、以及图像和对象检测追踪。
ARKit使用视觉惯性测量法(visual-inertial odometry)在真实和虚拟空间之间建立对应关系。

功能

  • planeDetection:查找现实平面(水平或竖直),并作为ARPlaneAnchor对象来添加到会话中。
  • detectionImages:识别2D图像并追踪图像的移动,并作为ARImageAnchor对象添加到场景中。
  • detectionObjects:识别3D对象,并作为ARObjectAnchor对象添加到场景中。
  • environmentTexturing:光面物体上展示环境纹理。
  • ARFrame,ARSCNView或者ARSKView中通过hit-testing来查找与相机场景的2D坐标对应的现实世界中的位置。

最佳实践:

  • 在可靠的照明条件中设计AR体验。世界追踪需要清晰的图像来进行图像分析。如果细节不清晰,追踪效果将会降低。比如,相机对着空白墙面或者处于光线不足的场景中时。
  • 根据追踪信息来提供用户反馈。世界追踪将图像分析与设备运动关联。如果设备正在移动,ARKit会更好地理解场景。但过度的运动又会降低追踪质量。ARCamera类提供追踪状态的原因信息,可以使用此信息来进行UI展示
  • 留出时间进行平面检测,并在获得所需结果时禁用平面检测。平面检测结果是一个凸多边形,会随着检测结果不断变化。

AROrientationTrackingConfiguration - iOS 11.0+ - 3DOF

提供基本AR体验。使用后置摄像头跟踪设备方向。

ARFaceTrackingConfiguration - iOS 11.0+

提供使用前置摄像头的AR体验,并跟踪用户脸部拓扑和表情。
检测到人脸会返回一个ARFaceAnchor对象。其中的信息包括包头部姿势,脸部网格拓扑,眼球追踪信息和混合形状的信息系数。如果启用光估计,则会估计光线方向。

开启会话:

guard ARFaceTrackingConfiguration.isSupported else { return }
let configuration = ARFaceTrackingConfiguration()
configuration.isLightEstimationEnabled = true
sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])

  • ARFaceTrackingConfiguration:使用TrueDepth相机追踪脸部动作和表情
  • ARFaceAnchor:包含脸部姿势,拓扑,表情信息。如果有多张脸,ARKit会旋转最大的或最清晰的来识别。
  • ARSCNFaceGeometry
  • ARDirectionalLightEstimate: 模拟环境光照信息

ARImageTrackingConfiguration - iOS 12.0+ - 6DOF

使用后置摄像头来追踪已知图像,最多可同时最终4张图像。

image

通过在Asset catalog中创建AR Resource Group,导入需要识别的图像,来进行检测。Group中最多可导入25张图片。

在选择图像时有几点要求:

  • 为每张图像指定准确物理尺寸。ARKit通过这个物理尺寸决定图像与镜头的距离。
  • 特征点明显,对比度高。利于识别。
  • 避免反光材质等会干扰视觉图像的因素。

example:

guard let referenceImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil) else {
    fatalError("Missing expected asset catalog resources.")
}

let configuration = ARWorldTrackingConfiguration()
configuration.detectionImages = referenceImages
session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
  • ARReferenceImage: 在现实世界环境中被识别的图像。
  • ARImageAnchor:包含检测到的图像的位置和方向信息。

最佳实践

  • 使用检测到的图像来设置AR场景的参考系
  • 使用检测到的图像作为虚拟内容的起点
  • 考虑何时允许检测到的图像来触发交互:检测到图像时,操作只会触发一次。要触发多次可使用removeAnchor:在合适的时间主动移除,下一次检测到图像时,ARKit会添加一个新的anchor.

ARObjectScanningConfiguration - iOS 12.0+ - 6DOF

提供使用后置摄像头收集高保真空间数据,创建参考对象以便在其他AR体验中进行检测。
通过在Asset catalog中创建AR Resource Group,导入需要包含识别对象信息的.arobject文件,来进行检测。

image

example:

let configuration = ARWorldTrackingConfiguration()
guard let referenceObjects = ARReferenceObject.referenceObjects(inGroupNamed: "gallery", bundle: nil) else {
    fatalError("Missing expected asset catalog resources.")
}
configuration.detectionObjects = referenceObjects
sceneView.session.run(configuration)
  • ARReferenceObject:要识别的3D对象
  • ARObjectAnchor:检测到的3D对象的位置和方向信息。

degrees of freedom

下面这幅图展示的是6 degrees of freedom。其实就是包含在三位坐标x, y, z三轴上的位置(在轴上平移)和方向(绕轴旋转)。


image

ARFrame

每一个ARFrame都包含一个ARCamera(虚拟的相机对象:包含位置和成像特征的信息)
ARFrame包含如下信息:

  • 带有位置追踪信息的视频图像
  • 追踪的信息和状态
  • 场景信息

ARHitTestResult

包含通过检查AR会话的设备摄像机视图中的点找到有关真实世界表面的信息。

ARAnchor

锚点,这个大家都比较好理解。
我们如果要在现实世界中挂一幅画要怎么做呢?大致只需要两步。

  1. 找到我们要挂画的位置,定一个钉子(下个锚点)
  2. 把你的画(虚拟物体),挂上去

特点:

  • 物理世界中的点,用于放置虚拟物体。
  • 包含现实世界位置和方向
  • 通过ARSession添加和删除
  • 有丰富的子类,包含不同的anchor信息, 或自定义anchor
  • 通过ARSessionDelegate更新 add/update/remove

SceneKit相关

了解了ARKit的操作,下一步就要进行渲染。SceneKit负责所有虚拟物体的渲染。这里我们使用ARSCNView,它的主要功能如下

  • 绘制捕捉的图像
  • 更新SCNCamera
  • 更新场景光线
  • 映射SCNNodes到ARAchors
image

SceneKit会把ARAnchorSCNNode对应。我们要操作虚拟物体时,只需要操作Scene世界中的Node.我们关注的也都是ARSCNViewDelegate的回调。

环境音效

可以使用SceneKit的node-based audio API给物体添加声音。如果需要环境音效效果,需要使用单声道音频。

example:

// MARK: - Sound
    /// Sets up the audio for playback.
    /// - Tag: SetUpAudio
    private func setUpAudio() {
        // Instantiate the audio source
        audioSource = SCNAudioSource(fileNamed: "fireplace.mp3")!
        // As an environmental sound layer, audio should play indefinitely
        audioSource.loops = true
        // Decode the audio from disk ahead of time to prevent a delay in playback
        audioSource.load()
    }
    /// Plays a sound on the `objectNode` using SceneKit's positional audio
    /// - Tag: AddAudioPlayer
    private func playSound() {
        // Ensure there is only one audio player
        objectNode.removeAllAudioPlayers()
        // Create a player from the source and add it to `objectNode`
        objectNode.addAudioPlayer(SCNAudioPlayer(source: audioSource))
    }

ARKit 2新特性

空间映射的存储和共享

新增了ARWorldMap,包含映射信息。可以保存场景的状态,进行场景共享

image

World Tracking Enhancements

  • 保存/加载映射
  • 更快的初始化和平面检测
  • 检测更精准
  • 连续对焦
  • 4:3视频格式, ARKit2的默认格式

Environment Texturing

可以在光面物体上反射环境纹理,让物体更逼真。

Image Tracking

查阅ARImageTrackingConfiguration

Object Detection

查阅ARObjectScanningConfiguration

Face Tracking Enhancements

新增眼球👀和舌头😝追踪

推荐阅读

官方手册

Introducing ARKit: Augmented Reality for iOS

Face Tracking with ARKit

What’s New in ARKit 2

Understanding ARKit Tracking and Detection

推荐阅读更多精彩内容