You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Python人脸关键点检测实时控制3D人脸模型?求实现示例

实时人脸关键点驱动3D人脸模型实现方案

这完全可以实现,核心是把人脸关键点检测、3D模型顶点变形、实时渲染三个环节串联起来。以下是具体实现步骤和代码示例:

一、获取实时3D人脸关键点(Mediapipe Face Mesh)

Mediapipe Face Mesh直接输出468个3D人脸关键点(基于摄像头坐标系),适合做实时驱动:

import cv2
import mediapipe as mp
import numpy as np

mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh(
    max_num_faces=1,
    refine_landmarks=True,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5
)

cap = cv2.VideoCapture(0)
# 预存初始关键点位置,用于计算位移
initial_key_points = None

while cap.isOpened():
    success, image = cap.read()
    if not success:
        continue

    image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    results = face_mesh.process(image_rgb)

    if results.multi_face_landmarks:
        landmarks = results.multi_face_landmarks[0]
        # 提取3D关键点并缩放至模型适配尺寸
        key_points_3d = np.array([(lm.x, lm.y, lm.z) for lm in landmarks.landmark]) * 100
        if initial_key_points is None:
            initial_key_points = key_points_3d.copy()
        # 计算关键点位移量
        key_point_deltas = key_points_3d - initial_key_points

    cv2.imshow('Face Mesh', image)
    if cv2.waitKey(5) & 0xFF == 27:
        break

cap.release()
cv2.destroyAllWindows()

二、加载3D人脸模型(.obj格式)

用轻量代码读取.obj模型的顶点与UV数据:

def load_obj(filename):
    vertices = []
    uvs = []
    with open(filename, 'r') as f:
        for line in f:
            if line.startswith('v '):
                parts = line.strip().split()
                vertices.append([float(p) for p in parts[1:4]])
            elif line.startswith('vt '):
                parts = line.strip().split()
                uvs.append([float(p) for p in parts[1:3]])
    return np.array(vertices, dtype=np.float32), np.array(uvs, dtype=np.float32)

# 加载模型并保存原始状态
original_vertices, original_uvs = load_obj('face_model.obj')
model_vertices = original_vertices.copy()
model_uvs = original_uvs.copy()

三、建立关键点与模型顶点的映射关系

采用权重绑定方案:给每个模型顶点分配权重,指定它受哪些人脸关键点影响。简化场景下可手动绑定关键控制点:

# 选取Mediapipe中5个核心控制点索引:鼻尖、左眼角、右眼角、左嘴角、右嘴角
control_indices = [1, 33, 263, 61, 291]
initial_control_points = initial_key_points[control_indices]

# 计算每个顶点到控制点的权重(距离越近权重越高)
weights = []
for v in original_vertices:
    dists = np.linalg.norm(v - initial_control_points, axis=1)
    # 用倒数归一化作为权重,避免除零
    w = 1 / (dists + 1e-6)
    w /= np.sum(w)
    weights.append(w)
weights = np.array(weights)

四、实时计算模型顶点与纹理变形

根据关键点位移,更新模型顶点和UV坐标:

# 在实时检测循环中插入这段代码
current_control_points = key_points_3d[control_indices]
control_deltas = current_control_points - initial_control_points

# 更新顶点位置
model_vertices = original_vertices + np.dot(weights, control_deltas)
# 更新UV坐标(跟随顶点同步变形)
model_uvs = original_uvs + np.dot(weights, control_deltas[:, :2])  # UV仅用xy分量

五、实时渲染变形模型(PyOpenGL示例)

用GPU加速的PyOpenGL实现实时渲染:

from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *

def draw_model(vertices, uvs):
    glEnable(GL_TEXTURE_2D)
    glBegin(GL_TRIANGLES)  # 假设模型已按三角面组织,需补充读取obj的面数据
    # 此处需结合obj的面索引数据绘制,简化示例用点渲染
    for v, uv in zip(vertices, uvs):
        glTexCoord2fv(uv)
        glVertex3fv(v)
    glEnd()
    glDisable(GL_TEXTURE_2D)

def display():
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()
    gluLookAt(0, 0, 200, 0, 0, 0, 0, 1, 0)  # 设置相机视角

    # 实时传入更新后的顶点与UV数据
    draw_model(model_vertices, model_uvs)

    glutSwapBuffers()

glutInit()
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
glutInitWindowSize(800, 600)
glutCreateWindow(b"Face-Driven 3D Model")
glutDisplayFunc(display)
glutMainLoop()

实时性说明

  • 关键点检测:Mediapipe Face Mesh在CPU上即可达到30+fps,满足实时要求;
  • 变形计算:1万顶点以内的模型,用numpy向量运算单帧耗时≤1ms;
  • 渲染:PyOpenGL依赖GPU加速,轻松达到60fps,整体流程可实现实时交互。

内容的提问来源于stack exchange,提问作者Q Q

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 23:35:41