Подтвердить что ты не робот

Отображение изображения на трехмерной сетке

Я использую iPhone X и ARFaceKit для захвата лица пользователя. Цель состоит в том, чтобы текстурировать лицевую сетку с изображением пользователя.

Я рассматриваю только один кадр (ARFrame) из сеанса AR. Из ARFaceGeometry у меня есть набор вершин, которые описывают грань. Я создаю jpeg-представление текущего кадра capturedImage.

Затем я хочу найти координаты текстуры, которые отображают созданный 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 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"
    }
}

Это не работает, но вместо этого я получаю очень фанковое лицо! Где я ошибаюсь?

4b9b3361

Ответ 1

Начальная точка отличается:

Start point is different

Примените следующие изменения в вашем коде:

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

Вы можете получить нормальное лицо.

Ответ 2

Текстурирование сетки лица с помощью пользовательского изображения теперь доступно в примере кода Face-Based, опубликованном Apple (раздел Map Video Camera on 3D Face Geometry).

Можно отобразить видео с камеры на 3D Face Geometry, используя следующий модификатор шейдера.

// 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 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;

Ответ 3

Для правильного отображения UV вам нужно использовать класс ARSCNFaceGeometry вместо класса ARFaceGeometry, который вы используете в своем коде.

ARSCNFaceGeometry является представлением SceneKit топологии лица для использования с информацией лица, предоставленной ARSession. Он используется для быстрой визуализации геометрии лица с помощью движка рендеринга SceneKit.

Класс ARSCNFaceGeometry является подклассом SCNGeometry который SCNGeometry данные меша, предоставленные классом ARFaceGeometry. Вы можете использовать ARSCNFaceGeometry чтобы быстро и легко визуализировать топологию лица и выражения лица, предоставляемые ARKit в представлении SceneKit.

Но ARSCNFaceGeometry доступна только в представлениях SceneKit или средствах визуализации, которые используют Metal. Этот класс не поддерживается для рендеринга SceneKit на основе OpenGL.