ios - 在 iOS 中使用相机检测对象并使用 ARKit 定位 3D 对象

标签 ios swift scenekit augmented-reality arkit

我在寻找什么?

我的要求的简单解释是这样的

  1. 使用 ARKit,使用 iPhone 摄像头检测物体
  2. 找到这个对象在这个虚拟空间中的位置
  3. 使用 SceneKit 在这个虚拟空间中放置一个 3D 对象。 3D对象应该在后面 标记。

一个例子是使用相机检测 3D 空间中的小图像/标记位置,在虚拟空间中将另一个 3D 球模型放置在该标记后面(这样球将对用户隐藏,因为标记/图像位于前面)

到目前为止我能做什么?

  1. 我能够使用 ARKit 检测标记/图像
  2. 我能够在屏幕上定位球的 3D 模型。

我的问题是什么?

我无法以球位于检测到的标记后面的方式定位球。

当球在标记前面时,球正确地隐藏了标记。您可以在侧 View 中看到球在标记的前面。见下文

enter image description here

但是当球在标记后面时,不会发生相反的情况。球总是在前面阻挡标记。我希望记分员能把球藏起来。所以场景不尊重球位置的 z 深度。见下文

enter image description here

代码

也请看评论

override func viewDidLoad() {
    super.viewDidLoad()

    sceneView.delegate = self
    sceneView.autoenablesDefaultLighting = true

    //This loads my 3d model.
    let ballScene = SCNScene(named: "art.scnassets/ball.scn")
    ballNode = ballScene?.rootNode

    //The model I have is too big. Scaling it here.
    ballNode?.scale = SCNVector3Make(0.1, 0.1, 0.1)
}

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

    //I am trying to detect a marker/image. So ImageTracking configuration is enough
    let configuration = ARImageTrackingConfiguration()

    //Load the image/marker and set it as tracking image
    //There is only one image in this set
    if let trackingImages = ARReferenceImage.referenceImages(inGroupNamed: "Markers",
                              bundle: Bundle.main) {
        configuration.trackingImages = trackingImages
        configuration.maximumNumberOfTrackedImages = 1
    }

    sceneView.session.run(configuration)
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    sceneView.session.pause()
}


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

    if anchor is ARImageAnchor {
        //my image is detected
        if let ballNode = self.ballNode {

            //for some reason changing the y position translate the ball in z direction
            //Positive y value moves it towards the screen (infront the marker)
            ballNode.position = SCNVector3(0.0, -0.02, 0.0)

            //Negative y value moves it away from the screen (behind the marker)
            ballNode.position = SCNVector3(0.0, -0.02, 0.0)
            node.addChildNode(ballNode)
        }
    }

    return node
}

如何使场景尊重 z 位置?或者换句话说,如何在使用 ARKit 框架检测到的图像/标记后面显示 3D 模型?

我正在使用 Xcode 10.3 针对 iOS 12 运行。让我知道是否需要任何其他信息。

最佳答案

为此,您需要在 3D 场景中创建遮挡物。由于 ARReferenceImage 具有 physicalSize,因此在创建 ARImageAnchor 时在场景中添加几何应该很简单。

几何体将是一个 SCNPlane 和一个适合遮挡物的 SCNMaterial。我会选择 SCNLightingModelConstant 光照模型(它是最便宜的,我们实际上不会绘制平面),其 colorBufferWriteMask 等于 SCNColorMaskNone。该对象应该是透明的,但仍写入深度缓冲区(这就是它充当遮挡物的方式)。

最后,通过将遮挡物的 renderingOrder 设置为 -1(如果应用已经使用渲染顺序,则可以设置更低的值),确保遮挡物在任何增强对象之前渲染).

关于ios - 在 iOS 中使用相机检测对象并使用 ARKit 定位 3D 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58995442/

相关文章:

ios - Cocoapods 错误 : 'Unable to read the license file'

swift - “方法”在这种情况下对于类型查找不明确,Alamofire 中的错误

swift - 尝试在 Realm 对象上使用 setValue forKey 的问题

ios - 如何在 RXSwift 中重置 Observable 间隔运算符?

ios - ARKit - ARAnchor 到 2D 空间的投影

ios - 今天扩展中复制的主要应用程序 Assets 目录

iphone - 登录和注册错误 3840

ios - 我可以使用 PNG 序列作为 SceneKit 对象上的动画 Material 吗?

ios - 如何让场景套件中的光节点始终位于人的正上方?

ios - iOS URL方案或不存在的通用链接