对用户环境汇总的2D图像做出反应,并使用其位置展示AR内容。

代码下载


概述

许多AR体验可以通过 使用已知的用户环境特性来触发虚拟内容的展示 的方法来增强体验。例如,一个博物馆的app在用户将他们的设备指向一副绘画时显示出一位虚拟馆长。或者在桌游中,当玩家将设备指向桌游板时会看到虚拟的物件。iOS11.3之后,你可以通过启用ARKit的图像检测来添加这些特性到你的APP中: 首先你需要提供已知的2D图像,接下来ARKit将会告知你在AR会话中这些图像曾经出现在何时何地。

这个示例app会查找在app的资源目录(asset catalog)中所有的关联图像。当ARKit检测到这些图片中的一张时,app将会显示一条识别到图像的消息和一个简短的展示其场景中位置的动画。

重要

实例中包含的图像是为了符合多种苹果设备而专门设计的。为了使用这些图像来尝试该应用,选择一个适用于你的其他设备的图片,并将图片全屏展示在该设备上。接下来在一个不同的设备上运行示例代码项目,并将该设备的摄像头指向展示图像的设备。另外,你可以添加你自己的图片;查看下面的提供你自己的相关图片

笔记

ARKit要求iOS设备的处理器不低于A9。ARKit是无法在iOS模拟器中运行的

启用图像检测

图像检测是世界追踪AR会话的一个附加特性。(更多细节参见Tracking and Visualizing Planes)

为了启用图像检测:

  1. 从应用的资源目录中加载一个或多个ARReferenceImage 资源。
  2. 创建一个世界追踪配置项并将这些关联图像传入配置项的detectionImages 属性。
  3. 使用run(_:options:)方法基于配置项运行会话。

以下代码介绍了示例app在启动或者重启AR体验时如何执行这几个步骤的。

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])

成像图像检测结果

当ARKit检测到关联图像中的一张时,会话将会自动添加一个对应的ARImageAnchor 到会话的锚点列表中。为了响应一个图像被检测,实现一个适用的ARSessionDelegate, ARSKViewDelegate, 或者 ARSCNViewDelegate 方法来上报新的锚点被添加到会话中。(这个示例app使用renderer(_:didAdd:for:) 方法来执行下列代码)

为了使用检测到的图片作为AR内容的触发,你需要知道其位置、方向、大小和关联图像。锚点继承的transform 属性提供了位置和方向,其referenceImage 属性提供了是哪个ARReferenceImage 对象被检测到。如果AR内容基于场景中的图像的范围,你可以使用图像的physicalSize 来设置你的内容,如下代码所示。

guard let imageAnchor = anchor as? ARImageAnchor else { return }
let referenceImage = imageAnchor.referenceImage
updateQueue.async {

    // Create a plane to visualize the initial position of the detected image.
    let plane = SCNPlane(width: referenceImage.physicalSize.width,
                         height: referenceImage.physicalSize.height)
    let planeNode = SCNNode(geometry: plane)
    planeNode.opacity = 0.25

    /*     `SCNPlane` is vertically oriented in its local coordinate space, but     `ARImageAnchor` assumes the image is horizontal in its local space, so     rotate the plane to match.     */
    planeNode.eulerAngles.x = -.pi / 2

    /*     Image anchors are not tracked after initial detection, so create an     animation that limits the duration for which the plane visualization appears.     */
    planeNode.runAction(self.imageHighlightAction)

    // Add the plane visualization to the scene.
    node.addChildNode(planeNode)
}

提供自定义关联图像

为了使用自定义的图像来检测(无论是在示例项目还是你自己的项目),你都需要将这些自定义图片添加到你的Xcode的资源目录中。

  1. 打开项目的资源目录,使用Add按钮(+)来添加一个新的AR资源组。
  2. 从Finder中拖拽图像文件到新创建的资源组中。
  3. 对于每一个图像,使用检查工具来描述你期望在用户的真实环境汇总找到该图像的物理大小,可选择性的添加自用描述名称。

笔记

将某个会话需要的所有图像都放如同一个资源组中。使用分开的资源组来保存在不同会话使用的图像集合。例如,一个艺术博物馆app可能会使用不同的会话(因此也是多个资源组)在博物馆不同的区域检测绘画作品。

知晓图像检测的能力。 选择,设计并配置关联图片从而实现最佳的可靠性和性能:

  • 在Xcode中尽可能准确的输入图像的物理大小。ARKit基于该信息来确定图像到像头的距离。由于输入不正确的物理大小,将会导致ARImageAnchor 与摄像头的距离发生错误。
  • 当你添加关联图像到Xcode的资源目录时,注意Xcode提供的质量评估警告。有较高对比度的图像最有利于图像检测。
  • 只使用在平整表面上的图像来检测。如果过用来被检测的图像是在不平整的表面上,例如红酒瓶上的标签,ARKit可能无法完全检测到,或者在错误的位置创建一个图像锚点。
  • 考虑图像在不同光照条件下如何展示。如果一个图像通过光面纸打印或者再设备的屏幕上展示,表面的反光会干扰检测。

应用最佳实践

这个示例app只是简单的将ARKit在用户环境中检测到的每一个关联图像成像出来,但是你的app可以做的更多。遵循如下几点来设计更好的使用图像检测的AR体验。

使用检测到的图像为AR场景设置参考系。 使用检测到的图片来锚定虚拟场景,而不是需要用户选择一个位置放置虚拟内容,或者在用户环境中随机放置内容。你甚至可以使用多个检测到的图像。例如,零售商店的app可以通过检测放置在门两侧的海报在门店的前门放置一个虚拟人物,并在海报之间直接计算出虚拟人物应该在的位置。

笔记

使用ARSessionsetWorldOrigin(relativeTransform:) 方法来重新定义实际坐标系,因此你可以相对于所选参考点放置所有的锚点和其他内容。

通过将检测到的图像用作虚拟内容的起点来设计AR体验。 ARKit不会追踪每一个检测到的图片的位置或者方向的变化。如果你想追随某个检测到的图像放置虚拟内容,该内容可能无法总是出现在正确的位置。取而代之的是,使用检测到的图片作为参考系来创建一个动态场景。例如,你的app检测到了剧院中科幻电影的海报,接下来虚拟太空船便从海报中出现并在环境中飞行。

考虑何时允许每一个图像的检测都触发(或重复)AR交互。 ARKit每次只会为会话配置项中的detectionImages 数组中的一个关联图像添加图像锚点到会话。当一个图像被检测到时,如果你的AR体验将虚拟内容添加到场景中,该动作默认情况下只会发生一次。为了允许用户在不重启app的前提下再一次体验该内容,调用会话的remove(anchor:) 方法来移除相应的ARImageAnchor 。当锚点被移除之后,ARKit将会在下一次检测到该图像时添加新的锚点。

例如,在上述情况中,当飞船飞出电影海报后,你可能不希望在前一个动画还在播放时,另一个重复的动画出现。等到动画结束后再移除锚点,因此用户便可以通过将设备再一次指向图像而触发动画。