如何通过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
相关产品推荐
相关产品推荐

