【问题标题】:How to apply a 3D Model on detected face by Apple Vision "NO AR"如何在 Apple Vision “NO AR” 检测到的面部上应用 3D 模型
【发布时间】:2019-10-09 21:06:28
【问题描述】:

使用 iPhoneX True-Depth 摄像头可以获得任何对象的 3D 坐标并使用该信息来定位和缩放对象,但是对于较旧的 iPhone,我们无法使用前置摄像头上的 AR,我到目前为止,我们所做的是使用 Apple Vison 框架检测人脸并在人脸或地标周围绘制一些 2D 路径。 我制作了一个 SceneView 并将其应用为具有清晰背景的 My view 的前层,在其下方是 AVCaptureVideoPreviewLayer ,在检测到我的面部后,我的 3D 对象出现在屏幕上但是根据面部boundingBox正确定位和缩放它需要取消投影和其他我卡在那里的东西,我也尝试使用CATransform3D将2D BoundingBox转换为3D但我失败了!我想知道我想要实现的目标是否可能?如果我没记错的话,我记得 SnapChat 在 iPhone 上推出 ARKit 之前就已经这样做了!

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(self.sceneView)

        self.sceneView.frame = self.view.bounds
        self.sceneView.backgroundColor = .clear
        self.node = self.scene.rootNode.childNode(withName: "face", 
        recursively: true)!

    }

    fileprivate func updateFaceView(for result: 
    VNFaceObservation, twoDFace: Face2D) {
        let box = convert(rect: result.boundingBox)
        defer {
            DispatchQueue.main.async {
                self.faceView.setNeedsDisplay()
            }
        }

        faceView.boundingBox = box
        self.sceneView.scene?.rootNode.addChildNode(self.node)

        let unprojectedBox = SCNVector3(box.origin.x, box.origin.y, 
        0.8)

        let worldPoint = sceneView.unprojectPoint(unprojectedBox)

         self.node.position = worldPoint 
        /* Here i have to to unprojecting 
         to convert the value from a 2D point to 3D point also 
         issue here. */
    }

【问题讨论】:

    标签: swift xcode 3d face-detection apple-vision


    【解决方案1】:

    实现这一点的唯一方法是使用带有正交相机的 SceneKit 并使用 SCNGeometrySource 将来自 Vision 的地标与网格的顶点进行匹配。 首先,您需要具有相同数量的 Vision 顶点的网格(66 - 77,具体取决于您所在的 Vision Revision)。您可以使用 Blender 之类的工具创建一个。

    The mesh on Blender

    然后,在代码上,每次处理地标时,您都执行以下步骤: 1-获取网格顶点:

    func getVertices() -> [SCNVector3]{
            var result = [SCNVector3]()
            let planeSources = shape!.geometry?.sources(for: SCNGeometrySource.Semantic.vertex)
            if let planeSource = planeSources?.first {
                let stride = planeSource.dataStride
                let offset = planeSource.dataOffset
                let componentsPerVector = planeSource.componentsPerVector
                let bytesPerVector = componentsPerVector * planeSource.bytesPerComponent
                let vectors = [SCNVector3](repeating: SCNVector3Zero, count: planeSource.vectorCount)
                //   [SCNVector3](count: planeSource.vectorCount, repeatedValue: SCNVector3Zero)
                let vertices = vectors.enumerated().map({
                    (index: Int, element: SCNVector3) -> SCNVector3 in
                    var vectorData = [Float](repeating: 0, count: componentsPerVector)
                    let byteRange = NSMakeRange(index * stride + offset, bytesPerVector)
    
                    let data = planeSource.data
                    (data as NSData).getBytes(&vectorData, range: byteRange)
                    return SCNVector3( x: vectorData[0], y: vectorData[1], z: vectorData[2])
                })
    
                result = vertices
    
            }
    
            return result
        }
    

    2- 取消投影 Vision 捕获的每个地标并将它们保存在 SCNVector3 数组中:

    let unprojectedLandmark = sceneView.unprojectPoint( SCNVector3(landmarks[i].x + (landmarks[i].x,landmarks[i].y,0))
    

    3- 使用新顶点修改几何体:

    func reshapeGeometry(_vertices: [SCNVector3]){

    let source = SCNGeometrySource(vertices: vertices)
    
    var newSources = [SCNGeometrySource]()
    newSources.append(source)
    
    for source in shape!.geometry!.sources {
        if (source.semantic != SCNGeometrySource.Semantic.vertex) {
            newSources.append(source)
        }
    }
    
    let geometry = SCNGeometry(sources: newSources, elements: shape!.geometry?.elements)
    
    let material = shape!.geometry?.firstMaterial
    shape!.geometry = geometry
    shape!.geometry?.firstMaterial = material
    

    }

    我能够做到这一点,这就是我的方法。 希望这会有所帮助!

    【讨论】:

    • 你能分享一个更完整的实现吗?这似乎很有希望,但没有解释如何使用 getVertices()unprojectedLandmark
    【解决方案2】:

    我建议查看 Google 的 AR Core 产品,这些产品支持带有后置或前置摄像头的 Apple AR 场景……但在涉及非人脸深度摄像头设备时,它在 Apple 之外添加了一些额外功能。

    Apple 的 Core Vision 与 Google 的 Core Vision 框架几乎相同,后者返回代表眼睛/嘴巴/鼻子等的 2D 点......以及面部倾斜组件。

    但是,如果您想要一种方法来简单地将 2D 纹理应用到响应式 3D 面部,或者将 3D 模型附加到面部上的点,那么请查看 Google 的 Core Augmented Faces 框架。它在 iOS 和 Android 上有很好的示例代码。

    【讨论】:

    • ARCore SDK 非常棒,但与 Vision 相比受到限制(I.E. 似乎不支持检测/跟踪多个面,并且使用的顶点数量少于 Vision 当前版本)。也就是说,这是实施此类技术的好方法,而且不会过于复杂。
    • 当然可以,但是 Apple 的 Vision 框架不允许真正的 3D 头部跟踪,而只能对面部标记进行 2D 跟踪。 Apple 的 ARKIt 将进行真正的 3D 头部跟踪 - 但仅适用于 iPhone10 及更高版本的设备。
    猜你喜欢
    • 2018-10-31
    • 1970-01-01
    • 2021-11-21
    • 2020-06-09
    • 2020-02-24
    • 2019-07-15
    • 2016-05-08
    • 1970-01-01
    • 2018-06-18
    相关资源
    最近更新 更多