【问题标题】:How do i detect multiple images in AR?如何在 AR 中检测多个图像?
【发布时间】:2019-04-27 13:59:52
【问题描述】:

我正在使用 ARKit 创建这个实时报纸应用程序,它将报纸上的图像转换为视频。我能够检测到一个图像并在其上播放视频,但是当我尝试在两个图像上执行此操作并在该图像上播放相应的视频时我收到一个错误 Attempted to add a SKNode which already has a parent

我尝试检查跟踪的图像并将它们与参考图像进行比较,但我认为我的逻辑有问题。

这是我的ViewDidAppear() 方法

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // Create a session configuration
    let configuration = ARImageTrackingConfiguration()

    if  let trackedImages = ARReferenceImage.referenceImages(inGroupNamed: "NewsPaperImages", bundle: Bundle.main) {

        configuration.trackingImages = trackedImages
        configuration.maximumNumberOfTrackedImages = 20



    }

    // Run the view's session
    sceneView.session.run(configuration)
}

func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
    let node = SCNNode()

    if let imageAnchor = anchor as? ARImageAnchor {

        if(imageAnchor.referenceImage == UIImage(named: "Image2_River")) {
            self.videoNode = SKVideoNode(fileNamed: "riverBeauty.mp4")
        }

        print("Yes it is an image")
        self.videoNode.play()

        let videoScene = SKScene(size: CGSize(width: 480, height: 360))

        videoNode.position = CGPoint(x: videoScene.size.width/2, y: videoScene.size.height/2)
        videoNode.yScale = -1.0
        videoScene.addChild(videoNode)

        let plane = SCNPlane(width: imageAnchor.referenceImage.physicalSize.width, height: imageAnchor.referenceImage.physicalSize.height)


        plane.firstMaterial?.diffuse.contents = videoScene

        let planeNode = SCNNode(geometry: plane)
        planeNode.eulerAngles.x = -.pi/2

        node.addChildNode(planeNode)

        }
    return node

}

它应该在每个检测到的图像上播放视频,但它却崩溃了。

【问题讨论】:

  • 好的,首先让我们看看ARImageResourcegroup。然后告诉我们您是否将 ARImageTrackingConfiguration 设置为读取多个图像,这可以通过更改来完成:configuration.maximumNumberOfTrackedImages = 10 必须声明此设置才能检测多个图像。
  • 最后请告诉我,当您检测到其他图像时,会导致您的代码在检测到单个图像时仅实例化 VideoNode,然后如果还检测到另一个图像,则 VideoNode 未实例化但实际上是玩过。
  • @KarloA.Lopez 请检查我编辑了我正在跟踪最多 20 张图像的代码。你能告诉我当检测到新图像时如何实例化另一个视频节点?
  • @KarloA.Lopez 哦,明白了,所以我创建了一些 if 语句来检查锚点的名称。并且根据检测到的锚点,我通过实例化视频节点来播放相应的视频。感谢您的帮助。

标签: ios swift augmented-reality arkit


【解决方案1】:

查看您的代码,根据您所说的,我认为您需要更改逻辑,以使用 ARReferenceImagename 属性创建视频节点。

当您静态(在ARResourceBundle 内)或动态创建ARReferenceImage 时,您可以为其指定一个名称,例如:

然后,您可以使用名称添加逻辑,为检测到的每个 referenceImage 分配不同的视频。

为了保留您的代码DRY,您可以创建一个可重用的函数来创建您的视频节点。

这样一个简单的例子可能看起来像这样:

  //-------------------------
  //MARK: - ARSCNViewDelegate
  //-------------------------

  extension ViewController: ARSCNViewDelegate{

    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

      //1. Check We Have Detected An ARImageAnchor
      guard let validAnchor = anchor as? ARImageAnchor else { return }

      //2. Create A Video Player Node For Each Detected Target
      node.addChildNode(createdVideoPlayerNodeFor(validAnchor.referenceImage))

    }


    /// Creates An SCNNode With An AVPlayer Rendered Onto An SCNPlane
    ///
    /// - Parameter target: ARReferenceImage
    /// - Returns: SCNNode
    func createdVideoPlayerNodeFor(_ target: ARReferenceImage) -> SCNNode{

      //1. Create An SCNNode To Hold Our VideoPlayer
      let videoPlayerNode = SCNNode()

      //2. Create An SCNPlane & An AVPlayer
      let videoPlayerGeometry = SCNPlane(width: target.physicalSize.width, height: target.physicalSize.height)
      var videoPlayer = AVPlayer()

      //3. If We Have A Valid Name & A Valid Video URL The Instanciate The AVPlayer
      if let targetName = target.name,
        let validURL = Bundle.main.url(forResource: targetName, withExtension: "mp4", subdirectory: "/art.scnassets") {
        videoPlayer = AVPlayer(url: validURL)
        videoPlayer.play()
      }

      //4. Assign The AVPlayer & The Geometry To The Video Player
      videoPlayerGeometry.firstMaterial?.diffuse.contents = videoPlayer
      videoPlayerNode.geometry = videoPlayerGeometry

      //5. Rotate It
      videoPlayerNode.eulerAngles.x = -.pi / 2

      return videoPlayerNode

    }

  }

如您所见,我选择使用AVPlayer 作为我的视频内容,但如果您愿意,您可以继续使用您的 videoScene。

希望它为您指明正确的方向...

【讨论】:

    猜你喜欢
    • 2014-01-15
    • 2021-06-26
    • 2023-03-06
    • 1970-01-01
    • 2021-01-15
    • 2012-07-07
    • 1970-01-01
    • 2020-04-09
    • 2020-04-21
    相关资源
    最近更新 更多