GEAR 完整复现(CVPR 2026 Findings)—— 5 阶段全跑通

EPPUR · 2026-06-27 · repo VIPL-VSU/GEAR · 数据 gear.zip(SAPIEN 多视角)· 新建 conda env gear(torch2.4.1+cu124)· H100

一句话:复现成功

box_100154(一个带 4 个铰链盖的箱子)上端到端跑完 GEAR 的 5 个阶段:SAM mask → coarse GS → 体素化抽关节 → 几何-运动交替精修 → 渲染评测。GEAR 正确分出"底座 + 4 个翻盖"5 个部件、估出 4 条铰链轴,并产出官方关节指标(轴角误差均值 0.0266、轴距 0.0061、运动量误差 0.064、动件 Chamfer 0.155)。
亲眼渲染核对:GEAR 预测的部件分解 + 关节轴。底座=灰,4 个翻盖=红/蓝/绿/黄(各为独立部件),黑线=估出的 4 条铰链轴(沿箱体四条边)。左=START(合)/ 中=END(4 盖各绕铰链转开)/ 右=正视露出空腔。与"4 铰链盖箱子"真实结构一致。

GEAR 是什么(5 阶段)

2D Gaussian Splatting 的铰接物体建模:① SAM 出 2D mask;② coarse GS 拿全局几何;③ 两态占据体素化 + Top-K 连通分量抽动件、初始化关节;④ 几何-运动交替精修(GEAR 核心,训练日志可见 Phase=E/M 交替);⑤ 渲染 + 评测(轴角/轴距/Chamfer)。

跑通证据(box_100154)

stage2 coarse:30000 iters ~12min,两态各 100 相机,depth 初始化 ~55k 点 → point_cloud_0/1.ply + larger_motion_state.txt(判出 State 0 = Source)。
stage3 voxelize:24789 体素,slots=5 matched=4,关节类型 s,r,r,r,r → joint_voxel_info.npy
stage4 GEAR train:30000 iters ~26min,5 关节(1 静 + 4 转)从体素初始化,日志可见 Phase=E/M 交替
stage5 render/eval:result.csv(关节指标)+ joint_info.json(运动学树 root heavy + 4 hinge,每个带 axis origin/direction)+ 部件/轴 mesh。
关节指标(均值)
轴角误差 avg_angle0.0266
轴距误差 avg_distance0.0061
运动量误差 avg_theta_diff0.0638
动件 Chamfer avg_CD_dynamic0.1549
整体 Chamfer avg_CD_whole0.8382

PSNR/SSIM/LPIPS = −1:该数据集无 test 划分(test 相机=0),--skip_test 下外观指标不计算;几何/关节指标是这条线重点,正常产出。

⚠️ 修了 4 个 repo 自带的 bug(都贴了底层证据)

① 仓库提交了未解决的 git 合并冲突(<<<<<<< HEAD … >>>>>>> main,只有一个 "init clean" commit)。train_coarse.py 的是平凡冲突(只差引号)。utils/other_utils.pyget_larger_motion_state 非平凡:main 一侧引用文件里从未初始化的变量(cano_gs/opacities…),合并时丢了代码、无法运行;HEAD 一侧 + 标记后的 else/return 恰好是完整可跑函数,且 cal_cluster_centers 无人调用,下游 stage3 也只要 point_cloud_{0,1}.ply+larger_motion_state.txt取 HEAD 侧清干净
② dataset_readers.py:Image.fromarray(...,dtype=np.byte) 新版 Pillow 拒绝 RGBA → 改 np.uint8
③ artgs.py:287:渲染期用了不存在的 args.iterations → 改 getattr 兜底。
tensorboard(log_utils 要)补装;依赖 pin numpy/pandas/scipy/sklearn 要 py≥3.11(与 README 的 3.10 自相矛盾)→ 非关键包松绑版本。

全部 10 个 sapien scene 跑完(8 卡并行,5 阶段全绿)

每 scene 一卡 ~45min 全完;figs/gear_<scene>_seg.png 逐件亲眼渲染核对(逐部件着色 + 关节轴 START|END)。

scene部件(关节)轴角°轴距运动量动件CD整体CD评价
box_100154底座+4铰链盖0.0270.0060.0640.1550.838
bucket_100481体+2摆件0.0000.0030.0240.0840.662
door_9168底座+2门0.0000.0030.0580.1140.276
knife_101068柄+3刀片折叠0.1410.0010.0730.2011.271✅ 折叠
eyeglasses_101284框+2镜腿折叠0.0450.0000.0470.0410.091✅ 折叠
refrigerator_10655体+2门0.0270.0010.0310.1641.077
oven_7187体+2件0.0310.011119.9226.622.1⚠️ 轴对/运动量崩
clock_6843体+2件0.0330.0000.0003.073.09⚠️ 重建CD高
storage_45271体+6抽屉门7.430.0030.09322.10.906❌ 1个轴差44.5°
faucet_1028体+龙头/出水31.90.21145.50.20167.3❌ 旋转抓不住
分化结论:GEAR 在铰链门/盖/折叠类近完美(box/door/bucket/knife/eyeglasses/fridge 轴角 <0.15°);多自由度/旋转/多关节类失败——faucet 旋转龙头 31.9°、storage 7关节里 1 个 44.5°、oven 轴对但运动量错(θ=119)。PSNR/SSIM/LPIPS=−1 因数据集无 test 划分。
knife_101068(✅折叠刀):柄(红)+ 刀片(蓝/黄/绿)折出。START|END。轴角 0.14°。
faucet_1028(❌):龙头(红)+ 手柄(蓝)+ 出水口(绿)。START|END 两态几乎没动 → 旋转自由度抓不住,轴角 31.9°。
storage_45271(❌,7关节):体(红)+ 6 抽屉/门(多色)。多数对,1 个门轴差 44.5° 拉高均值。

复杂连杆机构:折叠台灯(串联链)—— 自造输入,实测 GEAR 局限

GEAR 自带数据没有台灯,且其关节树是星形拓扑(joint_info 每个关节 parent=0 全挂 root),结构上表示不了串联链。为实测,我自造了 PNM 折叠台灯 13928 的 GEAR 输入:写 render_lamp_gear.py(pyrender EGL)解析 SDF 的 4 铰串联运动学树(base→静态底座→joint→臂→link0→link1→灯头),FK 算两态(rest/展开),每态渲 100 视角 rgba+depth+实例mask+点云。踩坑修掉:PNM 黑色材质→近黑渲染→GS 在 iter 700 把高斯剪到 0 崩,改每 link 亮色纯材质后稳过。
自造台灯输入(4 视角,每 link 一色:灰底座/橙大臂/红link0/蓝link1/绿灯头),两态多视角喂给 GEAR。
GEAR 抽出关节类型最近 GT轴角差
joint_2hingebase→臂(主导铰链)0.0°
joint_1hingelink0→link126.4°
joint_3hingelink0→link133.9°
joint_4slider(误判)link0→link130.0°
坐实星形拓扑局限:GEAR 只抓对了主导的底座铰链(0°),远端 3 个串联铰链轴差 26-34°、1 个铰链误判成滑轨,而且 4 关节全 parent=0 星形 —— 串联链结构被彻底压平(GT 是 5 节父子相连)。voxelize 阶段 matched=1(只干净匹配出 1 个动态分量)印证:整条臂相对底座的运动被并成 1 块。
台灯 GEAR 结果(START|END):分出 4 动件 + 静态,但关节全挂 root(星形),串联链拓扑丢失。

数据集 10 个 sapien scene 全解压在 data/gear/sapien/;台灯输入由 render_lamp_gear.py 生成。报告 EPPUR/experiments/gear_repro_20260627/REPORT_GEAR复现_20260627.md