当前位置: 首页 > news >正文

PiscCode使用 Mediapipe 实时人脸表情识别与可视化

在人机交互(HCI)、虚拟主播(VTuber)、情绪计算(Affective Computing)等应用场景中,实时识别人脸表情 是一个非常重要且实用的功能。它不仅能够增强用户体验,还能作为交互逻辑的输入信号。例如:

  • 智能客服系统 中,实时捕捉用户的情绪状态,可以帮助系统判断用户是否满意,从而动态调整应答策略。

  • 虚拟主播或虚拟形象驱动 中,通过人脸表情识别将主播的面部动作实时映射到虚拟角色上,可以实现更加自然的表情同步,让角色“活”起来。

  • 心理学与情绪分析 领域,自动检测微表情与显著表情能够为研究者提供客观数据,辅助情绪识别与行为分析。

实现这类功能的核心在于 人脸关键点检测与表情分析。传统方法通常依赖复杂的深度学习模型,开发门槛高、部署难度大。而 Google 开源的 MediaPipe 框架 提供了高效、跨平台的解决方案。

本文将演示如何基于 Mediapipe FaceLandmarker 模型,快速搭建一个实时人脸表情识别系统,主要功能包括:

  1. 人脸关键点检测:在视频流中检测单张或多张人脸,获取数百个高精度面部关键点。

  2. 表情分析:利用 MediaPipe 提供的 Face Blendshapes 输出,计算并提取显著表情。

  3. 可视化展示:在摄像头画面上叠加人脸网格(面部结构线、轮廓线、虹膜)以及文字标签,实时显示当前识别到的显著表情。

最终效果是:用户只需对着摄像头做出不同的表情(如微笑、惊讶、皱眉等),系统便能自动捕捉并在屏幕上显示对应的表情类别,实现一种轻量级的 实时表情驱动 功能。


1. 项目概述

本项目实现了以下功能:

  1. 人脸检测:检测视频帧中的人脸。

  2. 关键点绘制:绘制人脸网格、轮廓和虹膜。

  3. 表情识别:根据 face_blendshapes 输出最显著的表情。

  4. 实时可视化:在视频帧上显示人脸网格和表情文字。

核心依赖:

  • mediapipe:用于人脸关键点检测和表情计算。

  • opencv-python:摄像头读取和图像显示。

  • numpy:数组和坐标计算。


2. 环境依赖

 

pip install mediapipe opencv-python numpy

注意:Mediapipe Tasks API 在 Python 3.9+ 上效果最佳。


3. 核心类:FaceExperssion

3.1 初始化 FaceLandmarker

class FaceExperssion:def __init__(self, model_path="face_landmarker.task"):base_options = python.BaseOptions(model_asset_path=model_path)options = vision.FaceLandmarkerOptions(base_options=base_options,output_face_blendshapes=True,output_facial_transformation_matrixes=True,num_faces=1)self.detector = vision.FaceLandmarker.create_from_options(options)

我们使用 Mediapipe 的 Tasks API 加载 face_landmarker.task 模型,并启用 blendshapes 输出,这样可以获取面部表情评分。


3.2 绘制人脸网格

def _draw_landmarks_on_image(self, rgb_image, detection_result):annotated_image = np.copy(rgb_image)for face_landmarks in detection_result.face_landmarks:face_landmarks_proto = landmark_pb2.NormalizedLandmarkList()face_landmarks_proto.landmark.extend([landmark_pb2.NormalizedLandmark(x=lm.x, y=lm.y, z=lm.z) for lm in face_landmarks])# 绘制网格、轮廓、虹膜solutions.drawing_utils.draw_landmarks(image=annotated_image,landmark_list=face_landmarks_proto,connections=mp.solutions.face_mesh.FACEMESH_TESSELATION,landmark_drawing_spec=None,connection_drawing_spec=mp.solutions.drawing_styles.get_default_face_mesh_tesselation_style())solutions.drawing_utils.draw_landmarks(image=annotated_image,landmark_list=face_landmarks_proto,connections=mp.solutions.face_mesh.FACEMESH_CONTOURS,landmark_drawing_spec=None,connection_drawing_spec=mp.solutions.drawing_styles.get_default_face_mesh_contours_style())solutions.drawing_utils.draw_landmarks(image=annotated_image,landmark_list=face_landmarks_proto,connections=mp.solutions.face_mesh.FACEMESH_IRISES,landmark_drawing_spec=None,connection_drawing_spec=mp.solutions.drawing_styles.get_default_face_mesh_iris_connections_style())return annotated_image

这里分别绘制:

  • FACEMESH_TESSELATION:人脸三角网格

  • FACEMESH_CONTOURS:面部轮廓

  • FACEMESH_IRISES:虹膜


3.3 获取显著表情

Mediapipe 的 face_blendshapes 提供每个表情的概率,我们取 分数最高的表情 作为当前表情。

def _get_dominant_expression(self, detection_result):if not detection_result.face_blendshapes:return "Neutral"max_val = 0expression = "Neutral"for blendshape_list in detection_result.face_blendshapes:for category_score in blendshape_list:if category_score.score > max_val:max_val = category_score.scoreexpression = category_score.category_namereturn expression

3.4 处理单帧图像

def do(self, frame, device=None):if frame is None: return Nonemp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))detection_result = self.detector.detect(mp_image)annotated = self._draw_landmarks_on_image(mp_image.numpy_view(), detection_result)expression = self._get_dominant_expression(detection_result)cv2.putText(annotated, f"Expression: {expression}", (10, 30),cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, cv2.LINE_AA)return cv2.cvtColor(annotated, cv2.COLOR_RGB2BGR)

do 方法将返回绘制了人脸网格和表情文字的帧,可直接用于显示或进一步处理。


4. 快速体验

import cv2import numpy as npimport mediapipe as mpfrom mediapipe import solutionsfrom mediapipe.framework.formats import landmark_pb2from mediapipe.tasks import pythonfrom mediapipe.tasks.python import visionclass FaceExperssion:def __init__(self, model_path="文件地址/face_landmarker.task"):"""初始化 Mediapipe FaceLandmarker"""base_options = python.BaseOptions(model_asset_path=model_path)options = vision.FaceLandmarkerOptions(base_options=base_options,output_face_blendshapes=True,output_facial_transformation_matrixes=True,num_faces=1)self.detector = vision.FaceLandmarker.create_from_options(options)def _draw_landmarks_on_image(self, rgb_image, detection_result):"""在图像上绘制人脸网格、轮廓和虹膜"""face_landmarks_list = detection_result.face_landmarksannotated_image = np.copy(rgb_image)for face_landmarks in face_landmarks_list:face_landmarks_proto = landmark_pb2.NormalizedLandmarkList()face_landmarks_proto.landmark.extend([landmark_pb2.NormalizedLandmark(x=lm.x, y=lm.y, z=lm.z)for lm in face_landmarks])# 绘制三类连接solutions.drawing_utils.draw_landmarks(image=annotated_image,landmark_list=face_landmarks_proto,connections=mp.solutions.face_mesh.FACEMESH_TESSELATION,landmark_drawing_spec=None,connection_drawing_spec=mp.solutions.drawing_styles.get_default_face_mesh_tesselation_style())solutions.drawing_utils.draw_landmarks(image=annotated_image,landmark_list=face_landmarks_proto,connections=mp.solutions.face_mesh.FACEMESH_CONTOURS,landmark_drawing_spec=None,connection_drawing_spec=mp.solutions.drawing_styles.get_default_face_mesh_contours_style())solutions.drawing_utils.draw_landmarks(image=annotated_image,landmark_list=face_landmarks_proto,connections=mp.solutions.face_mesh.FACEMESH_IRISES,landmark_drawing_spec=None,connection_drawing_spec=mp.solutions.drawing_styles.get_default_face_mesh_iris_connections_style())return annotated_imagedef _get_dominant_expression(self, detection_result):"""根据 blendshapes 返回最显著的表情"""if not detection_result.face_blendshapes:return "Neutral"max_val = 0expression = "Neutral"# detection_result.face_blendshapes 是 List[List[CategoryScore]]for blendshape_list in detection_result.face_blendshapes:for category_score in blendshape_list:  # 直接遍历 CategoryScoreif category_score.score > max_val:max_val = category_score.scoreexpression = category_score.category_namereturn expressiondef do(self, frame, device=None):"""处理单帧图像,返回绘制人脸网格和表情文字后的帧"""if frame is None:return None# 转为 Mediapipe Imagemp_image = mp.Image(image_format=mp.ImageFormat.SRGB,data=cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))# 检测人脸detection_result = self.detector.detect(mp_image)# 绘制人脸网格annotated = self._draw_landmarks_on_image(mp_image.numpy_view(), detection_result)# 获取显著表情expression = self._get_dominant_expression(detection_result)# 在左上角绘制文字cv2.putText(annotated,f"Expression: {expression}",(10, 30),cv2.FONT_HERSHEY_SIMPLEX,1,(0, 255, 0),2,cv2.LINE_AA)return cv2.cvtColor(annotated, cv2.COLOR_RGB2BGR)

运行后,你可以在摄像头画面上看到:

  • 实时人脸网格

  • 面部轮廓和虹膜

  • 左上角的表情文字(如 Happy, Neutral, Surprised 等)

对 PiscTrace or PiscCode感兴趣?更多精彩内容请移步官网看看~🔗 PiscTrace


文章转载自:

http://VklIrvyI.qtzwh.cn
http://DgbRZ9zJ.qtzwh.cn
http://gMPnFU7M.qtzwh.cn
http://8RXUZKGV.qtzwh.cn
http://FlHPPwHt.qtzwh.cn
http://ou0wy1lW.qtzwh.cn
http://yQ53wbrL.qtzwh.cn
http://wFrTHQ0O.qtzwh.cn
http://Fvsw3vRN.qtzwh.cn
http://k70E3znh.qtzwh.cn
http://FxE10gBB.qtzwh.cn
http://Cnu6oeEQ.qtzwh.cn
http://W7FRV1pE.qtzwh.cn
http://iT8mlWBk.qtzwh.cn
http://ikGql1NK.qtzwh.cn
http://QnoiRTFA.qtzwh.cn
http://pr07EOHr.qtzwh.cn
http://FvYfLlQP.qtzwh.cn
http://u3Kgzv3C.qtzwh.cn
http://HdcXlZ5D.qtzwh.cn
http://wqKcB0PU.qtzwh.cn
http://a8A0OnWU.qtzwh.cn
http://jCr79LtQ.qtzwh.cn
http://AHhf9hLI.qtzwh.cn
http://xdoGFmUP.qtzwh.cn
http://McNKWCgC.qtzwh.cn
http://Gjc6CxhX.qtzwh.cn
http://6PsSx0ku.qtzwh.cn
http://NZ9io7NY.qtzwh.cn
http://hbNaGNZQ.qtzwh.cn
http://www.dtcms.com/a/370746.html

相关文章:

  • EG2104 SOP-8 带SD功能 内置600V功率MOS管 栅极驱动芯片
  • 【审核问题——托管式首次进入APP展示隐私政策弹窗】
  • MySQL+Canal同步ES延时问题全链路解决方案
  • 【高等数学】第十一章 曲线积分与曲面积分——第三节 格林公式及其应用
  • Android Kotlin 动态注册 Broadcast 的完整封装方案
  • OceanBase容量统计:租户、数据库、表大小
  • SpringAMQP
  • 软件设计师备考-(十四)数据库设计
  • Fast DDS原生程序ROS2 Rviz Debug工具接入--Overview
  • 深入理解 Next.js 的路由机制
  • 鸿蒙 BLE 蓝牙智能设备固件升级之DFU升级方式(Nordic芯片)
  • 5-10数组元素添加和删除(数组基础操作)
  • echarts实现两条折线区域中间有线连接,custom + renderItem(初级版)
  • 机器人控制器开发(传感器层——奥比大白相机适配)
  • 深入解析 JavaScript 中的 call、apply、bind:用法、差异与面试题
  • LangChain实战(十八):构建ReAct模式的网页内容摘要与分析Agent
  • OpenRouter:一站式 AI 模型调用平台,免费畅享千问、DeepSeek 等顶级模型
  • Python基础(①⑧Queue)
  • 小型磨床设计cad+三维图+设计说明书
  • EMS 抗扰度在边缘计算产品电路设计的基本问题
  • 拯救珍贵回忆:AI照片修复让老照片重获新生
  • 一款免费易用且打造的全功能媒体播放器
  • 记一次uniapp微信小程序开发scss变量失效的问题
  • 如何在Kali Linux官网下载历史版本
  • 软考中级习题与解答——第二章_程序语言与语言处理程序(3)
  • 外置flash提示音打包脚本
  • ecplise配置maven插件
  • Android应用完全重启指南:从任务重置到进程重生
  • WordPress如何绑定多个域名 WordPress实现多域名访问
  • Windows防火墙出入站规则在注册表中的位置