说明
ARKit系列文章目录
资料下载
你是否曾经站在博物馆展台前面,不满足于艺术品或手工艺品前面的小卡片所展示的内容,想要知道更多?要是有一个这样的 app 该有多好。现在,你可以用 ARKit 2 来自己制作一个带有图片/物体检测与追踪的 app。
为了让体验更加有趣,ARKit 允许 app 添加动态的虚拟内容到真实世界物体上。它允许我们为真实世界的地方和物品创建一个交互式的引导 app。是博物馆,画廊,游乐场和学校等地的完美配套 app。它可以让任何地方“活起来”,提供一个动态的或定制的体验。
在本教程中,你将构建一个TriassicLoupe(三叠纪放大镜),一个用在自然历史博物馆里恐龙展览的配套 app。这个概念来自珠宝商的放大镜;这个 app 会在用户指向展品的时候显示出隐藏的细节。如果你周围没有任何恐龙,请不要担心 - 你可以使用普通的家用物品作为占位。
最终应用程序在信息图像上显示一段简短的动画。它还会在复制品旁边显示有关恐龙的信息。该 app 还将为该物体添加一些可怕的声音效果。

该应用程序将 ARKit 与 SceneKit(iOS的3D图形框架)结合使用。你会看到 ARKit 使用 SceneKit 完成所有繁重的工作。对于图片追踪和物体追踪,您将只使用非常基本的 SceneKit 功能,本教程中您从中学到的所有内容都是通用的。了解有关 SceneKit 的更多信息将使您能够构建更丰富的应用程序,但这超出了本教程的范围。
开始
ARKit 依赖于A9或更高版本处理器的内置功能。它使用了机器学习,后置摄像头,以及视频和图像处理。这意味着 ARKit 应用程序需要在iPhone 6s或更新版本上运行,并且它们无法在模拟器中运行。
使用超长的Lightning线缆或者设置设备以通过 Wi-Fi 连接到Xcode方便调试。 ARKit 需要移动一点才能获得一张好的世界地图。世界地图是 ARKit 对物理空间的意识。它是一系列特征点,尺寸,方向和锚点。
稍后你会需要扫描一些图像。显示器上显示的图像应该也适用,但如果您在扫描图像时遇到问题,则可能需要打印图像以获得更好的效果。
要开始使用,请使用本教程顶部或底部的“下载材料”按钮下载入门项目。 .zip文件包含一个帮助项目,包含将在教程中使用的素材,以及初始项目和最终项目。
打开入门项目。应用程序本身非常简单,只需一个ViewController
即可添加所有逻辑。有一个辅助结构体,DinosaurFacts
,其中包含一些关于一些恐龙的基本信息。
如果你构建并运行,你会看到一个黑屏,因为你尚未连接ARKit会话。

创建图片检测
首先要做的是创建图片检测。图片检测可能是ARKit最简单的功能。要创建图片检测器,您所要做的就是提供带有图像副本的图像跟踪会话。这些提供的图像称为参考图片。
添加参考图片
TriassicLoupe 使用含有信息标志的艺术作品作为参考图像。当用户将应用程序指向其中一个标志时,该应用程序将添加恐龙图像叠加层。
与其他应用程序图像一样,增强现实(AR)参考图像存在于素材目录asset catalog中。参考图像有点特殊,因为它们需要专门为ARKit分组。
打开Assets.xcassets 点击下面的 + 按钮。
从弹出菜单中,选择New AR Resource Group以创建新组。将其重命名为AR Images,因为该组将保留参考图像。

在Finder中,从下载的材料中打开Dinosaur Images文件夹。将每个图像文件逐个拖动到Xcode中的AR Images中。完成后,您应该有三个带黄色警告三角形的图像。

如果参考图像作为参考质量不好,Xcode会发出警告。这可能是因为它们太小或者没有足够的特征或对比度。具有大量空白空间,颜色太少或缺乏独特形状的图像是难以检测的。
在这种情况下,警告是“不支持的配置”警告。这是因为参考图像必须具有非零的正宽度
。 AR参考图像需要您指定其实际尺寸!
在资产库中选择stegosaurus(剑龙)图像。然后选择Attributes inspector。
将单位更改为英寸。接下来,输入宽度4.15。当你这样做时,根据纵横比,高度将自动变为2.5711!这些数字就是您桥接虚拟世界和真实世界的地方。

这两张图片,配置值如下:
- trex:Inches, width: 6.3333, height: 4.75
- triceratops: Inches, width: 5, height: 2.8125
当你输入尺寸后,警告就消失了。

这些图像对应于所包含的Dinosaurs.key Keynote文件的幻灯片。每张幻灯片代表一个信息标语牌,旁边是博物馆展示。在美国信纸大小的纸张上打印时,这个尺寸就是物理图像尺寸。
注意:某些图像实际上是在Keynote幻灯片中裁剪出来的。只要保持大小和宽高比相同,ARKit 完全能够识别并匹配。
这些图像都是不同的风格,以展示ARKit系列的一小部分。这里有两件事情:1。图像中有足够的形状和对比度。 2.真实世界中的图片平坦,光线充足,不反光。
书页上,壁纸上或在镜相打印出的图片是难以识别的。照片,绘画或插图可以很好地识别出来。如果参考图片不够友好,Xcode会发出警告。这样就无需在运行时猜测!
现在,是时候继续编写代码来寻找这些图像了。
添加图片追踪
在ViewController.swift中,在注释下添加一个新变量:// Add configuration variables here:
private var imageConfiguration: ARImageTrackingConfiguration?
这将设置一个变量,以便在创建后保留图像跟踪配置。
现在,查找setupImageDetection()
并添加以下代码:
imageConfiguration = ARImageTrackingConfiguration()
这会将该实例变量设置为新的ARImageTrackingConfiguration
。顾名思义,此类是一个ARKit配置,用于检测和跟踪图像。
在该行下面,添加以下内容:
guard let referenceImages = ARReferenceImage.referenceImages(
inGroupNamed: "AR Images", bundle: nil) else {
fatalError("Missing expected asset catalog resources.")
}
imageConfiguration?.trackingImages = referenceImages
这将使用您刚刚在素材目录中创建的AR Images
组中的图像,创建一个ARReferenceImage
集。然后,将它们作为要跟踪的图像列表添加到配置中。
注意:图像检测最适用于资源组中不超过25个图片。如果您的博物馆有超过25个展品,您可以创建多个资源组,并在用户在建筑物周围移动时切换它们。
要使用配置,请将以下内容添加到viewWillAppear(_ :)
:
if let configuration = imageConfiguration {
sceneView.session.run(configuration)
}
这将使用imageConfiguration
启动ARKit会话。一旦运行,ARKit将处理相机数据以检测参考图片。
要确保全部启动,请将以下内容添加到viewDidLoad()
的底部:
setupImageDetection()
最后,为了平衡会话运行,在viewWillDisappear(_ :)
添加:
sceneView.session.pause()
当视图消失时,这会暂停会话。ARKit会话会因为相机调用,视频处理和渲染,而把电池耗尽。在我们的单视图应用程序中,这不是什么大问题,但是尊重用户的设备并在没有显示时暂停会话总是一个好主意。
处理检测到的图片
一旦检测到图像,AR会话就会将ARImageAncho
r添加到其世界地图中。当发生这种情况时,您将在渲染器处获得回调renderer(_:didAdd:for:)
。
在ViewController.swift的底部找到此函数并添加以下代码:
DispatchQueue.main.async { self.instructionLabel.isHidden = true }
if let imageAnchor = anchor as? ARImageAnchor {
handleFoundImage(imageAnchor, node)
}
此代码检查是否为图像锚点添加了新添加的节点。这意味着在现实世界中检测到图像。
将handleFoundImage(_:_:)
函数替换为:
let name = imageAnchor.referenceImage.name!
print("you found a \(name) image")
let size = imageAnchor.referenceImage.physicalSize
if let videoNode = makeDinosaurVideo(size: size) {
node.addChildNode(videoNode)
node.opacity = 1
}
这将从锚点的参考图片中获取图像的名称和大小。您在素材目录中指定了这些值。使用该尺寸,调用辅助函数以在检测到的图像之上创建视频播放器。
要创建视频节点,请将makeDinosaurVideo(size :)
的内容替换为:
// 1
guard let videoURL = Bundle.main.url(forResource: "dinosaur",
withExtension: "mp4") else {
return nil
}
// 2
let avPlayerItem = AVPlayerItem(url: videoURL)
let avPlayer = AVPlayer(playerItem: avPlayerItem)
avPlayer.play()
// 3
NotificationCenter.default.addObserver(
forName: .AVPlayerItemDidPlayToEndTime,
object: nil,
queue: nil) { notification in
avPlayer.seek(to: .zero)
avPlayer.play()
}
// 4
let avMaterial = SCNMaterial()
avMaterial.diffuse.contents = avPlayer
// 5
let videoPlane = SCNPlane(width: size.width, height: size.height)
videoPlane.materials = [avMaterial]
// 6
let videoNode = SCNNode(geometry: videoPlane)
videoNode.eulerAngles.x = -.pi / 2
return videoNode
此功能创建一个视频播放器并将其放入一个大小适合图像的SceneKit节点。它通过以下方式实现:
- 从资源包中抓取视频。这有一个适用于所有恐龙的简单动画。但您可以根据图像锚点的名称为每种恐龙类型提供不同的视频。
- 为该视频创建和启动
AVPlayer
。
- AVPlayer 实例并不会自动循环播放。此通知块通过侦听播放器完成来循环视频。然后, 它会返回开头并重新开始播放。
- SceneKit 不使用
UIViews
, 而是使用节点来渲染场景。不能直接添加AVPlayer
。相反, 视频播放器可以用作节点的纹理或 "材质"。这将把视频帧映射到关联的节点。
- 检测到的图像是平坦正方形 (即平面), 因此覆盖的节点是与检测到的图像大小相同的
SCNPlane
。这架飞机被装饰成视频作为其纹理。
- 创建出的实际节点将成为场景的一部分。这就需要在 x 轴上进行翻转, 以便它正确显示给用户。
尝试一下
最后的最后, 是时候构建并运行了!但是, 首先, 打印幻灯片Dinosaurs.key中至少一张恐龙。将其放置在光线充足的区域中 (垂直或水平).
构建并运行该应用程序。接受相机权限并显示视频后, 请将其指向打印页面。它可能需要两只稳定的手来检测图像。完成后, 您将在控制台中看到一个注释, 并在屏幕上显示一个动画叠加。

不幸的是, 如果会话启动, 但它没有检测到图像, 那也没有错误消息。大多数情况下, ARKit 不保证能找到该图像, 因此它不被视为错误。只要素材目录中没有关于图像的警告, 就应该最终检测到该图像。
添加物体检测和追踪
现在, 您已经看到了图像检测如何工作。接下来, 您将向应用添加物体检测。从开发人员的角度来看, 物体检测的工作原理几乎相同。主要区别在于它将寻找三维物体而不是平面图像。设置物体检测稍微复杂一些。参考物体的创建也比较复杂。
回顾一下, 以下是使用图像和物体检测的步骤:
- 创建参考对象。
- 将参考对象放入素材集的AR Resources组中。
- 创建一个 ARKit 会话。
- 加载参考图片/物体,并设置会话来检测他们。
- 启动 session.
- 等待锚点被添加时的回调。
- 添加交互节点到场景中,或采取其他措施。
物体检测
另一个有用的 ARKit 函数是物体检测和跟踪。TriassicLoupe 检测已知物体并标记它们。在现实中, 这些将是恐龙在一个透视或恐龙骨架。对于本教程, 您将使用手头上的任何东西。
选择参考物体
检测物体所需的第一件事是参考物体。通过图像检测, 您可以创建、扫描或拍摄图像。但是, 对于3D 对象, 参考物体很难构造.
ARKit 提供了自己的 API, 用于使用 iPhone 扫描它们来创建参考物体。TriassicLoupe 不直接使用此项, 因为它只能检测到一组已知的对象。您可以使用 Apple 提供的实用程序提前扫描它们。
如果可以, 您应该下载 Apple 的对象扫描程序项目Object Scanner project。它也包括在项目下载ScanningAndDetecting3DObjects文件夹中, 为您的方便。请注意, 在您阅读此内容时, 包含的项目可能已过期。
此应用程序扫描对象, 并允许您导出. arobject
文件。然后, 您可以将此文件作为素材导入到 Xcode 项目中。成功的扫描需要有合适的对象和良好的照明。适当的对象是:
说明
ARKit系列文章目录
资料下载
你是否曾经站在博物馆展台前面,不满足于艺术品或手工艺品前面的小卡片所展示的内容,想要知道更多?要是有一个这样的 app 该有多好。现在,你可以用 ARKit 2 来自己制作一个带有图片/物体检测与追踪的 app。
为了让体验更加有趣,ARKit 允许 app 添加动态的虚拟内容到真实世界物体上。它允许我们为真实世界的地方和物品创建一个交互式的引导 app。是博物馆,画廊,游乐场和学校等地的完美配套 app。它可以让任何地方“活起来”,提供一个动态的或定制的体验。
在本教程中,你将构建一个TriassicLoupe(三叠纪放大镜),一个用在自然历史博物馆里恐龙展览的配套 app。这个概念来自珠宝商的放大镜;这个 app 会在用户指向展品的时候显示出隐藏的细节。如果你周围没有任何恐龙,请不要担心 - 你可以使用普通的家用物品作为占位。
最终应用程序在信息图像上显示一段简短的动画。它还会在复制品旁边显示有关恐龙的信息。该 app 还将为该物体添加一些可怕的声音效果。

该应用程序将 ARKit 与 SceneKit(iOS的3D图形框架)结合使用。你会看到 ARKit 使用 SceneKit 完成所有繁重的工作。对于图片追踪和物体追踪,您将只使用非常基本的 SceneKit 功能,本教程中您从中学到的所有内容都是通用的。了解有关 SceneKit 的更多信息将使您能够构建更丰富的应用程序,但这超出了本教程的范围。
开始
ARKit 依赖于A9或更高版本处理器的内置功能。它使用了机器学习,后置摄像头,以及视频和图像处理。这意味着 ARKit 应用程序需要在iPhone 6s或更新版本上运行,并且它们无法在模拟器中运行。
使用超长的Lightning线缆或者设置设备以通过 Wi-Fi 连接到Xcode方便调试。 ARKit 需要移动一点才能获得一张好的世界地图。世界地图是 ARKit 对物理空间的意识。它是一系列特征点,尺寸,方向和锚点。
稍后你会需要扫描一些图像。显示器上显示的图像应该也适用,但如果您在扫描图像时遇到问题,则可能需要打印图像以获得更好的效果。
要开始使用,请使用本教程顶部或底部的“下载材料”按钮下载入门项目。 .zip文件包含一个帮助项目,包含将在教程中使用的素材,以及初始项目和最终项目。
打开入门项目。应用程序本身非常简单,只需一个ViewController
即可添加所有逻辑。有一个辅助结构体,DinosaurFacts
,其中包含一些关于一些恐龙的基本信息。
如果你构建并运行,你会看到一个黑屏,因为你尚未连接ARKit会话。

创建图片检测
首先要做的是创建图片检测。图片检测可能是ARKit最简单的功能。要创建图片检测器,您所要做的就是提供带有图像副本的图像跟踪会话。这些提供的图像称为参考图片。
添加参考图片
TriassicLoupe 使用含有信息标志的艺术作品作为参考图像。当用户将应用程序指向其中一个标志时,该应用程序将添加恐龙图像叠加层。
与其他应用程序图像一样,增强现实(AR)参考图像存在于素材目录asset catalog中。参考图像有点特殊,因为它们需要专门为ARKit分组。
打开Assets.xcassets 点击下面的 + 按钮。
从弹出菜单中,选择New AR Resource Group以创建新组。将其重命名为AR Images,因为该组将保留参考图像。

在Finder中,从下载的材料中打开Dinosaur Images文件夹。将每个图像文件逐个拖动到Xcode中的AR Images中。完成后,您应该有三个带黄色警告三角形的图像。

如果参考图像作为参考质量不好,Xcode会发出警告。这可能是因为它们太小或者没有足够的特征或对比度。具有大量空白空间,颜色太少或缺乏独特形状的图像是难以检测的。
在这种情况下,警告是“不支持的配置”警告。这是因为参考图像必须具有非零的正宽度
。 AR参考图像需要您指定其实际尺寸!
在资产库中选择stegosaurus(剑龙)图像。然后选择Attributes inspector。
将单位更改为英寸。接下来,输入宽度4.15。当你这样做时,根据纵横比,高度将自动变为2.5711!这些数字就是您桥接虚拟世界和真实世界的地方。

这两张图片,配置值如下:
- trex:Inches, width: 6.3333, height: 4.75
- triceratops: Inches, width: 5, height: 2.8125
当你输入尺寸后,警告就消失了。

这些图像对应于所包含的Dinosaurs.key Keynote文件的幻灯片。每张幻灯片代表一个信息标语牌,旁边是博物馆展示。在美国信纸大小的纸张上打印时,这个尺寸就是物理图像尺寸。
注意:某些图像实际上是在Keynote幻灯片中裁剪出来的。只要保持大小和宽高比相同,ARKit 完全能够识别并匹配。
这些图像都是不同的风格,以展示ARKit系列的一小部分。这里有两件事情:1。图像中有足够的形状和对比度。 2.真实世界中的图片平坦,光线充足,不反光。
书页上,壁纸上或在镜相打印出的图片是难以识别的。照片,绘画或插图可以很好地识别出来。如果参考图片不够友好,Xcode会发出警告。这样就无需在运行时猜测!
现在,是时候继续编写代码来寻找这些图像了。
添加图片追踪
在ViewController.swift中,在注释下添加一个新变量:// Add configuration variables here:
private var imageConfiguration: ARImageTrackingConfiguration?
这将设置一个变量,以便在创建后保留图像跟踪配置。
现在,查找setupImageDetection()
并添加以下代码:
imageConfiguration = ARImageTrackingConfiguration()
这会将该实例变量设置为新的ARImageTrackingConfiguration
。顾名思义,此类是一个ARKit配置,用于检测和跟踪图像。
在该行下面,添加以下内容:
guard let referenceImages = ARReferenceImage.referenceImages(
inGroupNamed: "AR Images", bundle: nil) else {
fatalError("Missing expected asset catalog resources.")
}
imageConfiguration?.trackingImages = referenceImages
这将使用您刚刚在素材目录中创建的AR Images
组中的图像,创建一个ARReferenceImage
集。然后,将它们作为要跟踪的图像列表添加到配置中。
注意:图像检测最适用于资源组中不超过25个图片。如果您的博物馆有超过25个展品,您可以创建多个资源组,并在用户在建筑物周围移动时切换它们。
要使用配置,请将以下内容添加到viewWillAppear(_ :)
:
if let configuration = imageConfiguration {
sceneView.session.run(configuration)
}
这将使用imageConfiguration
启动ARKit会话。一旦运行,ARKit将处理相机数据以检测参考图片。
要确保全部启动,请将以下内容添加到viewDidLoad()
的底部:
setupImageDetection()
最后,为了平衡会话运行,在viewWillDisappear(_ :)
添加:
sceneView.session.pause()
当视图消失时,这会暂停会话。ARKit会话会因为相机调用,视频处理和渲染,而把电池耗尽。在我们的单视图应用程序中,这不是什么大问题,但是尊重用户的设备并在没有显示时暂停会话总是一个好主意。
处理检测到的图片
一旦检测到图像,AR会话就会将ARImageAncho
r添加到其世界地图中。当发生这种情况时,您将在渲染器处获得回调renderer(_:didAdd:for:)
。
在ViewController.swift的底部找到此函数并添加以下代码:
DispatchQueue.main.async { self.instructionLabel.isHidden = true }
if let imageAnchor = anchor as? ARImageAnchor {
handleFoundImage(imageAnchor, node)
}
此代码检查是否为图像锚点添加了新添加的节点。这意味着在现实世界中检测到图像。
将handleFoundImage(_:_:)
函数替换为:
let name = imageAnchor.referenceImage.name!
print("you found a \(name) image")
let size = imageAnchor.referenceImage.physicalSize
if let videoNode = makeDinosaurVideo(size: size) {
node.addChildNode(videoNode)
node.opacity = 1
}
这将从锚点的参考图片中获取图像的名称和大小。您在素材目录中指定了这些值。使用该尺寸,调用辅助函数以在检测到的图像之上创建视频播放器。
要创建视频节点,请将makeDinosaurVideo(size :)
的内容替换为:
// 1
guard let videoURL = Bundle.main.url(forResource: "dinosaur",
withExtension: "mp4") else {
return nil
}
// 2
let avPlayerItem = AVPlayerItem(url: videoURL)
let avPlayer = AVPlayer(playerItem: avPlayerItem)
avPlayer.play()
// 3
NotificationCenter.default.addObserver(
forName: .AVPlayerItemDidPlayToEndTime,
object: nil,
queue: nil) { notification in
avPlayer.seek(to: .zero)
avPlayer.play()
}
// 4
let avMaterial = SCNMaterial()
avMaterial.diffuse.contents = avPlayer
// 5
let videoPlane = SCNPlane(width: size.width, height: size.height)
videoPlane.materials = [avMaterial]
// 6
let videoNode = SCNNode(geometry: videoPlane)
videoNode.eulerAngles.x = -.pi / 2
return videoNode
此功能创建一个视频播放器并将其放入一个大小适合图像的SceneKit节点。它通过以下方式实现:
- 从资源包中抓取视频。这有一个适用于所有恐龙的简单动画。但您可以根据图像锚点的名称为每种恐龙类型提供不同的视频。
- 为该视频创建和启动
AVPlayer
。
- AVPlayer 实例并不会自动循环播放。此通知块通过侦听播放器完成来循环视频。然后, 它会返回开头并重新开始播放。
- SceneKit 不使用
UIViews
, 而是使用节点来渲染场景。不能直接添加AVPlayer
。相反, 视频播放器可以用作节点的纹理或 "材质"。这将把视频帧映射到关联的节点。
- 检测到的图像是平坦正方形 (即平面), 因此覆盖的节点是与检测到的图像大小相同的
SCNPlane
。这架飞机被装饰成视频作为其纹理。
- 创建出的实际节点将成为场景的一部分。这就需要在 x 轴上进行翻转, 以便它正确显示给用户。
尝试一下
最后的最后, 是时候构建并运行了!但是, 首先, 打印幻灯片Dinosaurs.key中至少一张恐龙。将其放置在光线充足的区域中 (垂直或水平).
构建并运行该应用程序。接受相机权限并显示视频后, 请将其指向打印页面。它可能需要两只稳定的手来检测图像。完成后, 您将在控制台中看到一个注释, 并在屏幕上显示一个动画叠加。

不幸的是, 如果会话启动, 但它没有检测到图像, 那也没有错误消息。大多数情况下, ARKit 不保证能找到该图像, 因此它不被视为错误。只要素材目录中没有关于图像的警告, 就应该最终检测到该图像。
添加物体检测和追踪
现在, 您已经看到了图像检测如何工作。接下来, 您将向应用添加物体检测。从开发人员的角度来看, 物体检测的工作原理几乎相同。主要区别在于它将寻找三维物体而不是平面图像。设置物体检测稍微复杂一些。参考物体的创建也比较复杂。
回顾一下, 以下是使用图像和物体检测的步骤:
- 创建参考对象。
- 将参考对象放入素材集的AR Resources组中。
- 创建一个 ARKit 会话。
- 加载参考图片/物体,并设置会话来检测他们。
- 启动 session.
- 等待锚点被添加时的回调。
- 添加交互节点到场景中,或采取其他措施。
物体检测
另一个有用的 ARKit 函数是物体检测和跟踪。TriassicLoupe 检测已知物体并标记它们。在现实中, 这些将是恐龙在一个透视或恐龙骨架。对于本教程, 您将使用手头上的任何东西。
选择参考物体
检测物体所需的第一件事是参考物体。通过图像检测, 您可以创建、扫描或拍摄图像。但是, 对于3D 对象, 参考物体很难构造.
ARKit 提供了自己的 API, 用于使用 iPhone 扫描它们来创建参考物体。TriassicLoupe 不直接使用此项, 因为它只能检测到一组已知的对象。您可以使用 Apple 提供的实用程序提前扫描它们。
如果可以, 您应该下载 Apple 的对象扫描程序项目Object Scanner project。它也包括在项目下载ScanningAndDetecting3DObjects文件夹中, 为您的方便。请注意, 在您阅读此内容时, 包含的项目可能已过期。
此应用程序扫描对象, 并允许您导出. arobject
文件。然后, 您可以将此文件作为素材导入到 Xcode 项目中。成功的扫描需要有合适的对象和良好的照明。适当的对象是:
说明
ARKit系列文章目录
资料下载
你是否曾经站在博物馆展台前面,不满足于艺术品或手工艺品前面的小卡片所展示的内容,想要知道更多?要是有一个这样的 app 该有多好。现在,你可以用 ARKit 2 来自己制作一个带有图片/物体检测与追踪的 app。
为了让体验更加有趣,ARKit 允许 app 添加动态的虚拟内容到真实世界物体上。它允许我们为真实世界的地方和物品创建一个交互式的引导 app。是博物馆,画廊,游乐场和学校等地的完美配套 app。它可以让任何地方“活起来”,提供一个动态的或定制的体验。
在本教程中,你将构建一个TriassicLoupe(三叠纪放大镜),一个用在自然历史博物馆里恐龙展览的配套 app。这个概念来自珠宝商的放大镜;这个 app 会在用户指向展品的时候显示出隐藏的细节。如果你周围没有任何恐龙,请不要担心 - 你可以使用普通的家用物品作为占位。
最终应用程序在信息图像上显示一段简短的动画。它还会在复制品旁边显示有关恐龙的信息。该 app 还将为该物体添加一些可怕的声音效果。

该应用程序将 ARKit 与 SceneKit(iOS的3D图形框架)结合使用。你会看到 ARKit 使用 SceneKit 完成所有繁重的工作。对于图片追踪和物体追踪,您将只使用非常基本的 SceneKit 功能,本教程中您从中学到的所有内容都是通用的。了解有关 SceneKit 的更多信息将使您能够构建更丰富的应用程序,但这超出了本教程的范围。
开始
ARKit 依赖于A9或更高版本处理器的内置功能。它使用了机器学习,后置摄像头,以及视频和图像处理。这意味着 ARKit 应用程序需要在iPhone 6s或更新版本上运行,并且它们无法在模拟器中运行。
使用超长的Lightning线缆或者设置设备以通过 Wi-Fi 连接到Xcode方便调试。 ARKit 需要移动一点才能获得一张好的世界地图。世界地图是 ARKit 对物理空间的意识。它是一系列特征点,尺寸,方向和锚点。
稍后你会需要扫描一些图像。显示器上显示的图像应该也适用,但如果您在扫描图像时遇到问题,则可能需要打印图像以获得更好的效果。
要开始使用,请使用本教程顶部或底部的“下载材料”按钮下载入门项目。 .zip文件包含一个帮助项目,包含将在教程中使用的素材,以及初始项目和最终项目。
打开入门项目。应用程序本身非常简单,只需一个ViewController
即可添加所有逻辑。有一个辅助结构体,DinosaurFacts
,其中包含一些关于一些恐龙的基本信息。
如果你构建并运行,你会看到一个黑屏,因为你尚未连接ARKit会话。

创建图片检测
首先要做的是创建图片检测。图片检测可能是ARKit最简单的功能。要创建图片检测器,您所要做的就是提供带有图像副本的图像跟踪会话。这些提供的图像称为参考图片。
添加参考图片
TriassicLoupe 使用含有信息标志的艺术作品作为参考图像。当用户将应用程序指向其中一个标志时,该应用程序将添加恐龙图像叠加层。
与其他应用程序图像一样,增强现实(AR)参考图像存在于素材目录asset catalog中。参考图像有点特殊,因为它们需要专门为ARKit分组。
打开Assets.xcassets 点击下面的 + 按钮。
从弹出菜单中,选择New AR Resource Group以创建新组。将其重命名为AR Images,因为该组将保留参考图像。

在Finder中,从下载的材料中打开Dinosaur Images文件夹。将每个图像文件逐个拖动到Xcode中的AR Images中。完成后,您应该有三个带黄色警告三角形的图像。

如果参考图像作为参考质量不好,Xcode会发出警告。这可能是因为它们太小或者没有足够的特征或对比度。具有大量空白空间,颜色太少或缺乏独特形状的图像是难以检测的。
在这种情况下,警告是“不支持的配置”警告。这是因为参考图像必须具有非零的正宽度
。 AR参考图像需要您指定其实际尺寸!
在资产库中选择stegosaurus(剑龙)图像。然后选择Attributes inspector。
将单位更改为英寸。接下来,输入宽度4.15。当你这样做时,根据纵横比,高度将自动变为2.5711!这些数字就是您桥接虚拟世界和真实世界的地方。

这两张图片,配置值如下:
- trex:Inches, width: 6.3333, height: 4.75
- triceratops: Inches, width: 5, height: 2.8125
当你输入尺寸后,警告就消失了。

这些图像对应于所包含的Dinosaurs.key Keynote文件的幻灯片。每张幻灯片代表一个信息标语牌,旁边是博物馆展示。在美国信纸大小的纸张上打印时,这个尺寸就是物理图像尺寸。
注意:某些图像实际上是在Keynote幻灯片中裁剪出来的。只要保持大小和宽高比相同,ARKit 完全能够识别并匹配。
这些图像都是不同的风格,以展示ARKit系列的一小部分。这里有两件事情:1。图像中有足够的形状和对比度。 2.真实世界中的图片平坦,光线充足,不反光。
书页上,壁纸上或在镜相打印出的图片是难以识别的。照片,绘画或插图可以很好地识别出来。如果参考图片不够友好,Xcode会发出警告。这样就无需在运行时猜测!
现在,是时候继续编写代码来寻找这些图像了。
添加图片追踪
在ViewController.swift中,在注释下添加一个新变量:// Add configuration variables here:
private var imageConfiguration: ARImageTrackingConfiguration?
这将设置一个变量,以便在创建后保留图像跟踪配置。
现在,查找setupImageDetection()
并添加以下代码:
imageConfiguration = ARImageTrackingConfiguration()
这会将该实例变量设置为新的ARImageTrackingConfiguration
。顾名思义,此类是一个ARKit配置,用于检测和跟踪图像。
在该行下面,添加以下内容:
guard let referenceImages = ARReferenceImage.referenceImages(
inGroupNamed: "AR Images", bundle: nil) else {
fatalError("Missing expected asset catalog resources.")
}
imageConfiguration?.trackingImages = referenceImages
这将使用您刚刚在素材目录中创建的AR Images
组中的图像,创建一个ARReferenceImage
集。然后,将它们作为要跟踪的图像列表添加到配置中。
注意:图像检测最适用于资源组中不超过25个图片。如果您的博物馆有超过25个展品,您可以创建多个资源组,并在用户在建筑物周围移动时切换它们。
要使用配置,请将以下内容添加到viewWillAppear(_ :)
:
if let configuration = imageConfiguration {
sceneView.session.run(configuration)
}
这将使用imageConfiguration
启动ARKit会话。一旦运行,ARKit将处理相机数据以检测参考图片。
要确保全部启动,请将以下内容添加到viewDidLoad()
的底部:
setupImageDetection()
最后,为了平衡会话运行,在viewWillDisappear(_ :)
添加:
sceneView.session.pause()
当视图消失时,这会暂停会话。ARKit会话会因为相机调用,视频处理和渲染,而把电池耗尽。在我们的单视图应用程序中,这不是什么大问题,但是尊重用户的设备并在没有显示时暂停会话总是一个好主意。
处理检测到的图片
一旦检测到图像,AR会话就会将ARImageAncho
r添加到其世界地图中。当发生这种情况时,您将在渲染器处获得回调renderer(_:didAdd:for:)
。
在ViewController.swift的底部找到此函数并添加以下代码:
DispatchQueue.main.async { self.instructionLabel.isHidden = true }
if let imageAnchor = anchor as? ARImageAnchor {
handleFoundImage(imageAnchor, node)
}
此代码检查是否为图像锚点添加了新添加的节点。这意味着在现实世界中检测到图像。
将handleFoundImage(_:_:)
函数替换为:
let name = imageAnchor.referenceImage.name!
print("you found a \(name) image")
let size = imageAnchor.referenceImage.physicalSize
if let videoNode = makeDinosaurVideo(size: size) {
node.addChildNode(videoNode)
node.opacity = 1
}
这将从锚点的参考图片中获取图像的名称和大小。您在素材目录中指定了这些值。使用该尺寸,调用辅助函数以在检测到的图像之上创建视频播放器。
要创建视频节点,请将makeDinosaurVideo(size :)
的内容替换为:
// 1
guard let videoURL = Bundle.main.url(forResource: "dinosaur",
withExtension: "mp4") else {
return nil
}
// 2
let avPlayerItem = AVPlayerItem(url: videoURL)
let avPlayer = AVPlayer(playerItem: avPlayerItem)
avPlayer.play()
// 3
NotificationCenter.default.addObserver(
forName: .AVPlayerItemDidPlayToEndTime,
object: nil,
queue: nil) { notification in
avPlayer.seek(to: .zero)
avPlayer.play()
}
// 4
let avMaterial = SCNMaterial()
avMaterial.diffuse.contents = avPlayer
// 5
let videoPlane = SCNPlane(width: size.width, height: size.height)
videoPlane.materials = [avMaterial]
// 6
let videoNode = SCNNode(geometry: videoPlane)
videoNode.eulerAngles.x = -.pi / 2
return videoNode
此功能创建一个视频播放器并将其放入一个大小适合图像的SceneKit节点。它通过以下方式实现:
- 从资源包中抓取视频。这有一个适用于所有恐龙的简单动画。但您可以根据图像锚点的名称为每种恐龙类型提供不同的视频。
- 为该视频创建和启动
AVPlayer
。
- AVPlayer 实例并不会自动循环播放。此通知块通过侦听播放器完成来循环视频。然后, 它会返回开头并重新开始播放。
- SceneKit 不使用
UIViews
, 而是使用节点来渲染场景。不能直接添加AVPlayer
。相反, 视频播放器可以用作节点的纹理或 "材质"。这将把视频帧映射到关联的节点。
- 检测到的图像是平坦正方形 (即平面), 因此覆盖的节点是与检测到的图像大小相同的
SCNPlane
。这架飞机被装饰成视频作为其纹理。
- 创建出的实际节点将成为场景的一部分。这就需要在 x 轴上进行翻转, 以便它正确显示给用户。
尝试一下
最后的最后, 是时候构建并运行了!但是, 首先, 打印幻灯片Dinosaurs.key中至少一张恐龙。将其放置在光线充足的区域中 (垂直或水平).
构建并运行该应用程序。接受相机权限并显示视频后, 请将其指向打印页面。它可能需要两只稳定的手来检测图像。完成后, 您将在控制台中看到一个注释, 并在屏幕上显示一个动画叠加。

不幸的是, 如果会话启动, 但它没有检测到图像, 那也没有错误消息。大多数情况下, ARKit 不保证能找到该图像, 因此它不被视为错误。只要素材目录中没有关于图像的警告, 就应该最终检测到该图像。
添加物体检测和追踪
现在, 您已经看到了图像检测如何工作。接下来, 您将向应用添加物体检测。从开发人员的角度来看, 物体检测的工作原理几乎相同。主要区别在于它将寻找三维物体而不是平面图像。设置物体检测稍微复杂一些。参考物体的创建也比较复杂。
回顾一下, 以下是使用图像和物体检测的步骤:
- 创建参考对象。
- 将参考对象放入素材集的AR Resources组中。
- 创建一个 ARKit 会话。
- 加载参考图片/物体,并设置会话来检测他们。
- 启动 session.
- 等待锚点被添加时的回调。
- 添加交互节点到场景中,或采取其他措施。
物体检测
另一个有用的 ARKit 函数是物体检测和跟踪。TriassicLoupe 检测已知物体并标记它们。在现实中, 这些将是恐龙在一个透视或恐龙骨架。对于本教程, 您将使用手头上的任何东西。
选择参考物体
检测物体所需的第一件事是参考物体。通过图像检测, 您可以创建、扫描或拍摄图像。但是, 对于3D 对象, 参考物体很难构造.
ARKit 提供了自己的 API, 用于使用 iPhone 扫描它们来创建参考物体。TriassicLoupe 不直接使用此项, 因为它只能检测到一组已知的对象。您可以使用 Apple 提供的实用程序提前扫描它们。
如果可以, 您应该下载 Apple 的对象扫描程序项目Object Scanner project。它也包括在项目下载ScanningAndDetecting3DObjects文件夹中, 为您的方便。请注意, 在您阅读此内容时, 包含的项目可能已过期。
此应用程序扫描对象, 并允许您导出. arobject
文件。然后, 您可以将此文件作为素材导入到 Xcode 项目中。成功的扫描需要有合适的对象和良好的照明。适当的对象是: