← Ego Platform · 报告打开 Test200 v3 可视化 ↗

HOT3D QUEST3 / GROUND TRUTH

HOT3D 构建 GT

从原始手部参数、双目图像和相机标定出发,经过 GT 一致性筛选、可见性审核与 ScaleHP 21 点转换,得到可追溯的 Test200 题集。

实现快照:2026-10-15 · 当前题集:Test200 v3 · 来源:已冻结题集证据与仓库实现

1,281本地完整候选 / 官方清单 1,288
200当前题集 Case
7 / 84参与者 / 录制 sequence
150 / 15每段总帧 / 空间评分帧
01固定来源原图、标注、标定
02筛选候选一致性 + 小手规则
03人工审核可见性与替补确认
04构建 21 点MANO → ScaleHP
05独立冻结新版本与来源审计

01 · 数据从哪里来

当前候选池取自固定版本 HOT3D-Clips 的 train_quest3 清单。官方清单含 1,288 段,本地已完整保存并校验其中 1,281 段,覆盖 7 位参与者、133 段录制、192,150 帧。Test200 是在这些候选中构建的平台评测集合,并非 HOT3D 官方 test split。

输入提供什么构建用途
两路灰度 JPG1201-1 / 1201-2,每 Case 150 帧冻结双目输入及人工检查原始画面
__hand_shapes.json__个体 MANO / UmeTrack 手形解码相同个体的手部几何
*.hands.json左右手姿态参数与腕部变换MANO 顶点/关节与 UmeTrack 关键点
*.cameras.json逐帧相机内参、模型与外参世界 → 相机变换及双目投影
*.hand_crops.json官方手部目标条目确定该手帧是否 eligible
*.info.json原始参考时间戳同步帧身份与时序评分

候选池中的 annotations/*.tar.gz 只是从原 TAR 逐字节抽取的 JSON 成员,不包含图像,也不是重新标注的 GT。解码使用已同步的 MANO 资产及固定 toolkit;不通过模型预测反推 GT。

来源版本与缺失候选

HOT3D 来源版本:30fe9674782f32e1e5edba98476b6ff4300132c5
Hand Tracking Toolkit:950d64f7e8d2ba1fd38cd2ceede6608a8fa7f5aa

未计入候选的 7 段:000239, 000328, 000335, 000454, 000527, 000578, 001091(均为 clip- 前缀)。不把不完整源文件当作可用样本。

02 · GT 如何筛选

筛选只依赖 GT 参数、相机投影与人工图像检查。预测误差、预测缺手、榜单分数均不参与筛选或候补排序。

第一层:MANO 与 UmeTrack 的指尖一致性

在同一帧、同一只手、同一坐标系内,计算两种参数化手模型对应五个指尖的绝对欧氏距离,单位 mm。不做刚体对齐,腕点不纳入这层筛选。

d(h, finger, t) = 1000 × ‖MANO_official_tip − UmeTrack_tip‖₂
D = max(h, finger) median_t d(h, finger, t)
T = max(h, finger) P95_t d(h, finger, t)
要求当前阈值判定范围
有效配对每只出现的手 ≥ 80 帧150 帧内;官方目标配对完整
最差指尖中位数 D≤ 12 mm取所有有效手 × 五指中的最大值
最差指尖 P95 T≤ 16 mm每手每指先沿时间统计,再取最大值
最差手拇指 P95≤ 12 mm对拇指单独收紧约束
一致性筛选使用 MANO 官方指尖顶点 [744, 320, 443, 554, 671]。它评估两种 GT 表示是否一致,不等于独立的物理精度证明,也不能保证图像中手部可见。历史初筛曾使用 T≤20 mm;当前最终规则为 T≤16 mm。

第二层:小手与低活动同时命中

每只手独立检查 60 帧窗口,步长 15 帧,起点为 0、15、…、90。窗口至少包含 48 个 eligible 手帧,以下两个条件同时成立时命中;任一只手任一窗口命中,剔除整个 Case。

条件计算方式阈值
小手每帧在两路相机分别计算 GT21 未裁剪包围框长边 / 图像短边,再取两路较大值尺度严格 <8% 的有效帧占比 ≥80%
低活动在掌部局部坐标中,21 点相对窗口逐坐标中位数的平均位移,再对各帧取 P95P95 ≤5 mm
局部坐标与百分位的准确实现
origin = P[5]                              # 腕点
x = normalize(P[8] − P[17])               # 食指 MCP − 小指 MCP
v = P[11] − P[5]                          # 中指 MCP − 腕点
y = normalize(v − dot(v, x) × x)
z = cross(x, y)
local = (P − P[5]) @ stack(x, y, z)
center = coordinatewise_median(local over eligible frames)
shape_t = mean_j ‖local[t,j] − center[j]‖₂ × 1000
shape_P95 = percentile(shape_t, 95, method="linear")

该指标去除了整体平移和旋转,测量手形变化;不是腕部速度。没有“必须在画面下方”“必须垂直下垂”的位置条件。单独低活动不会触发剔除,窗口不足 48 个有效帧也不能按此规则判定。

原 Test200 的复筛中,这条规则命中 31 个 Case、183 个窗口。这是对原 200 个 Case 的结果,不是对全候选池的统计。最新 200 个 Case 的同规则扫描未命中。

第三层:人工可见性审核与候补

逐段查看双目原图、四个手部特写和三维骨架,记录遮挡、不可见、出画、贴合异常等问题。官方 crop 条目表示手帧可计分,不能替代真实可见性判断;数值门槛通过后仍可能被人工剔除。

保留通过审核的原 Case。候补在满足相同数值门槛和既有剔除清单后,按当前参与者数量、参与者 ID、当前 sequence 数量、拇指 P95、D、T、clip ID 确定性排序;每段 sequence 最多 5 个 Case。候补还须经过图像预检及人工确认。

03 · 参数如何转换为冻结 GT

MANO 解码

读取个体 10 维手形、逐帧 15 维 PCA 姿态及腕部旋转/平移,使用对应左右手 MANO 模型做前向计算。沿用 toolkit 的左手 shapedirs 修正及非 flat hand mean 配置,得到每只手的 778 个顶点与原生关节。这里是 GT 参数解码,不是运行 ScaleHP 预测模型。

保留前 16 个 MANO 关节,追加五个 ScaleHP 指尖顶点,再按下节的明确顺序重排。左右手使用相同语义索引,不通过预测匹配交换左右手。

世界坐标 → 左相机 native 坐标

P_ref = inverse(T_world_from_cam0) × P_world
P_cam1 = inverse(T_world_from_cam1) × T_world_from_cam0 × P_ref

最终 points_scalehp21 固定为逐帧左相机 1201-1 的 native 坐标,单位 米。右相机投影使用该帧外参变换。3D 不因为图像旋转而旋转坐标轴,显示误差时才从米转为毫米。

双目投影与图像方向

使用原生相机模型投影(保留畸变模型),每路分别从世界点得到 native 像素,再对像素和原图做顺时针 90° 旋转。若 native 图像为 W×H:

(u_upright, v_upright) = (H − 1 − v_native, u_native)
(W_upright, H_upright) = (H, W)

只做 CW90,不额外缩放、裁剪、拉伸或去畸变。二维点使用 upright 像素坐标;越界/不可投影点保留可用性语义,不能把它们拉回图像内以制造可见性。

可计分与时间同步

每手帧的 eligible 由官方 hand_crops 目标条目确定,并核对 MANO 参数是否可解码。缺少官方目标的手帧可有几何数据,但不据此升级为 eligible。逐帧保留 ref_timestamp_ns;视频、标定、GT 和播放帧编号共用 0…149 的身份。

04 · ScaleHP 的 21 点取点规则

此处“ScaleHP”指平台冻结的 scalehp-mano21-tips-v1 点定义。索引从 0 开始。五个指尖在前,腕点是 5,拇指 CMC 是 20。

tips = [744, 333, 444, 555, 672]   # 拇指、食指、中指、无名指、小指
raw = concat(J_mano[:16], V_mano[tips])
order = [16,17,18,19,20,0,14,15,1,2,3,4,5,6,10,11,12,7,8,9,13]
points_scalehp21 = raw[order]
01234567891011121314151617181920索引与连边示意 · 非真实手部坐标

拇指链:5 → 20 → 6 → 7 → 0。其余手指从腕点连接各自 MCP、PIP、DIP、指尖。完整骨架共 20 条边。

输出索引语义MANO 来源
0拇指指尖
thumb_tip
顶点 V[744]
1食指指尖
index_tip
顶点 V[333]
2中指指尖
middle_tip
顶点 V[444]
3无名指指尖
ring_tip
顶点 V[555]
4小指指尖
pinky_tip
顶点 V[672]
5腕点
wrist
关节 J[0]
6拇指 MCP
thumb_mcp
关节 J[14]
7拇指 IP
thumb_ip
关节 J[15]
8食指 MCP
index_mcp
关节 J[1]
9食指 PIP
index_pip
关节 J[2]
10食指 DIP
index_dip
关节 J[3]
11中指 MCP
middle_mcp
关节 J[4]
12中指 PIP
middle_pip
关节 J[5]
13中指 DIP
middle_dip
关节 J[6]
14无名指 MCP
ring_mcp
关节 J[10]
15无名指 PIP
ring_pip
关节 J[11]
16无名指 DIP
ring_dip
关节 J[12]
17小指 MCP
pinky_mcp
关节 J[7]
18小指 PIP
pinky_pip
关节 J[8]
19小指 DIP
pinky_dip
关节 J[9]
20拇指 CMC
thumb_cmc
关节 J[13]
指尖一致性筛选:官方 MANO最终 GT:ScaleHP
拇指744744
食指320333
中指443444
无名指554555
小指671672
三个容易混淆的定义:冻结 GT21 使用 points_scalehp21;历史 points_canonical20 只是前 20 点,缺少拇指 CMC;原生 UmeTrack 的索引 20 是掌心,而非拇指 CMC。三者不能直接互换。报告中的 MANO 网格、UmeTrack21 为独立展示图层,评分仍使用冻结 ScaleHP21。

05 · 如何冻结、验证与评分

先在独立开发数据根构建,再发布新版本目录。对于沿用 Case,保留 GT、标定、时间戳、视频输入及预览的原始字节;新增 Case 从同一来源解码 GT、旋转原 JPG 并编码为 FFV1 无损 MKV。PNG 精确帧通过按帧号解码该 MKV 获得。

产物内容与约束
GT JSONL150 帧;每手 eligible、ScaleHP21、双目 UV、原始时间戳
frames / calibration图像帧与时间戳对应、逐帧相机参数、CW90 像素变换
selection / inputs manifest明确 Case 清单、输入身份、GT 版本、点定义和来源
review / approval / audit保留原审核记录、后续确认、筛选规则与解码审计;不伪造历史审核状态
冻结输入与工具 ZIP输入图像、清单、模板及工具;正式输入下载包不含 GT

参数重建支持 --verify-against:核对 150 帧身份、eligible 和坐标,XYZ 最大差异要求 ≤10⁻⁷ m;独立投影核对要求 <0.02 px。冻结/发布验证绑定来源、标定、时间戳、清单和文件身份,拒绝覆写已有版本。

空间正式评分取 0,10,…,140 共 15 帧;时序评分使用全部 150 帧。可视化报告的 Abs-MPJPE21 曲线展示 150 帧,正式 Case 汇总仍沿用原评测的 15 帧口径;不可用帧断线,不填零。

Abs-MPJPE21 不做对齐;RR-MPJPE21 分别减去 GT/预测的腕点 5,仍对全部 21 点求均值,包含归零的腕点。当前报告只在 GT、输入、标定和时间戳完全一致的 199 个 Case 上对照历史 v2 预测;新增 clip-000607 无预测。

06 · 当前题集与版本边界

版本这次演进做了什么历史处理
Test200 v1原冻结 200 Case,后续复筛发现 31 个“小手/低活动”候选保留原题集与成绩
Test200 v2叠加小手规则及人工复核,最终保留 v1 的 165 个、加入 35 个;85 个 sequence独立 GT / 输入身份;不回写 v1
Test200 v3 · 当前保留 v2 的 199 个;因不可见剔除 clip-000422,加入已确认的 clip-000607;84 个 sequence保留 v2 中的 clip-000422 和旧评测

当前参与者分布:P0002 17、P0003 53、P0010 22、P0013 50、P0017 24、P0018 14、P0021 20。每 sequence 最多 5 个 Case。

新题集改变的是样本集合及其冻结身份,不改变 ScaleHP 21 点定义、米制 native 坐标或原八项评分口径。199 个重叠 Case 的历史分数不合成为“新 200 Case 成绩”;完整 v3 成绩应来自新的完整提交。

Test200 的选样不是随机抽样,也不保证与模型训练参与者隔离。解读结果时应同时报告题集版本与来源;MANO/UmeTrack 一致性和人工可见性审核均有各自局限。

07 · 实现入口与复现路径

实现 / 证据职责
metadata/candidate-index.jsonl候选来源索引,含 D/T/拇指摘要及原始参数相对路径
history/reselection/screening/scan_official_pool.py官方指尖与 UmeTrack 的逐帧差异统计;历史扫描的 T≤20 标签不能当作当前最终通过判定
evidence/selection-policy.json当前 D12/T16/拇指12、候补与人工剔除的冻结政策;以 approval.json 记录后续确认
scripts/screen_hot3d_gt.py可复现的小手/低活动窗口判定
scripts/decode_hot3d_gt.pyMANO 解码、ScaleHP 取点、坐标与双目投影、重建一致性验证
scripts/freeze_hot3d_review.py在开发写根暂存新题集、媒体、清单、下载包和审计
scripts/publish_hot3d_revision.py只读预演;显式授权后发布新版本资产
scripts/build_hot3d_gt_review.py
scripts/hot3d_review_geometry.py
从冻结 GT / 历史证据生成 review 数据、MANO 网格和原生 UmeTrack21
src/ego_platform/hot3d_pose.py
docs/benchmark.md
21 点语义、连边、评分帧与题集契约
复现单 Case 的 GT 解码与窗口筛选

使用有 NumPy、torch、MANO 的环境;先配置 EGO_ENV=dev 和自己的 EGO_DATA_ROOT。以下为参数示例,输出必须在独立开发写根内。

PYTHONPATH=src python -B scripts/decode_hot3d_gt.py \
  --pool /path/to/hot3d-gt-candidate-pool \
  --clip-id clip-000607 \
  --output /path/to/own-dev-root/tmp/clip-000607.jsonl \
  --verify-against /path/to/frozen/clip-000607/gt.jsonl

PYTHONPATH=src python scripts/screen_hot3d_gt.py \
  --gt /path/to/own-dev-root/tmp/clip-000607.jsonl \
  --calibration /path/to/frozen/clip-000607/calibration.json

解码和筛选不会自动选满 200 个、覆盖正式 GT 或触发模型评测。后续仍须按相同标准选样、人工确认、冻结新版本并按发布流程上线。

来源校验保留已有参数、GT 与冻结证据身份检查。已有大输入的校验回执可以在满足冻结发布工具的复用条件时显式复用;不把复用回执描述成重新计算了 SHA,也不为展示报告反复扫描原 TAR/MKV。