news 2026/8/23 16:44:23

Ditto核心原理(三):motion_stitch缝合网络如何让数字人自然眨眼与表情过渡

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ditto核心原理(三):motion_stitch缝合网络如何让数字人自然眨眼与表情过渡

Ditto核心原理(三):motion_stitch缝合网络如何让数字人自然眨眼与表情过渡

【免费下载链接】ditto-talkinghead[ACM MM 2025] Ditto: Motion-Space Diffusion for Controllable Realtime Talking Head Synthesis项目地址: https://gitcode.com/gh_mirrors/di/ditto-talkinghead

Ditto 是 ACM MM 2025 的实时说话头合成项目,输入一张照片和一段音频,就能生成口型、表情、眼神都极其自然的说话数字人视频。而数字人之所以"像活人",除了嘴会动,更关键的是它会不定时眨眼、表情平滑过渡。这正是缝合网络(motion_stitch 模块)的功劳。本文带你读懂 Ditto 中这套"运动缝合"机制的原理。

数字人为什么容易"假":眨眼与缝合两大难题

在生成式数字人里,两个细节最容易穿帮:

  1. 不眨眼:如果直接用音频驱动的口型运动,眼睛会全程睁着,几秒后观众就会产生"恐怖谷"般的违和感;
  2. 肩颈错位:驱动人脸动起来时,肩、颈部位的像素会和背景"撕开",出现明显的接缝。

Ditto 把这两类问题都交给了运动空间中的缝合模块处理,对应文件 core/atomic_components/motion_stitch.py,模型结构在 core/models/modules/stitching_network.py。

缝合流水线:audio2motion 之后的"整形师"

在 Ditto 的在线推理管线(stream_pipeline_online.py)中,各模块通过队列多线程串联:

音频特征提取 → audio2motion(扩散模型生成运动) → motion_stitch(缝合) → warp_f3d(3D变形) → decoder(解码出图) → putback(贴回原图)

motion_stitch 拿到的是两份"运动信息":

  • x_s_info(source 运动):从参考图片/视频中提取的原始姿态,代表"这个人本来长什么样、怎么摆头";
  • x_d_info(driving 运动):扩散模型由音频驱动生成的新运动,代表"说话时嘴该怎么动"。

缝合任务就是一句话:保留 source 的脸部结构,把 driving 的口型"缝"上去,再补上自然的眨眼

表情融合:谁说了算?

核心函数_mix_s_d_info按类别决定每路数据的权重:

  • 图片模式下,driving 提供exp(表情形变)、pitch/yaw/roll(头姿)、t(平移);
  • 采用相对增量方式(relative_d=True):以第一帧 driving 运动为基准 d0,只叠加"变化量",避免人脸被整体拽偏;
  • 不同分辨率来源之间还会按scale比例缩放运动幅度,保证幅度匹配。

简单说:头怎么摆、脸长什么样听 source 的,嘴巴怎么动听 driving 的。

自然眨眼:15帧闭眼 + 60~100帧随机间隔

这是数字人"活过来"的关键。_set_eye_blink_idx函数会生成一整条视频的眨眼时间轴

  • 每次眨眼持续blink_n=15帧(约 0.5 秒,正好是一开一闭的节奏);
  • 两次眨眼之间随机间隔60~100帧,模拟人类自然的眨眼频率;
  • 支持固定间隔或循环指定间隔列表,让眨眼节奏可控制。

而"闭眼动作"从哪来?Ditto 提供三种眼睛运动来源,在setup时通过参数组合:

  1. driving 眼睛drive_eye=True,图片模式默认):驱动序列自带的眼部运动,眨眼最真实;
  2. source 眼睛drive_eye=False,视频模式默认):用参考视频本身的眼部动作,保留本人眨眼习惯;
  3. 固定眨眼数组delta_eye_arr):预先录好的一组闭眼形变,按上面的时间轴周期性套用,适合"单图驱动"却想要自然眨眼的场景。

融合时_fix_exp_for_x_d_info_v2按 21 个关键点对眼睛、嘴部分别加权:6/12/14/17/19/20是嘴部关键点(听 driving),11/13/15/16/18是眼部关键点(听眼睛来源),其余面部关键点(眉毛、脸颊等)保持 source 原样——嘴动、眼眨、脸不变,三者互不干扰。

缝合网络:一个"肩带修正"小MLP

光融合数据还不够。人脸动起来后,肩颈处像素会错位。Ditto 训练了一个轻量 MLP 来预测修正量,输入 source 和 driving 两组关键点(21×3×2=126 维),输出 65 维:

  • 前 63 维:21 个关键点各自的 3D 位移修正delta_exp
  • 后 2 维:整体平移修正delta_tx_ty

网络把修正量直接加到 driving 关键点上,就能让动画后的脸"贴回"原始图像空间而不出缝。这个结构继承自 LivePortrait 的 retargeting 思想,参数极少,实时推理毫无压力。

细节魔法:视线跟随与无声闭嘴

  • 视线修正_fix_gaze:当 source 是静态图片时,人眼不会随说话而转头。Ditto 用头姿差(yaw/pitch 变化)按固定比例微调眼球关键点,让人物说话时"眼神跟着内容走",而不是呆滞盯着镜头;
  • VAD 闭嘴ctrl_vad:静音片段(无语音)时,用vad_alpha把嘴部关键点淡回到闭嘴状态,避免人物"没说话却一直在嚼";
  • 淡入淡出fade:视频开头结尾可用fade_alpha把运动渐变回 source 初始姿态,配合离线模式下强制首尾帧睁眼(set_Nd),解决"视频以闭眼状态开始/结束"的尴尬。

总结:一套"数据缝合 + 小网络"的优雅组合

Ditto 的 motion_stitch 设计思路非常清晰:

问题解决方案关键代码
口型与脸型冲突按关键点分类加权融合_mix_s_d_info
全程睁眼像机器人随机眨眼时间轴 + 多源眼部运动_set_eye_blink_idx
肩颈接缝错位轻量 MLP 预测关键点修正StitchingNetwork
眼神呆板头姿差驱动眼球微调_fix_gaze
静音时乱动嘴VAD 淡入闭嘴ctrl_vad

大部分工作用规则化的数据融合完成(快且可控),只在真正需要学习的"接缝修正"上放了一个几百 KB 的 MLP——这正是 Ditto 能做到实时、可控、且自然的关键之一。下一篇我们看 warp_f3d 如何把缝合好的关键点变成 3D 变形场。

【免费下载链接】ditto-talkinghead[ACM MM 2025] Ditto: Motion-Space Diffusion for Controllable Realtime Talking Head Synthesis项目地址: https://gitcode.com/gh_mirrors/di/ditto-talkinghead

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/23 16:40:53

如何把安卓手机投到电脑并直接控制:scrcpy 三步上手

如何把安卓手机投到电脑并直接控制:scrcpy 三步上手 【免费下载链接】scrcpy Display and control your Android device 项目地址: https://gitcode.com/GitHub_Trending/sc/scrcpy 你正用电脑赶一份文档,手机放在手边,来条消息就忍不…

作者头像 李华
网站建设 2026/8/23 16:39:59

猫抓扩展:网页视频音频一键提取的完整上手指南

猫抓扩展:网页视频音频一键提取的完整上手指南 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 你一定遇到过这种场景:想存一…

作者头像 李华
网站建设 2026/8/23 16:30:20

深入理解D3.js中的数字格式化工具d3-format

深入理解D3.js中的数字格式化工具d3-format 为什么需要数字格式化 在JavaScript中处理数字时&#xff0c;开发者经常会遇到一些令人困惑的现象。比如下面这个简单的循环&#xff1a; for (let i 0; i < 10; i) {console.log(0.1 * i); }输出结果可能出乎意料&#xff1a; 0…

作者头像 李华