我搜索了所有文档,可能只是遗漏了一些非常重要的内容。前置原深度摄像头是否可以像 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 空间中两点之间的距离,但使用前置摄像头而不是后置摄像头。
谢谢你让我明白了!我很感激。
很明显,用于基于世界跟踪配置检测到的平面的 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()