将图像映射到3D面网格

时间:2017-12-05 21:38:11

标签: ios 3d augmented-reality arkit iphone-x

我正在使用iPhone X和ARFaceKit来捕捉用户的脸。目标是使用用户的图像纹理面部网格。

我只查看ARFrame会话中的单个帧(AR)。 从ARFaceGeometry开始,我有一组描述面部的顶点。 我对当前帧capturedImage进行了jpeg表示。

然后我想找到将创建的jpeg映射到网格顶点的纹理坐标。我想要: 1.将顶点从模型空间映射到世界空间; 2.将顶点从世界空间映射到摄像机空间; 3.除以图像尺寸以获得纹理的像素坐标。

let geometry: ARFaceGeometry = contentUpdater.faceGeometry!
let theCamera = session.currentFrame?.camera

let theFaceAnchor:SCNNode = contentUpdater.faceNode
let anchorTransform = float4x4((theFaceAnchor?.transform)!)

for index in 0..<totalVertices {
    let vertex = geometry.vertices[index]

    // Step 1: Model space to world space, using the anchor's transform
    let vertex4 = float4(vertex.x, vertex.y, vertex.z, 1.0)
    let worldSpace = anchorTransform * vertex4

    // Step 2: World space to camera space
    let world3 = float3(worldSpace.x, worldSpace.y, worldSpace.z)
    let projectedPt = theCamera?.projectPoint(world3, orientation: .landscapeRight, viewportSize: (theCamera?.imageResolution)!)

    // Step 3: Divide by image width/height to get pixel coordinates
    if (projectedPt != nil) {
        let vtx = projectedPt!.x / (theCamera?.imageResolution.width)!
        let vty = projectedPt!.y / (theCamera?.imageResolution.height)!
        textureVs += "vt \(vtx) \(vty)\n"
    }
}

这不行,但反而给我一个非常时髦的脸!我哪里错了?

3 个答案:

答案 0 :(得分:0)

起点不同:

Start point is different

对您的代码应用以下更改:

//let vty = projectedPt!.y / (theCamera?.imageResolution.height)!
let vty = ((theCamera?.imageResolution.height)! - projectedPt!.y) / (theCamera?.imageResolution.height)!

你可以获得普通面孔。

答案 1 :(得分:0)

现在可以在Apple发布的Face-Based sample code中使用用户图像对面部网格进行纹理化(将摄像机视频映射到3D面部几何部分)。

可以使用以下着色器修改器将摄像机视频映射到3D人脸几何。

// Transform the vertex to the camera coordinate system.
float4 vertexCamera = scn_node.modelViewTransform * _geometry.position;

// Camera projection and perspective divide to get normalized viewport coordinates (clip space).
float4 vertexClipSpace = scn_frame.projectionTransform * vertexCamera;
vertexClipSpace /= vertexClipSpace.w;

// XY in clip space is [-1,1]x[-1,1], so adjust to UV texture coordinates: [0,1]x[0,1].
// Image coordinates are Y-flipped (upper-left origin).
float4 vertexImageSpace = float4(vertexClipSpace.xy * 0.5 + 0.5, 0.0, 1.0);
vertexImageSpace.y = 1.0 - vertexImageSpace.y;

// Apply ARKit's display transform (device orientation * front-facing camera flip).
float4 transformedVertex = displayTransform * vertexImageSpace;

// Output as texture coordinates for use in later rendering stages.
_geometry.texcoords[0] = transformedVertex.xy;

答案 2 :(得分:0)

  

为正确进行UV映射,您需要使用ARSCNFaceGeometry类而不是您在代码中使用的ARFaceGeometry

ARSCNFaceGeometry是SceneKit的面部拓扑表示,用于ARSession提供的面部信息。它用于使用SceneKit的渲染引擎快速可视化面部几何。

ARSCNFaceGeometry类是SCNGeometry的子类,它包装ARFaceGeometry类提供的网格数据。您可以使用ARSCNFaceGeometry在SceneKit视图中快速轻松地可视化ARKit提供的面部拓扑和面部表情。

但是ARSCNFaceGeometry仅在使用Metal的SceneKit视图或渲染器中可用。 基于OpenGL的SceneKit渲染不支持此类。