VOL.01 / 2026
展示分析 · 技术开发 / Bug / 代码优化

对于手部渲染问题排查和解决

2026.06.14 · 系列「项目-Emg训练数据管理平台」

发现连续手手势csv在回放时 3d 手部显示很奇怪,问题首先定位两个方向:

  1. 采集App 的采集问题
  2. 前端渲染问题
  3. 后端解析问题

其实可能性1的概率并不大,因为关节角度每一列本身在整段记录中的变化范围都是合理的,所以问题大概率发生在 CSV→解析→特征/姿态→Three.js 渲染这条链。

让claude有侧重点的去查之后,claude 返回是 前端rig 渲染问题,我们让claude 去修复,中途还因为缺乏权限问题,我无法到本地demo前端界面进行验证,让它给管理员重置密码,然后我上去校验。

然而并没有改好,依旧不理想。claude仅仅是使用了自己造的数据进行了smoke 测试和截图,我上传我采集到的真实数据时,原形毕露。

我原样反馈了我发现的情况,让claude 使用我提供的数据进行测试验证(我给出了emg2pose的数据,我采集的数据,neruopose 的wrist 数据)。给出新的根因报告,明确“用户实测失败”的原因。再给修复方案,不接受仅靠 clamp/AA 缩放/灯光材质把视觉压正常。

然后claude这次去查的很彻底,但是结果也很打击:

没有权威 emg2pose FK 约定时,当前三份只有角度的数据要么无法修到可用,要么必须允许受约束推导。

说白了,就是这三种数据差异过大,不同的关节角度语义没对齐,它无论如何去挑都没办法。

我想到了映射层,我先让 Claude 暂停继续调 UI,先读源码推翻/重建数据契约。尤其是三类数据来源不同,强行用一套 joint_angles 映射解释所有文件,很可能永远调不稳。我先拉一个空目录,将规则、数据文件拷贝进去,让claude 重新制定方案。

1.建立独立小项目,不读取主项目文档作为事实,只以样本文件和提取脚本结果为准。
2. 支持 CSV 和 HDF5 样本,先用脚本提取为统一 JSON,再由前端读取。
3. 前端用 Three.js 做可交互 viewer:选择样本、播放、拖动时间轴、切换 rig/convention preset。
4. 必须覆盖三个验收样本:
   - EMG_1781418395207.csv
   - 2022-11-18-1668758400-843cb-cv-emg-pose-demonstration@2-recording-6_right.hdf5
   - wrist_user_006_dataset_001.hdf5
5. 对比多种 FE/AA 映射、骨架几何和 wrist-only 路径,记录每个方案的效果。
6. 不追求炫技,不引入重依赖;目标是验证姿态约定和可移植实现。

Claude 很快就做出了demo,20min左右,我检查发现效果还是很差:

看来,单单从数据内容层面是无法还原各个数据的实际意义,应该去推导这些数据背后的意义。

例如我的采集数据的数据源是Mediapipe ,使用的21个landmark然后推算出的关节角度。而emg2pose 和 neruopose 是使用的自定义的关节角度映射。

我在提出反馈之后,claude又回去读了采集端app 的代码:

claude 推荐 改采集app输出,改为使用 mediapipe 默认输出格式landmark,很适合前端界面显示。(的确)。但是我也指出了csv的输出数据不单纯是考虑可视化,而是要作为训练数据和其他hdf5数据达到一个统一的效果。允许改,但是要从设计角度考虑:对比另外两种hdf5数据(尤其是emg2pose 送入模型的数据类型(好像是关节角弧度)),单纯改landmark会失去作为训练数据的价值,如果emg2pose的数据存储的关节信息是是关节角弧度,那么要求最终采集送入模型的数据csv数据那也是同样的信息价值。

所以我们开始设计。

数据层面推理

我将不同数据源相关文件拷贝进了这个demo实验目录,做数据层面的分析,得出结果:

现在有三种数据:

  1. emg2pose 的 HDF5
    • 它的标签是 joint_angles[20]
    • 这些角度不是普通几何角,而是 UmeTrack 手模型里的关节参数
    • 适合训练,也能通过官方 FK 推出手部关键点
  2. generic-neuromotor-interface 的 HDF5
    • 它主要是 wrist_angles
    • 是腕部任务,不是完整手指任务
  3. 我们采集 App 的 CSV
    • 现在写的是 MediaPipe 算出来的几何角
    • 虽然列名也像 INDEX_MCP_FE,但含义和 emg2pose 的 joint_angles 不是一回事
    • 所以不能直接和 emg2pose HDF5 混在一起训练

我提议:不要把目标定成“CSV 修修补补”。目标应该改成:采集 App 输出一种新的统一数据格式,最好 HDF5,里面同时保存原始证据和训练标签。但是更进一步,**我们将这一层数据转换,放到我们的数据管理平台来做更适合,将mediapipe的原始结果直接写入采集文件!**考虑放弃计算旧几何角,而是直接写mediapipe坐标数据。还能提高采集性能!

我们在浏览器上模拟跑了一遍集成,效果不错!

这是针对emg2pose的训练数据的效果:

针对自己采集的数据、Mediapipe算出的21个关节点:

针对emg2pose 和 mediapipe 的数据的区别是,mediapipe在大鱼际多一个坐标点,所以为了兼容,我们在传emg2pose的关节坐标的时候,不计算但是保留。

对比图:

这是emg2pose的顶视图:

这是mediapipe的顶视图(大拇指多一个端点):

我们优化采集设备,

然后我们用新采集的landmark 做可视化测试:

目前原始 landmark 数据已经可用,真实手的骨架和 mesh 可视化也已经达标;但从这些 landmark 反解出来的 IK joint_angles 作为训练标签时,质量一般,所以不能无脑当“全帧高质量标签”用,必须带 ik_residual_mmjoint_angles_valid,训练时按质量过滤。

我发现当前真机 landmark 约 16fps,需检查是否由相机配置、MediaPipe 推理、线程阻塞、写盘/zip、UI 渲染导致。如果能低风险提高到 30fps,可以考虑下一轮迭代修复。帧率从 15fps 提到 30fps 的好处是:

  • 动作更连续,训练时序更密;
  • 快速动作时更少丢帧;
  • 可做更稳定的时间对齐;
  • 若低 fps 是因为推理卡顿/运动模糊导致,确实可能降低一部分 IK 残差。

但它不一定能显著降低 单帧 IK residual。因为这次 13mm median 的主要来源大概率是:

  • MediaPipe worldLandmarks 的深度估计噪声;
  • 单目相机对手掌深度/拇指位置不稳定;
  • UmeTrack 手模型和 MediaPipe 21 点定义并非完全同源;
  • 拇指本来就是 IK 最弱点。

所以提高 fps 是值得做的工程优化,但不是“解决 IK 标签质量”的唯一钥匙。

总结而言:对比旧的“安卓端计算关节角度”相比:总体是明显提升。

旧方式它算出来的角度看起来每帧都有,但语义不对。它是 MediaPipe 几何夹角,FE/AA/拇指定义都和 emg2pose 的 UmeTrack 轴角不是一回事。尤其拇指和 MCP_AA 偏差很大,混进训练会污染标签。

新方式至少保留了原始真源:landmarks 落盘后,以后 IK 算法改进可以重新转换,不需要重采。