【免费下载链接】WiLoR
WiLoR: End-to-end 3D hand localization and reconstruction in-the-wild
WiLoR 是一个端到端的 3D 手部定位与重建模型(CVPR 2025),它能从一张普通照片里直接"算出"一只手的 3D 网格。对开发者来说,最有价值的就是它的输出数据:verts(网格顶点)、joints(3D 关键点)、cam_t(相机参数)和pred_mano_params(MANO 姿态参数)。本文带你逐字段读懂这些输出,并亲手把它们变成可在 Unity、Blender、three.js 中使用的.obj3D 资产,为 AR 手部交互铺好路。
WiLoR 能做什么?
WiLoR 的思路是"定位 + 重建"二合一:先用检测器在画面中框出手部,再由一个 ViT 网络直接回归出 MANO 手部模型参数,最终生成带皮肤网格的 3D 手。
它面向"in-the-wild"(真实场景)图像,无论是篮球比赛、办公桌面还是多人合影,都能稳定输出 3D 手。
运行 WiLoR 拿到输出数据
想拿到原始输出数据,最简单的入口是仓库自带的demo.py。加上--save_mesh参数,它会自动把每只手导出成.obj文件:
python demo.py --img_folder demo_img --out_folder demo_out --save_mesh --fast
--fast开启半精度 + 层裁剪,推理速度最高提升 1.6 倍,精度损失极小(Δ-MPJPE ≈ 0.05mm)。
运行后,输出目录里会出现两类文件:
{图片名}.jpg:3D 网格叠加回原图的可视化结果{图片名}_{n}.obj:第n只手的 3D 网格模型文件
如果你只想要交互式体验,也可以跑 gradio_demo.py 启动本地网页版。
逐字段解读 4 类核心输出
模型前向传播(见 wilor/models/wilor.py)会返回一个字典out,这是所有下游开发的起点:
| 输出键 | 形状 | 含义 | 典型用途 |
|---|---|---|---|
pred_vertices | (778, 3) | 手部网格顶点,单位米 | 生成.obj、做 AR 渲染 |
pred_keypoints_3d | (40, 3) | 40 个 3D 关键点(15 骨骼 + 25 顶点) | 手势识别、手部追踪 |
pred_cam | (3,) | 弱透视相机(s, tx, ty) | 裁剪坐标恢复 |
pred_cam_t | (3,) | 相机平移t(米) | 世界系定位 |
pred_mano_params | dict | global_orient/hand_pose/betas | 驱动参数化手、重姿态 |
verts —— 778 个 3D 顶点
pred_vertices是最核心的一份数据,形状(778, 3),对应 MANO 手部模型的标准顶点布局,坐标以米为单位,原点在手腕附近。它和固定的面片(faces)一起,就构成了一个完整的封闭手网格。
小技巧:左手网格需要沿 x 轴镜像。
demo.py里用verts[:,0] = (2*is_right-1)*verts[:,0]一行就完成了左右手的对称处理。
joints —— 40 个 3D 关键点
pred_keypoints_3d包含 40 个点:15 个 MANO 骨骼关节(手腕 + 各指关节)+ 25 个从顶点索引采样的点(指尖、掌面等)。做手势识别或逐帧手部追踪时,用这份稀疏关键点比整网格更轻量、更好用。
cam_t —— 弱透视相机参数
pred_cam_t把网格从"手部局部系"平移到"相机系",单位同样是米。拿到verts + cam_t,你就拥有了在 3D 空间里摆放这只手的全部信息——这正是 AR 场景需要的。
pred_mano_params —— 可驱动的参数
这是 WiLoR 的"隐藏福利":它输出的不止是网格,还是一套可参数化驱动的 MANO 参数:
global_orient:手腕朝向(3×3 旋转矩阵)hand_pose:15 个手指关节的姿态betas:10 维形状 PCA 系数(控制手的大小胖瘦)
有了它,你不仅能"看"这只手,还能换姿势——把参数喂回 MANO 模型即可生成新的手形,适合做动画与交互。
从 verts 到 .obj:网格导出全链路
导出逻辑集中在 demo.py 的两行:
tmesh = renderer.vertices_to_trimesh(verts, cam_t, LIGHT_PURPLE, is_right=is_right) tmesh.export(os.path.join(out_folder, f'{img_fn}_{n}.obj'))其中vertices_to_trimesh(见 wilor/utils/renderer.py)做了 4 件关键的事,决定了.obj能否被引擎正确读取:
- 平移:
verts + cam_t,把网格放进相机/世界空间; - 左手翻面:左手使用
faces_left(顶点序反转),保证法线朝外、不被"看穿"; - 旋转 180°(绕 x 轴):把 MANO 模型转成引擎常见的正向显示姿态;
- 着色:给顶点赋上淡紫色,导出后一眼就能认出。
最终生成的.obj结构非常标准:
v 0.012 0.034 0.021 # 顶点,共 778 行(单位:米) f 93 39 235 # 三角面,共 1523 行因为 MANO 本身就是 778 顶点 + 1509 面,WiLoR 额外补了 14 个面让手掌"水密"(见 renderer.py),所以导出的.obj是可直接渲染的封闭网格,导入 Blender / Unity / three.js 都不会破面。
实战:AR 手部交互与 3D 资产开发
① 导出 .obj 作为 3D 资产
verts导出成.obj后,就是一个标准的低模 3D 资产:
- Blender:直接
File > Import > Wavefront (.obj),即可做雕刻、贴图、批量建模; - Unity / Unreal:导入后作为手部预制体,用于角色动捕重定向;
- Web (three.js):用
OBJLoader加载,即可在浏览器里做 3D 手展示。
注意单位是米,导入引擎后记得检查缩放,避免手"穿模"或"巨大化"。
② 用 verts + cam_t 做 AR 手部交互
在 AR 应用里,典型闭环是:
- 跑 WiLoR 得到
verts和cam_t; - 用相机内参(默认
FOCAL_LENGTH=5000,见 model_config.yaml)把verts投影回屏幕,做虚实对齐; - 用
pred_cam_t把网格放进真实世界坐标系,实现"手长在你手的位置"。
仓库里的project_full_img(demo.py)就是一个现成的 3D→2D 投影实现,可直接参考。
③ 用 MANO 参数驱动手势与动画
若你的 AR 应用需要持续追踪 + 换姿势,优先使用pred_mano_params:
- 逐帧取
hand_pose变化,可做手势状态机(如"握拳/张开"); - 把参数喂回 MANO 封装,生成平滑过渡的中间手形,减少抖动。
常见问题 FAQ
Q:为什么导出的左手网格是反的 / 法线朝内?A:左手必须沿 x 镜像并翻转面片朝向。WiLoR 已在demo.py与vertices_to_trimesh中处理,自己扩展时别漏掉这两步。
Q:.obj里的坐标是什么单位?A:米。MANO 标准布局,原点约在手腕。导入引擎后注意缩放。
Q:只想要 2D 关键点怎么办?A:用project_full_img(verts, cam_t, focal, img_size)把 3D 顶点投影到 2D 即可,无需再跑 2D 检测。
Q:多只手怎么区分?A:demo.py会按检测框逐只手输出,文件名带_0、_1后缀,分别对应画面中不同手。
小结
WiLoR 的输出是一份"开箱即用"的 3D 手部数据:verts决定网格、cam_t决定位置、joints决定手势、mano_params决定驱动。理解了这 4 类字段,你就能用 demo.py 一键导出.obj,快速接入 AR 手部交互与 3D 资产管线。想深入细节,可对照 wilor/models/wilor.py 的前向传播与 wilor/utils/renderer.py 的网格导出实现。
【免费下载链接】WiLoR
WiLoR: End-to-end 3D hand localization and reconstruction in-the-wild
相关推荐
从秒级监控到数据资产:Netdata多格式数据导出全攻略
从秒级监控到数据资产:Netdata多格式数据导出全攻略 你是否还在为监控数据的碎片化存储而困扰?是否尝试过将实时监控指标与历史趋势分析结合却受制于格式不兼容?
可观测性指标监控告警异常检测运维超简单Iced表格开发:从数据展示到交互实战
超简单Iced表格开发:从数据展示到交互实战 你还在为Rust GUI开发中的表格组件头疼吗?跨平台适配复杂、数据交互繁琐、样式定制困难?本文将带你用Iced表
桌面应用跨平台UI组件Rope 免费人脸交换工具:4 步产出第一条换脸视频
Rope 免费人脸交换工具:4 步产出第一条换脸视频 Rope 是一款免费的人脸交换工具,基于 insightface 的 inswapper_128 模型。你
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考