ARKit 2简介—图像跟踪

上一个WWDC,iOS 12与ARKit 2一起发布。最初的ARKit于去年与iOS 11一起发布-它允许开发人员使用本机iOS框架将AR添加到其应用程序中,并使用户可以使用它。 借助ARKit 2,新的功能被添加到框架中,从而将体验带到了另一个层次。 诸如图像跟踪,世界地图,对象扫描, 视觉集成以及金属和反射表面之类的东西是其最新版本最令人期待的功能。

由于这只是第一部分,因此我将从图像跟踪开始,并随着我们的前进继续探讨其余所有主题。 这是集合的列表,随着我们的进行,它将更新:

  1. 影像追踪
  2. 世界地图
  3. 物体扫描
  4. 视觉整合(即将推出)
  5. 金属和反射性表面(即将推出)

就个人而言,图像跟踪是ARKit 2的最佳功能。 它允许开发人员将图像上传到他们的应用程序中,例如从相框中上传照片,然后可以在使用该应用程序时实时识别这些图片并在其上执行某些操作-例如在其顶部放置3D模型。

在WWDC的示例中,演示者使用了他的猫的相框。 他将图像作为ARReferenceImage上传到应用程序。 然后,您可以在应用程序中这样定义它:

  //定义一个变量来保存所有参考图像,  referenceImages = ARReferenceImage .referenceImages(inGroupNamed:“ AR Resources”,bundle:Bundle.main) 

这将收集您放置在资产文件夹的AR资源文件夹中的所有参考图像。

接下来,我们必须配置我们的AR会话。 我们通过设置实例化ARImageTrackingConfiguration 除此之外,您还必须设置其trackingImages属性以及maximumNumberOfTrackedImages 属性。 第二个属性使应用程序知道该应用程序“允许”同时跟踪多少图像-通常取决于您打算对应用程序使用什么来决定。 这是一个例子:

  //创建会话配置 let配置= ARImageTrackingConfiguration () 配置 .trackingImages = referenceImages 配置 .maximumNumberOfTrackedImages = 1 
//运行视图的会话 sceneView .session.run(configuration)

恭喜你! 您的应用程序现在将自动跟踪您告诉它的图像。 从那里开始,我们使用renderer( _ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? 函数确定当应用程序实际识别参考图像之一时该怎么做。 在运行场景的每个帧处调用此函数。

我们将通过一个示例说明如何利用该功能和图像跟踪。


在此示例中,我们将利用图像跟踪将相框上的照片转换为实时视频-这是一个非常基本的示例,甚至在WWDC中也使用过。

首先,我们必须创建一个AVPlayer ,它仅允许您的应用播放视频。 首先,下载视频,然后将其添加到资产文件夹。 然后,将此代码添加到viewDidLoad()上方:

  //加载视频并创建视频播放器 let videoPlayer:AVPlayer = { //从捆绑包 保护中 加载猫视频 let url = Bundle.main.url(forResource:“ video”,withExtension:“ mp4”) else {print(“无法查找视频文件。“) return AVPlayer()} return AVPlayer(url:url)}() 

确保将forResource下的视频名称更改为您的视频名称,并将withExtension属性更改为您的视频扩展名。

之后,如前所述设置您的参考映像和配置。 在这种情况下,参考图像应该是视频本身的静止图像。 例如,如果它是一枚火箭起飞的视频,则该图像可能是仍然停靠的一帧。

设置完所有内容后,您必须设置renderer( _ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? 功能,使应用程序可以对识别图像做出反应-这使您可以处理图像,并在出现图像时执行所需的操作。

我将向您介绍我们的功能及其内容:

由于该函数必须返回SCNNode ,因此我们必须声明最后要返回的空节点:

  节点= SCNNode() 

然后,我们检查该帧返回的锚点是否确实是图像锚点。 我们使用if let语句来做到这一点。

在声明(仅在确认为图像锚点后才会运行)的语句中,我们创建一个具有锚点物理尺寸的尺寸的SCNPlane ,这实际上意味着现实生活中图像的尺寸。 这样,该节点将采用其标识的原始图像的完整大小(高度和宽度),并将其完全覆盖。

  平面= SCNPlane(宽度:imageAnchor.referenceImage.physicalSize.width,高度:imageAnchor.referenceImage.physicalSize.height) 

然后,将飞机的材质内容设置为我们先前设置的videoPlayer。 此时,我们将播放视频播放器本身。

  plane.firstMaterial?.diffuse.contents = videoPlayer 自身 .videoPlayer.play() 

然后,我们使用刚创建的平面的几何图形创建另一个SCNNode ,称为planeNode。

   planeNode = SCNNode(geometry:plane) 

最后,我们设置eulerAngles.x属性,然后将其作为子节点添加到在if let之前声明的原始空SCNNode上。 声明。

  planeNode.eulerAngles.x = -.pi / 2node.addChildNode(planeNode) 

最后要做的就是按照功能期望返回节点。

  返回节点 

这是一劳永逸的渲染功能:

  func renderer( _ renderer:SCNSceneRenderer,nodeFor锚点:ARAnchor)-> SCNNode?  { 节点= SCNNode() 如果  imageAnchor =锚定 ?  ARImageAnchor { 
let plane = SCNPlane(width:imageAnchor.referenceImage.physicalSize.width,height:imageAnchor.referenceImage.physicalSize.height)plane.firstMaterial?.diffuse.contents = videoPlayer
自我 .videoPlayer.play()
planeNode = SCNNode(geometry:plane)
planeNode.eulerAngles.x = -.pi / 2
node.addChildNode(planeNode)} 返回节点}

而已! 可能性是无止境! 这是某人在Twitter上发布的一个很酷的示例:https://twitter.com/robomex/status/1007006956622630913

玩得开心!