如何使用 ARFaceAnchor 和 RealityKit 检查人脸是否完全可见且位于屏幕中央?

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

我正在使用 ARKit 和 RealityKit 以及 ARFaceAnchor 对象。我想确保该人的脸部靠近或靠近设备屏幕中心椭圆的边界。

我不知道如何获取脸部的尺寸,例如 minX/maxX 和 minY/maxY,以及如何将这些值转换为屏幕的坐标,特别是椭圆形状所在的位置。

谁能指出解决方案吗?

enter image description here

ios augmented-reality arkit realitykit arfacegeometry
1个回答
0
投票

我在我的一个应用程序中实现了类似的方法来跟踪用户的面部。我将它用于

ARSCNView
SceneKit
,但它也应该适用于
ARView
RealityKit
(可能你需要做一些小的调整)

实现这一点并使其适应您的逻辑。

该功能打印出每一帧的面部位置。然后,您可以实施一些边界检查或其他任何措施来保持面部居中,或提醒用户靠近中心。

extension ViewController {
    func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) {
        guard let faceAnchor = anchors.first as? ARFaceAnchor else { return }
        checkFacePosition(faceAnchor: faceAnchor)
    }

    private func checkFacePosition(faceAnchor: ARFaceAnchor) {
        guard let frame = arSession.currentFrame else { return }

        // Combine the camera's transform with the face transform
        let faceTransform = faceAnchor.transform
        let cameraTransform = frame.camera.transform
        let combinedTransform = cameraTransform.inverse * faceTransform

        // Extract the face's translation (position relative to the camera)
        let translation = combinedTransform.columns.3

        // Normalize offsets using a reference distance
        let referenceDistance: Float = 0.5
        let xOffset = translation.y / referenceDistance // Flip x/y to match screen orientation
        let yOffset = translation.x / referenceDistance

        // Define thresholds for an ellipse (values can be adjusted)
        let ellipseWidth: Float = 0.2 // Adjust for the horizontal size of the ellipse
        let ellipseHeight: Float = 0.3 // Adjust for the vertical size of the ellipse

        // Check if the face is within the ellipse bounds
        let isInsideEllipse = pow(xOffset, 2) / pow(ellipseWidth / 2, 2) + pow(yOffset, 2) / pow(ellipseHeight / 2, 2) <= 1.0

        // Log the result
        if isInsideEllipse {
            print("Face is inside the ellipse: xOffset: \(xOffset), yOffset: \(yOffset)")
        } else {
            print("Face is outside the ellipse: xOffset: \(xOffset), yOffset: \(yOffset)")
        }
    }
}

这是控制台记录器的一些打印输出:

Face is outside the ellipse: xOffset: 0.026052857, yOffset: -0.2010466
Face is outside the ellipse: xOffset: 0.018577524, yOffset: -0.18251653
Face is outside the ellipse: xOffset: 0.009894665, yOffset: -0.16267225
Face is inside the ellipse: xOffset: 0.0024384973, yOffset: -0.13900988
Face is inside the ellipse: xOffset: 0.002202771, yOffset: -0.11147189
Face is inside the ellipse: xOffset: 0.008226621, yOffset: -0.08980697

您可以通过使用

ARKit
引擎设置默认的
SceneKit
项目来快速查看它。然后用该代码替换您的
ViewController

场景套件解决方案

class ViewController: UIViewController, ARSCNViewDelegate, ARSessionDelegate {

    @IBOutlet var sceneView: ARSCNView!
    private var arSession: ARSession {
        return sceneView.session
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set the view's delegate
        sceneView.delegate = self
        sceneView.session.delegate = self

        // Show statistics such as fps and timing information
        sceneView.showsStatistics = true

        // Create a new scene
        let scene = SCNScene()

        // Set the scene to the view
        sceneView.scene = scene
    }

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

        // Create a session configuration
        guard ARFaceTrackingConfiguration.isSupported else {
            print("ARFaceTracking is not supported on this device.")
            return
        }

        let configuration = ARFaceTrackingConfiguration()
        configuration.isLightEstimationEnabled = true // Enable light estimation if needed

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

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

        // Pause the view's session
        sceneView.session.pause()
    }

    // MARK: - ARSCNViewDelegate (Optional Node Configuration)

    func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
        guard anchor is ARFaceAnchor else { return nil }

        // Return a new node for face anchor (optional for visualization)
        let node = SCNNode()
        node.geometry = SCNSphere(radius: 0.02)
        node.geometry?.firstMaterial?.diffuse.contents = UIColor.red
        return node
    }

    func session(_ session: ARSession, didFailWithError error: Error) {
        // Present an error message to the user
        print("ARSession failed with error: \(error.localizedDescription)")
    }

    func sessionWasInterrupted(_ session: ARSession) {
        // Inform the user that the session has been interrupted
        print("ARSession was interrupted.")
    }

    func sessionInterruptionEnded(_ session: ARSession) {
        // Reset tracking if consistent tracking is required
        print("ARSession interruption ended.")
    }
}

我希望这能帮助您实现您正在寻找的目标,或者至少为您指明某个方向。

© www.soinside.com 2019 - 2024. All rights reserved.