ARRaycastQuery 和前置摄像头(ARFaceTrackingConfiguration)

问题描述 投票:0回答:1

我搜索了所有文档,可能只是遗漏了一些非常重要的内容。前置原深度摄像头是否可以像 iPad Pro 一样使用光线投射?

我目前正在开发一个应用程序,我在 ARFaceTrackingConfiguration 中,并且来自屏幕中心的简单光线投射没有产生结果。

使用后置摄像头的世界配置中的相同代码正在产生结果。该代码直接来自文档。

let raycastQuery: ARRaycastQuery? = sceneView.raycastQuery(
                                                      from: sceneView.center,
                                                  allowing: .estimatedPlane,
                                                 alignment: .any)

let rayresults: [ARRaycastResult] = sceneView.session.raycast(raycastQuery!)
print(rayresults)

根据有关背景模糊的面部跟踪深度图的示例,我的理解是,前置摄像头将具有与后置摄像头基本相同的深度数据,只是可用的总深度距离较少。

由于此代码返回后置摄像头的结果集,但不返回前置摄像头的结果,我想知道这是否是由于光线方向的原因?对于前置摄像头,如果支持rayCast,可能需要将光线投射到负z方向?但我在那里还没有取得成功。

该项目的目标是能够获得 3D 空间中两点之间的距离,但使用前置摄像头而不是后置摄像头。

谢谢你让我明白了!我很感激。

swift scenekit arkit
1个回答
0
投票

ARFaceTrackingConfig 的命中测试

很明显,用于基于世界跟踪配置检测到的平面的 ARKit 光线投射方法不适用于面部跟踪场景。在您的情况下,您需要使用 SceneKit 的命中测试。对于命中测试,您将无法使用

estimatedPlane
,您需要
canonical face mask
。使用前置摄像头时,您对 XZ 坐标的理解是绝对正确的 - XZ 平面是镜像

在 iPad Pro 上的 Swift Playgrounds 应用程序中运行此代码。

import ARKit
import SceneKit
import PlaygroundSupport

class ViewController : UIViewController {
    var sceneView = ARSCNView(frame: .zero)
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view = self.sceneView
        sceneView.delegate = self
        sceneView.scene = SCNScene()
        
        let config = ARFaceTrackingConfiguration()
        config.maximumNumberOfTrackedFaces = 1
        sceneView.session.run(config)
    }
}

extension ViewController {       
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let location: CGPoint? = touches.first?.location(in: sceneView)
                                            
        var hitTestOptions = [SCNHitTestOption: Any]()
        hitTestOptions[.boundingBoxOnly] = true
                                            
        let hitTestResults: [SCNHitTestResult] = sceneView.hitTest(location!, 
                                                   options: hitTestOptions)
                    
        guard let hit = hitTestResults.first else { return }
                                        
        let sphere = SCNNode(geometry: SCNSphere(radius: 0.005))
        sphere.simdPosition = hit.simdWorldCoordinates
        sceneView.scene.rootNode.addChildNode(sphere)            
    }
}

extension ViewController : ARSCNViewDelegate {
    func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
        let faceGeo = ARSCNFaceGeometry(device: sceneView.device!)
        let node = SCNNode(geometry: faceGeo)
        node.geometry?.firstMaterial?.lightingModel = .physicallyBased
        node.geometry?.firstMaterial?.diffuse.contents = UIColor.green
        return node
    }
    func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode,
                                                    for anchor: ARAnchor) {    
        if let faceAnchor = anchor as? ARFaceAnchor,
           let faceGeo = node.geometry as? ARSCNFaceGeometry {
            faceGeo.update(from: faceAnchor.geometry)
        }
    }
}

PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = ViewController()
© www.soinside.com 2019 - 2024. All rights reserved.