Skip to content

基于 Mediapipe 的面部捕捉算法 ​

把 Mediapipe 每帧输出的 478 个原始特征点,按面部区域归纳成语义化、抗抖动的 BlendShape 数据,让普通摄像头直接驱动虚拟人面部。

技术问题 ​

摄像头加 Mediapipe 只能回答一个问题:这一帧人脸上的 478 个点各自在什么坐标。而虚拟人模型要的是另一种数据——BlendShape 通道权重,比如「眨眼 0.6」「张嘴 0.3」,取值范围 0 到 1。

中间缺的这一层就是特征点归纳算法:怎么从一堆点位坐标算出语义化的表情权重。当时市面上没有开源的、基于 Mediapipe 点位图的归纳实现——要用 Mediapipe 做面捕,这一层只能自己写。

现有方案不足 ​

  • 直接线性映射:把点位距离直接按比例映射到 BlendShape,不同人脸的五官比例差异大,数值范围漂移,基本不可用。
  • 原始解算不平滑:相邻帧的特征点检测天然带噪声,不做滤波直接驱动模型,面部会高频抖动。
  • 商用 SDK 绑定自家生态:ARKit 这类方案自带归纳能力,但绑定自家协议和平台,无法直接用在 Mediapipe 链路上。

核心思路 ​

按面部区域拆分归纳模块,每个模块只消费自己区域的特征点,输出该区域语义化的 BlendShape 值;所有模块的输出汇总成原始 BS 数据集,统一过滤波后再交给驱动层。

mermaid
flowchart LR
    A["相机模块<br>每帧输出人脸纹理"] --> B["Mediapipe 推理<br>输出 478 个特征点"]
    B --> C["归纳模块<br>眉 / 眼 / 嘴 / 眼珠"]
    C --> D["原始 BlendShape<br>数据集"]
    D --> E["滤波模块<br>低通 + 卡尔曼"]
    E --> F["CompatibleFaceBlendShape<br>稳定 BS 数据"]
    F --> G["模型驱动层<br>面部迁移"]

关键实现 ​

区域归纳 ​

以眨眼为例:取眼部关键特征点与基准特征点(即眨眼通道值为 0、眼睛完全睁开时的未变化状态)之间的距离关系,经眨眼函数、分段函数和 lerp 处理,输出 0-1 的眨眼幅度。眉毛、嘴巴、眼珠模块同理,各自取本区域的关键点做推导,再持续调参收敛到可用效果。

工程拆分 ​

  • UnityMediapipePlugin:管理相机纹理输出,托管 Mediapipe 框架,产出特征点数据集。
  • MediapipeAdaptor:承载归纳算法和滤波模块,把特征点处理成稳定平滑的 BS 数据集。
  • 驱动层:业务代码,按模型自身的 BlendShape 协议消费数据,与解算链路完全解耦。

可移植性 ​

归纳算法只依赖点位图的语义定义(哪个编号是眼角、哪个是嘴角),不依赖 Mediapipe 本身。其他面捕引擎只要点位定义与 Mediapipe 一致,同一套归纳算法可以直接复用。

应用场景 ​

  • 虚拟直播 PC 端:摄像头面捕实时驱动虚拟主播。
  • AR 头套开播:移动端复用同一条链路。
  • 已落地于虚拟直播姬 PC 版、AR 头套开播 PC 版、虚拟直播姬移动端。

关联案例 ​

罗子初 · AI 座舱专家 · 8年端侧研发

Lv.1