到目前为止,您可能已经在iPhone上使用了增强现实应用程序,虚拟对象看上去栩栩如生,并与环境特征完美融合。 在本系列中,您将学习如何通过环境光检测和水平面检测在自己的iOS应用中实现此功能,从而改善增强现实应用。 本教程将重点介绍如何在ARKit中显示水平面和特征点。
通常,在使用增强现实时,您希望将虚拟对象放置在平面上,例如桌子,桌子,甚至地面上。 为了准确地执行此操作,重要的是您能够在开始之前检测到这些对象。 在检测到飞机之后,该对象将使用一系列点将您的虚拟对象锚定到该对象上,即使您四处移动设备,该对象也将保留在其中。
入门
Xcode版本
在开始之前,请确保您的Mac上安装了最新版本的Xcode。 这非常重要,因为ARKit仅在Xcode 9或更高版本上可用。 您可以通过打开Xcode并转到上方工具栏中的Xcode > 关于Xcode来检查您的版本。
如果您的Xcode版本早于Xcode 9,则可以转到Mac App Store并免费进行更新。 如果您还没有Xcode,也可以免费下载并安装。
样例项目
新项目
在确定具有正确版本的Xcode之后,您需要创建一个新的Xcode项目。
继续并打开Xcode,然后单击“ 创建新的Xcode项目”。
您可能习惯制作单视图应用程序, 但在本教程中,您将需要选择一个增强现实应用程序 。 然后单击“ 下一步”。
游戏框架
您可以根据自己的喜好为项目命名,但我将命名为“ 飞机检测”。 您还将注意到,底部有一个选项,您可以从其中选择SceneKit,SpriteKit和Metal。
这些都是Apple的游戏框架,在本教程中,我们将使用SceneKit,因为我们将使用3D对象。
继续并选择SceneKit(如果尚未选择)。 您的屏幕应如下所示:
准备测试
连接iPhone
由于Xcode Simulator没有相机,因此您需要插入iPhone。 不幸的是,如果您没有iPhone,则需要借用一本才能随本教程一起使用(以及与其他任何与相机相关的应用程序)。 如果您已经将iPhone连接到Xcode,则可以跳到下一步。
Xcode 9中的一个令人讨厌的新功能是您可以在设备上无线调试应用程序,因此让我们花点时间现在进行设置:
在顶部菜单栏中,选择“ 窗口” >“ 设备和模拟器”。 在出现的窗口中,确保在顶部选择了设备 。
现在,使用避雷线插入设备。 这应该使您的设备出现在“ 设备和模拟器”窗口的左窗格中。 只需单击您的设备,然后选中通过网络连接框。
现在,您将可以在所有未来的应用程序的iPhone上进行无线调试。
完成设定
现在您的设置完成。 您应该有一个运行良好的ARKit应用程序,并且可以在刚刚连接的iPhone上对其进行测试。 在Xcode左上方的“ 运行”和“ 停止”按钮旁边,选择 模拟器下拉菜单中的设备。 我已经选择了Vardhan的iPhone,但是您需要选择特定的设备。
现在,您已经完成了创建入门项目的工作,单击“运行”后 ,您应该会看到虚拟飞船出现在您的世界中。 它应该是这样的:
理论上
在我们开始对该应用程序进行实际编程之前,了解ARKit如何实际检测这些平面非常重要。 在本教程中,我们将探讨两个主要概念:特征点和水平面。 简而言之,iPhone上的增强现实与称为视觉惯性测距 (VIO)的过程配合使用,该过程从相机和内部传感器获取数据以对场景进行3D理解。
特征点
那么,特征点到底是什么? 每个图像自然都具有其独特的功能。 例如,在一朵花中,将具有独特的形状,或者在地毯上,将具有独特的纹理。
这些点代表在相机图像中检测到的显着特征。 它们在3D世界坐标空间中的位置被推断为ARKit执行的图像分析的一部分,以便准确跟踪设备的位置,方向和运动。 总而言之,这些点从摄像机的角度松散地与实际对象的轮廓相关。 - 苹果
正如Apple文档所解释的那样,功能点可帮助您的设备(和ARKit)了解世界的深度和“真实感”,从而使增强现实更加准确。 这些也可用于为虚拟对象提供固定的位置,以帮助他们了解在移动设备时应保留的位置。
水平平面
与特征点相似,水平面可以帮助您的应用感知周围环境。 毫不奇怪,特征点和水平面非常紧密地耦合在一起,因为没有特征点就无法检测到这些平面。
使用iPhone的内置传感器(当然包括相机)和这些特征点的组合,ARKit可以检测场景中的各种平面。 这些计算和估计每帧进行一次,并且可以一次检测到多个平面。
当您运行启用了planeDetection选项的世界跟踪AR会话时,该会话会自动将ARKit使用后置摄像头检测到的每个平面的ARPlaneAnchor对象添加到其锚列表中。 每个平面锚提供有关估计的表面位置和形状的信息。 - 苹果
在代码中
大! 现在,您已经可以使用ARKit应用程序了。 该应用程序的目标是能够检测到水平面并通过特征点(放置在ARKit场景中的虚拟点)对其进行可视化。
入门代码
您现在已经对什么是特征点和水平面有了深刻的了解,并且现在可以开始将它们编程到应用程序中了。 如果您想要更多有关特征点和水平面的背景知识,建议阅读Apple的文档 。
准备项目
由于很多代码都是样板代码,因此我们将其保留下来,但是对于宇宙飞船,让我们通过删除处理其放置位置的代码来摆脱它。 在ViewController.swift文件的viewDidLoad()
方法中, 删除以下代码行:
let scene = SCNScene(named: "art.scnassets/ship.scn")!
sceneView.scene = scene
特征点
启用调试选项
您的Xcode项目现在可以开始工作了。 我们的第一步是添加可见特征点。 您可能不会在生产应用程序中看到它们,但这是调试增强现实应用程序的绝佳功能。
此步骤非常简单,可以一行完成。 在您的viewDidLoad()
方法中,添加以下代码行:
sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints]
此代码使用一系列选项配置调试选项。 您可以通过将其他特征添加到此数组中来启用它们,但是目前,我们只需要显示特征点即可。 这是您运行应用程序时的外观:
如您所见,所有检测到的特征点都是可见的。 如果看不到它们,请尝试移动iPhone,您应该会看到黄点出现。 它们没有立即出现的部分原因是ARKit仍在检测场景。
组态
现在,我们准备进行飞机检测。 如果您查看viewWillAppear()
方法,将看到以下两行代码。 让我们花一点时间来了解它们的含义,因为它们与飞机检测相关。
let configuration = ARWorldTrackingConfiguration()
sceneView.session.run(configuration)
在这里,创建了ARWorldTrackingConfiguration
类的实例。 此类负责设备定位。 之后,我们在当前的sceneView
会话上运行配置。 如果您想了解更多有关此的信息,可以访问Apple的文档 。 不过,到目前为止,您已经准备好继续下一步。
现在,让我们在ARWorldTrackingConfiguration
上启用平面检测。 在创建配置的行下方,您需要插入以下行:
configuration.planeDetection = .horizontal
优秀的! 现在,启用了水平平面检测,但是我们看不到它,因为它发生在引擎盖下,这意味着iPhone知道该平面在哪里,但是我们看不到它的想法。
平面检测
检查锚点
在开始可视化检测到的平面之前,我们需要找出检测平面的时间和位置。 这可以通过Apple提供给我们的委托方法轻松完成。
首先,为ARSCNViewDelegate
声明一个方法,如您所见, ViewController
类已经在入门代码中符合该委托。 将以下委托方法粘贴到您的ViewController
类中:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
// Your code goes here
}
当新的ARAnchors
添加有一个相应的节点时(在这种情况下,这将是我们的水平面),将调用此方法。
告诉对应于新的AR锚SceneKit节点已经被添加到scene.-委托苹果
平面几何
但是,对于大多数应用程序,您希望用户能够说出您的应用程序认为它在哪里发现了水平面,因此我们将学习如何使用委托中提供的节点和锚点向用户实际显示这些平面。我们之前调用的方法。
我们的第一个问题是: ARAnchor
真的是一架飞机,还是我们不想要的东西? 我们可以使用类型转换和可选绑定进行检查。 将以下代码行放入您的委托方法中:
if let anchor = anchor as? ARPlaneAnchor {
// Your code goes here
}
您可能已经注意到anchor
参数的类型为ARAnchor
。 如果我们想知道此锚点是否为平面,可以尝试将其键入为ARPlaneAnchor
。 如果成功,我们知道已经检测到飞机。
在可选的绑定语句中,让我们添加代码以创建一个SCNPlane
,其尺寸是从委托方法接收到的锚的尺寸。 编写以下两行代码:
let plane = SCNPlane(width: CGFloat(anchor.extent.x), height: CGFloat(anchor.extent.z))
plane.materials.first?.diffuse.contents = UIColor.red.withAlphaComponent(0.5)
这里的第一行创建一个二维SCNPlane
,该二维SCNPlane
在其构造函数中带有两个参数:width和height。 您会看到我们传入了anchor.extent.x
和anchor.extent.z
,正如其名称所暗示的那样,它们表示检测到的平面的宽度和高度。 您会注意到,我们省略了锚点的y值,这是因为我们要检测的平面是二维的,并且x和z轴横穿我们正在识别的平面。
下一行代码将半透明的红色色调应用于这些检测到的平面,由于alpha值设置为0.5,因此您可以透视这些平面。 当然,只要您能够看到它们,就可以使用任何颜色或外观。
创建节点
我们还没有完成; 我们仍然需要创建要添加到视图的节点。 尽管我们的平面是一个二维对象,但我们仍然需要用x,y和z坐标以3D形式表示它。 这些坐标将相对于检测到的平面锚的父节点,而不是sceneView
。 输入以下代码行:
let planeNode = SCNNode(geometry: plane)
planeNode.position = SCNVector3(CGFloat(anchor.center.x), CGFloat(anchor.center.y), CGFloat(anchor.center.z))
planeNode.eulerAngles.x = -.pi / 2
node.addChildNode(planeNode)
我们首先使用上一步中创建的SCNNode
来创建一个SCNNode
。 这是通过将几何作为SCNNode
的构造函数的参数SCNNode
来完成的。
接下来,我们使用三维平面中x,y和z坐标的SCNVector3
表示将平面节点直接定位在平面锚点的中心。
另外,在下一行中,您会看到eulerAngles
的x
值设置为-π/2
。 该物业eulerAngles
代表俯仰,偏航和轧辊SCNNode
。 根据Apple的文档,x值表示间距(或围绕x轴的旋转),我们希望我们的平面相对于平面是平坦的(而不是垂直固定)。
最后,将新创建的节点添加为检测到的平面节点的子节点,以使其在相同位置对用户可见。
结论
很好! 现在,当您在iPhone上运行应用程序时,您应该能够看到水平面(当然还有特征点)。 如果不这样做,请确保缓慢移动手机以扫描表面,并尝试增加我们之前设置的颜色的Alpha值。 这是我的样子:
翻译自: https://code.tutsplus.com/tutorials/augmented-reality-with-arkit-feature-points-and-horizontal-plane-detection--cms-30839