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 中这套"运动缝合"机制的原理。
数字人为什么容易"假":眨眼与缝合两大难题
在生成式数字人里,两个细节最容易穿帮:
- 不眨眼:如果直接用音频驱动的口型运动,眼睛会全程睁着,几秒后观众就会产生"恐怖谷"般的违和感;
- 肩颈错位:驱动人脸动起来时,肩、颈部位的像素会和背景"撕开",出现明显的接缝。
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时通过参数组合:
- driving 眼睛(
drive_eye=True,图片模式默认):驱动序列自带的眼部运动,眨眼最真实; - source 眼睛(
drive_eye=False,视频模式默认):用参考视频本身的眼部动作,保留本人眨眼习惯; - 固定眨眼数组(
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),仅供参考