Prelulu · 2026-11-11 · 实验报告(不是视觉验收)
头部转动对比:PSD2Live(线上)vs 我们自己的 binder
Head turning — PSD2Live field in production (#177) vs our own head binder (draft #181, head 4830af3)
结论 Summary
- 网格指标我们更好,画面在对角上我们更差。五个角色上我们的折叠三角形都比 PSD2Live 少一个数量级以上,p99 拉伸相当或更低;但在对角(X/Y 同时 ±30)时,我们的头部位移过大:脸和头发错位、下颌和脸颊轮廓断开、头发与头顶分离,五个角色都有,Momo 最严重。PSD2Live 在对角处整体更稳,但有它自己的固定毛病:Hiyori 的呆毛和发带脱离、Momo 抬头时嘴唇被拉开像在笑、mara_bob 眼周出现错位补丁。
- 我们的鼻子位移约为 PSD2Live 的两倍(0.57–0.64 vs 0.31–0.32 脸半宽),满抬头时脸上移也多 34–99 %。单轴左右转时这让我们的转头更有立体感(耳朵和脸侧露出来),到了对角就“转过头”而破面。把位移量压下来是下一步要调的第一项。
- 门禁:37、mara_bob、朝霧 朔通过我们自己的门禁;Hiyori 未通过 2 项(前发、头饰拉伸),Momo 未通过 6 项(头饰、耳饰拉伸,耳朵跳变)。未通过的字段用
--inspect写出,仅供对比,不会进入生产。 - 与之前的截图不同,这次每个姿态都用播放器自己的 pose 指令驱动到满轴(ParamAngleX/Y = ±30,对应字段的 ±45° / ±30° 关键帧),待机动作关闭,眼睛保持睁开,两个字段用同一帧同一裁切。
五个角色一览 Overview
| 角色 | 我们的门禁 | 折叠 PSD2Live → 我们 | 拉伸 p99 | 鼻子位移(脸半宽) | 方向余弦 |
|---|---|---|---|---|---|
| Hiyori | 未通过(2 项) | 0.61 % → 0.037 % | 2.11 → 2.01 | 0.32 → 0.64 | 0.82–0.99 |
| Momo | 未通过(6 项) | 0.72 % → 0.048 % | 2.51 → 1.98 | 0.32 → 0.63 | 0.84–0.98 |
| 37 | 通过 | 0.32 % → 0.023 % | 1.94 → 1.98 | 0.32 → 0.57 | 0.43–0.77 |
| mara_bob | 通过 | 0.70 % → 0.005 % | 2.31 → 1.90 | 0.31 → 0.64 | 0.92–0.99 |
| 朝霧 朔 | 通过 | 0.72 % → 0.012 % | 2.03 → 1.88 | 0.32 → 0.64 | 0.89–0.99 |
比较什么,怎么产出 Method
- 角色包:五个都在公开画廊里列出,通过公开的角色记录路由下载已发布的包,每个文件都按 manifest 的 SHA-256 校验。包里的
head-field.json就是线上 PSD2Live binder 在 #177 重烘焙时生成的字段。 - 我们的字段:用 #181 自带的命令行
node packages/bake/scripts/bind-head.ts 包目录 输出.json --inspect从同一个包生成。未通过门禁的字段也写出,以便对比。 - 播放器:#181 分支构建的
talk/engine(播放器代码与线上相同,#181 没有改播放器)。两个字段之间唯一的差别是 URL 里的?headField=。 - 姿态驱动:宿主页通过播放器的 postMessage 协议发
pose指令(x、y 为头部单位,1 = 30°),发presence: quiet关闭待机动作,并播放一个把ParamEyeLOpen/ROpen固定为 1 的效果,压住眨眼。每个姿态等 1.5 秒(身体跟随有 0.12 秒滞后)后截图。不使用鼠标跟随近似。 - 渲染:本机 Chromium(SwiftShader WebGL),640×640 视口、2 倍像素;同一角色的两个字段用同一个正方形裁切。扫动视频逐帧设定姿态、等 3 帧后截图,20 fps,共 4.8 秒。
- 指标:通过播放器自己的读取(
prepareRig+buildHeadFields)统计每个头部图层的有色三角形在全部 45 个关键帧上的折叠和拉伸(奇异值最大值),以及满偏航时脸和鼻子的平均位移、满抬头时脸的上移。
滑块模式:在每张图上左右拖动,左半是 PSD2Live,右半是我们的。并排模式:左 PSD2Live,右我们的。角度写作 X / Y(ParamAngleX / ParamAngleY,单位度;+Y 为抬头)。
Hiyori
Live2D 官方样例,经我们的管线重新处理。双马尾、红色发带、头顶呆毛。
- front hair stretches its painted triangles at the 99th percentile by 2.60 (limit 2.50)
- headwear stretches its painted triangles at the 99th percentile by 2.65 (limit 2.50)
- PSD2Live:满偏航和对角时呆毛与头顶分离,右侧发带脱离头发漂在外面;脸本身稳定。
- 我们的:满偏航时整个头部(尤其前发和脸)位移过大;右上角(+30/+30)脸颊被截断、发际线露出一块肤色、下巴轮廓断开。正面和低头时两者接近。
扫动视频 Sweep
左:PSD2Live(线上字段);右:我们的。先偏航 0 → +30 → −30 → 0,再俯仰 0 → +30 → −30 → 0,循环播放。
9 个姿态 Poses

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的
指标 Metrics
| 测量 | PSD2Live(线上) | 我们的(#181) |
|---|---|---|
| 折叠三角形(面积 ≤ 0) | 0.609 % | 0.037 % |
| 拉伸 中位 / p99 / 最大 | 1.01 / 2.11 / 4.63 | 1.06 / 2.01 / 3.80 |
| 满偏航时脸平均位移(脸半宽) | 0.256 | 0.268 |
| 满偏航时鼻子位移(脸半宽) | 0.317 | 0.639 |
| 满抬头时脸上移(脸半宽) | 0.073 | 0.111 |
| 网格数 / 顶点数 | 26 / 2,088 | 21 / 2,289 |
| 字段大小 原始 / gzip | 1.09 MB / 251 KB | 1.20 MB / 415 KB |
| 生成耗时 | 5.4 s(Modal CPU,含 JDK,#177 实测) | 7.5 s(本机 Node,aarch64 CPU) |
逐顶点方向余弦(两者都移动 > 1 px 的顶点)在 8 个边/角关键帧上为 0.82–0.99;满偏航时 RMS 差 24.5 px,PSD2Live 自身 RMS 位移 29.5 px。
Momo
粉色双丸子头、星形发饰、长垂耳饰,刘海较厚。
- back hair stretches its painted triangles at the 99th percentile by 2.56 (limit 2.50)
- ears_1 pops between keys by 3.75 (limit 3.00)
- ears_2 pops between keys by 3.32 (limit 3.00)
- front hair stretches its painted triangles at the 99th percentile by 2.67 (limit 2.50)
- headwear stretches its painted triangles at the 99th percentile by 3.73 (limit 2.50)
- earwear stretches its painted triangles at the 99th percentile by 3.54 (limit 2.50)
- PSD2Live:抬头的三个姿态(左上、抬头、右上)嘴唇被拉开,看起来像张嘴笑(扫动视频里同样出现,所以不是截图时机问题);对应指标里 lips 图层 2.43 % 的折叠。其余姿态稳定。
- 我们的:这是最差的一个,门禁本身就拒绝了它。对角处丸子头和发饰大幅变形、耳朵完全露出且错位、脸部边缘出现接缝;抬头时下巴边缘可见一道接缝。
扫动视频 Sweep
左:PSD2Live(线上字段);右:我们的。先偏航 0 → +30 → −30 → 0,再俯仰 0 → +30 → −30 → 0,循环播放。
9 个姿态 Poses

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的
指标 Metrics
| 测量 | PSD2Live(线上) | 我们的(#181) |
|---|---|---|
| 折叠三角形(面积 ≤ 0) | 0.725 % | 0.048 % |
| 拉伸 中位 / p99 / 最大 | 1.02 / 2.51 / 4.43 | 1.02 / 1.98 / 4.11 |
| 满偏航时脸平均位移(脸半宽) | 0.260 | 0.284 |
| 满偏航时鼻子位移(脸半宽) | 0.316 | 0.630 |
| 满抬头时脸上移(脸半宽) | 0.076 | 0.143 |
| 网格数 / 顶点数 | 26 / 2,784 | 22 / 2,822 |
| 字段大小 原始 / gzip | 1.43 MB / 359 KB | 1.48 MB / 502 KB |
| 生成耗时 | 未单独测(线上 Modal 重烘焙) | 9.0 s(本机 Node,aarch64 CPU) |
逐顶点方向余弦(两者都移动 > 1 px 的顶点)在 8 个边/角关键帧上为 0.84–0.98;满偏航时 RMS 差 17.8 px,PSD2Live 自身 RMS 位移 36.3 px。
37
蓝色及腰长卷发、金色额饰、一侧编发,刘海遮住一只眼。
- 全部检查通过
- PSD2Live:左转时编发从脸侧露出来,读起来像头发有厚度;额饰跟随稳定。
- 我们的:左转时远侧脸颊轮廓变形、远侧眼睛被刘海盖住,编发没有露出;近侧耳朵露出较多。两者的逐顶点方向余弦只有 0.43–0.77,是五个角色里分歧最大的(主要在头发图层)。门禁通过,但门禁不检查“看起来对不对”。
扫动视频 Sweep
左:PSD2Live(线上字段);右:我们的。先偏航 0 → +30 → −30 → 0,再俯仰 0 → +30 → −30 → 0,循环播放。
9 个姿态 Poses

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的
指标 Metrics
| 测量 | PSD2Live(线上) | 我们的(#181) |
|---|---|---|
| 折叠三角形(面积 ≤ 0) | 0.318 % | 0.023 % |
| 拉伸 中位 / p99 / 最大 | 1.00 / 1.94 / 4.32 | 1.05 / 1.98 / 3.99 |
| 满偏航时脸平均位移(脸半宽) | 0.257 | 0.256 |
| 满偏航时鼻子位移(脸半宽) | 0.319 | 0.566 |
| 满抬头时脸上移(脸半宽) | 0.074 | 0.099 |
| 网格数 / 顶点数 | 26 / 3,192 | 21 / 2,787 |
| 字段大小 原始 / gzip | 1.66 MB / 524 KB | 1.46 MB / 488 KB |
| 生成耗时 | 未单独测(线上 Modal 重烘焙) | 14.3 s(本机 Node,aarch64 CPU) |
逐顶点方向余弦(两者都移动 > 1 px 的顶点)在 8 个边/角关键帧上为 0.43–0.77;满偏航时 RMS 差 19.2 px,PSD2Live 自身 RMS 位移 28.4 px。
mara_bob
红棕色齐下巴短发(波波头),写实画风,无头饰。
- 全部检查通过
- PSD2Live:抬头和对角时眼周皮肤图层与脸错开,一只眼周围出现一块颜色不同的补丁、眉毛断开(左上、右上、右下最明显)。头发和轮廓稳定。
- 我们的:左右转更有“立体转头”的感觉,眼周没有补丁;但对角时整张脸倾斜、位移过大,下颌线断开,头顶头发被削平(右上角最明显)。
扫动视频 Sweep
左:PSD2Live(线上字段);右:我们的。先偏航 0 → +30 → −30 → 0,再俯仰 0 → +30 → −30 → 0,循环播放。
9 个姿态 Poses

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的
指标 Metrics
| 测量 | PSD2Live(线上) | 我们的(#181) |
|---|---|---|
| 折叠三角形(面积 ≤ 0) | 0.702 % | 0.005 % |
| 拉伸 中位 / p99 / 最大 | 1.01 / 2.31 / 3.85 | 1.02 / 1.90 / 3.80 |
| 满偏航时脸平均位移(脸半宽) | 0.260 | 0.292 |
| 满偏航时鼻子位移(脸半宽) | 0.310 | 0.638 |
| 满抬头时脸上移(脸半宽) | 0.074 | 0.147 |
| 网格数 / 顶点数 | 22 / 1,621 | 20 / 2,225 |
| 字段大小 原始 / gzip | 861 KB / 191 KB | 1.16 MB / 393 KB |
| 生成耗时 | 未单独测(线上 Modal 重烘焙) | 3.6 s(本机 Node,aarch64 CPU) |
逐顶点方向余弦(两者都移动 > 1 px 的顶点)在 8 个边/角关键帧上为 0.92–0.99;满偏航时 RMS 差 20.4 px,PSD2Live 自身 RMS 位移 32.4 px。
朝霧 朔
男性深棕色短发、碎刘海,写实动漫风,无头饰。
- 全部检查通过
- PSD2Live:九个姿态都稳定,没有明显破面;转动幅度偏小,像平移多于转头。
- 我们的:左右转能看到近侧耳朵和脸侧,转头感更强;对角(左上、右上)时头发与头顶分离、下颌轮廓出现锯齿,右上角脸部明显错位。
扫动视频 Sweep
左:PSD2Live(线上字段);右:我们的。先偏航 0 → +30 → −30 → 0,再俯仰 0 → +30 → −30 → 0,循环播放。
9 个姿态 Poses

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的

PSD2Live我们的
指标 Metrics
| 测量 | PSD2Live(线上) | 我们的(#181) |
|---|---|---|
| 折叠三角形(面积 ≤ 0) | 0.719 % | 0.012 % |
| 拉伸 中位 / p99 / 最大 | 1.01 / 2.03 / 4.23 | 1.01 / 1.88 / 3.38 |
| 满偏航时脸平均位移(脸半宽) | 0.257 | 0.275 |
| 满偏航时鼻子位移(脸半宽) | 0.315 | 0.641 |
| 满抬头时脸上移(脸半宽) | 0.074 | 0.125 |
| 网格数 / 顶点数 | 24 / 1,838 | 20 / 2,123 |
| 字段大小 原始 / gzip | 975 KB / 183 KB | 1.10 MB / 376 KB |
| 生成耗时 | 未单独测(线上 Modal 重烘焙) | 3.0 s(本机 Node,aarch64 CPU) |
逐顶点方向余弦(两者都移动 > 1 px 的顶点)在 8 个边/角关键帧上为 0.89–0.99;满偏航时 RMS 差 22.8 px,PSD2Live 自身 RMS 位移 28.3 px。
局限 Limitations
- 这是一份实验数据,不是视觉验收。角色好不好看由 owner 判断。
- 只有 5 个角色,都是正面半身原图;没有戴帽子或侧脸原图的角色。另有两个画廊角色没放进来:Haru 的部分 rig 图层不通过公开路由提供,我们的 binder 读不到;linwanwan_rose 的
mouth/open.png不通过公开路由提供,本地播放器加载时报 404,两种字段都渲染不了(指标能算:PSD2Live 折叠 0.90 %、我们 0.01 %,我们的门禁通过)。 - 截图来自 SwiftShader 软件渲染,和手机 GPU 上的抗锯齿不完全一致;几何形状一致。
- 扫动视频是逐帧设定姿态再截图,帧间实际间隔约 0.5 秒,所以身体的滞后跟随比真实播放时更“跟得上”。
- PSD2Live 的生成耗时只有 Hiyori 在 #177 里的一次实测(Modal CPU 5.4 秒);我们的耗时是本机 aarch64 CPU 上单次运行,未做多次统计。
- 我们的 binder 只用轮廓估计体积,没有深度网络,也没有 ARAP 求解;常数(鼻子抬起 0.18、深度 0.6、轮廓带 0.85)只在 Hiyori 上手调过。
- Momo 和 Hiyori 的我们字段未通过门禁,在生产里会被拒绝;这里展示它们是为了看清失败的样子。
下一步实验 Next experiments
- 把满偏航时的平移量(尤其鼻子和前发)压到 PSD2Live 的水平附近,再看对角处的脸颊截断和发际线肤色块是否消失。
- 对角处的近侧轮廓带:判断 p99 ≤ 2.5 的拉伸门禁是否够,还是需要真实几何(深度或法线,例如 MoGe-2)。
- 耳朵和侧发的逐关键帧绘制顺序/透明度,Momo 的耳饰和耳朵跳变是首个用例。
- 在 Live2D 官方样例(Hiyori、Haru 等)上与其手工制作的 AngleX/Y 渲染做 LPIPS/SSIM 对比。
- #181 合并
feat/head-field-compact后,用同一份压缩看两种字段的残差和体积。