一段短视频,经过处理后能直接输出三维空间中的人体关节运动轨迹——这个想法听起来像需要专业动捕棚才能实现,但实际上,一个叫VideoPose3d的开源项目就能在普通电脑上完成大部分工作。它是一个基于PyTorch的三维人体姿态估计工具,由FAIR团队开源,核心思路是先用成熟的2D关键点检测器从视频帧里提取人体关节坐标,再用时序卷积网络把这些2D坐标“提升”成3D坐标。我最早接触这个项目是为了给一个动作分析的小实验准备数据,折腾了一圈环境,踩了不少坑,最终跑通后用自己随手拍的视频做出了带三维骨架的动画,整个过程相当有成就感。这篇文章就把我从零开始的环境搭建流程、做自己视频的完整步骤、以及调试中遇到的各种问题一次性写清楚,给想入坑三维姿态估计的朋友做个参考。
1. 先搞懂VideoPose3d要做什么,然后再说环境
很多人一上来就急着装环境,结果装到一半发现连项目要解决什么问题都没搞明白,后面配置参数全靠猜。我建议先花十分钟理解这个项目的运行逻辑,后面所有步骤都会顺很多。
1.1 这个项目到底解决什么问题
人体姿态估计可以分成两条技术路线:一条是2D姿态估计,比如OpenPose、HRNet、Detectron2里的Keypoint RCNN,输出的是图像上每个关节的像素坐标;另一条是3D姿态估计,输出的是关节在三维空间中的坐标。2D姿态估计在公开数据集上已经做得非常成熟,但很多实际应用(动作捕捉、运动分析、人机交互)需要的是3D信息,而这恰恰是难点。
VideoPose3d走的是“2D转3D”的路线,学术上叫2D-to-3D lifting。它不直接从图像回归3D坐标,而是先利用现成的2D关键点检测器得到每帧的二维关节位置,再把这些二维关节点序列输入一个时序卷积网络,利用时间维度上的运动信息推出三维坐标。这种做法的好处是:2D检测器可以随便换成精度更高的新模型,3D提升模块也能单独训练和替换,灵活性很强。在当年的Human3.6M数据集上,这个方案刷新了3D姿态估计的精度纪录,而且推理速度很快,在GTX 1080Ti上能跑到实时以上。
1.2 翻一下源码目录,搞清楚每一个关键文件
克隆下来的项目目录大概是这样的,里面的关键文件我一个个说清楚:
run.py:主入口,负责训练和评估3D提升网络。run_2d.py:在Human3.6M等数据集上运行2D关键点检测器,生成2D关键点文件。run_3d.py:基于已有的2D关键点文件,运行3D提升网络进行推理或评估。inference/infer_video.py:这个脚本最实用,把“视频 → 2D检测 → 3D提升 → 可视化”串成了完整pipeline。common/:模型定义、训练参数、数据加载等核心代码。data/:数据预处理相关脚本。demo/:可视化demo。scripts/download_models.sh:批量下载预训练权重的脚本,跑之前建议先看一遍。
搞清楚这些文件的职责后,你就能理解为什么很多教程会让你先从infer_video.py入手——因为它就是为“用自己的视频跑出结果”设计的。
1.3 先想清楚你的机器能不能跑,再动手
VideoPose3d对硬件的要求没有想象中高。官方模型不大,3D提升网络的参数量只有一百多万,纯CPU也能跑,但慢得让人怀疑人生。如果涉及2D关键点检测(Detectron2的Keypoint RCNN),那么CPU基本上没法用,必须要有NVIDIA显卡。我的建议是:
- 显卡:NVIDIA显卡,显存4GB以上,GTX 1060 6G就能跑,RTX 3060/4060会更舒服。AMD显卡和苹果M系列芯片在Detectron2这一步会遇到很多兼容性问题,不太推荐。
- 内存:16GB起步,32GB更稳妥,因为视频帧和中间特征都会吃内存。
- 系统:Ubuntu 18.04/20.04最省心,Windows也能跑,但有些坑需要额外处理(后面会专门讲)。
- CUDA:建议先装CUDA 11.x版本的驱动,然后让PyTorch自己带运行时环境,这样最不容易冲突。
环境搭建的第一原则:不要追新。PyTorch不是越新越好,Detectron2和VideoPose3d都是几年前的项目,新版本PyTorch不一定兼容。我建议的稳妥搭配是Python 3.8 + PyTorch 1.13 + Detectron2 0.6(对应PyTorch 1.10版本的wheel),这个组合经过大量人验证,坑最少。
2. 环境搭建实操:从零到能跑demo
这一部分我会按照我实际操作的顺序写,每个命令都验证过,照着复制粘贴基本能跑通。
2.1 创建独立的Python虚拟环境
建议使用conda,不需要最新版,只要有conda命令就行,Minicoda也可以。创建独立的Python环境是第一步,也是很多新手最容易跳过的一步——直接在系统Python里装一堆包,后面想清理都没法清理。
conda create -n videopose python=3.8 -y conda activate videopose这里指定Python 3.8是经过了权衡的:VideoPose3d的代码比较老,太新的Python(比如3.11、3.12)在安装Detectron2时经常遇到编译问题,3.8兼容性最好。如果你电脑上还没有conda,可以先装Miniconda,过程很简单,网上教程也很多。
2.2 安装PyTorch,注意CUDA版本匹配
进入videopose环境后,安装PyTorch。这里的关键是版本号和CUDA版本的匹配。我推荐直接用PyTorch官方源:
pip install torch==1.13.1 torchvision==0.14.1如果不指定--index-url,pip会从PyPI下载CPU版本或默认版本,在GPU机器上可能没法用CUDA。建议用官方命令安装带CUDA的版本:
pip install torch==1.13.1+cu117 torchvision==0.14.1+cu117安装完成后,务必验证一下CUDA是不是真的可用:
python -c "import torch;print(torch.__version__);print(torch.cuda.is_available())"如果输出True,说明GPU版本装好了。这一步值得多花两分钟确认,因为后面所有报错排查都建立在“PyTorch能把数据搬到GPU”这个前提下。
2.3 安装Detectron2,最容易报错的一步
Detectron2是Facebook开源的2D检测和分割框架,VideoPose3d的2D关键点检测器依赖它。但Detectron2不能直接用pip install detectron2装(官方没有发布所有版本的wheel,PyPI上的包也不全),官方推荐从源码编译,或者下载预编译的wheel。
我建议直接下载对应PyTorch版本的预编译wheel,省去编译时间,也避免因为系统环境问题编译失败。对于PyTorch 1.13,可以试试官方提供的wheel对应表:
pip install detectron2 -f https://dl.fbaipublicfiles.com/detectron2/wheels/cu113/torch1.10/index.html注意:这个wheel对应的是PyTorch 1.10,在PyTorch 1.13上通常也能用,但不保证100%兼容。如果你严格按照PyTorch 1.10 + CUDA 11.3来装,那么Detectron2直接装对应wheel就行。
另一种方式是从源码安装:
pip install git+https://github.com/facebookresearch/detectron2.git源码安装会现场编译,慢一些,但对环境的兼容性判断更智能。如果你在安装Detectron2时遇到编译错误,绝大多数情况是CUDA版本或gcc版本问题,检查一下nvcc --version和gcc --version是否正常。
这里有个初学者容易忽略的问题:Detectron2依赖的第三方库比较多,比如shapely、pycocotools,建议先安装基础依赖:
pip install pyyaml cython matplotlib tqdm pycocotools shapely安装顺序很重要,先装依赖再装Detectron2,能省去不少麻烦。
2.4 下载VideoPose3d项目与预训练模型
克隆项目:
git clone https://github.com/facebookresearch/VideoPose3D.git cd VideoPose3D然后安装项目自己的依赖,内容不多,主要是numpy、torch这些已经在前面装好的包:
pip install -r requirements.txt接着下载预训练模型。项目提供了官方脚本:
bash scripts/download_models.sh这个脚本会下载多个模型文件,大约一两个GB,包括在Human3.6M上训练的3D提升模型。下载速度取决于你的网络情况,如果中途断了可以重跑一次,脚本本身支持断点续传(实际上是靠wget的-c参数)。
如果下载失败,可以去项目的GitHub Release页面手动下载对应的.tar或.pth.tar文件,然后放到checkpoint/目录下。VideoPose3d的3D模型文件命名规律是{2d_detector}-{window_size}-{frames}.pth.tar,比如cpn-48-96.pth.tar表示用CPN做2D检测、3D模型窗口大小为48帧。
还需要下载2D检测器的权重。VideoPose3d的推理脚本默认使用Detectron2的keypoint_rcnn_R_50_FPN_3x模型,可以从Detectron2的模型库下载,文件名通常叫model_final_a6e10b.pkl。下载后放到Detectron2的缓存目录(通常是~/.torch/或~/.cache/torch/)。
2.5 跑通官方demo,验证环境是否正常
环境装完后的第一件事是跑通官方demo,不要急着用自己的视频。官方仓库的inference目录下提供了一个示例视频和推理脚本,可以先跑一遍看看效果。
python inference/infer_video.py \ --cfg=configs/infer/wildfire.yaml \ --video-file=inference/media/messi_walking.mp4 \ --output=output/demo.mp4如果这一步没有报错且输出文件正常生成,说明你的环境搭建已经成功。跑通demo后再换成自己的视频,心智负担会小很多。
3. 制作自己的视频:完整流程拆解
有了能跑的环境,接下来就是核心需求:用自己录的视频生成3D姿态结果。这一步看起来简单,实际操作时有很多细节直接影响最终效果。
3.1 视频素材准备:录视频时的注意事项
VideoPose3d对视频内容是有要求的,录的时候注意以下几点,能省掉后期很多麻烦:
- 人物尽量完整出现在画面中,不要被裁掉手脚。因为2D检测器是逐帧检测,肢体一旦被截断,关键点就会丢失或偏移,3D提升网络收到错误输入后输出也会乱跳。
- 画面不要太模糊。手机在光线好的环境下录的720p以上视频就够用,但如果是昏暗环境、运动模糊严重的画面,2D检测的效果会大打折扣。
- 背景尽量简单。虽然Detectron2的检测器对复杂背景有一定鲁棒性,但背景里如果有其他人、动物、与人形相似的物体,很容易误检,导致输出的骨架跳到别人身上。
- 视频时长建议10秒到1分钟。太短的话时序网络没有足够上下文,3D结果会不稳定;太长的话推理时间会成倍增加,而且人物姿态重复度高,信息冗余。
我推荐用手机横屏录制,帧率30fps或60fps都行,最终项目会抽取固定帧数处理。录制时让被拍摄者站在离镜头2到4米的位置,动作幅度不用太大但要有变化,比如挥手、走路、转身,这类动作在3D化之后效果最好。
3.2 动手跑推理:infer_video.py的参数与原理
核心命令就是这样:
python inference/infer_video.py \ --cfg=configs/infer/wildfire.yaml \ --video-file=myvideo.mp4 \ --output=myvideo_3d.mp4wildfire.yaml是官方给的一个配置示例,里面定义了检测器、3D模型权重、关键点格式、渲染参数等。如果你想换一个3D模型权重,或者换一个2D检测器,直接改yaml文件里的路径就行。
我先简单解释一下这个配置文件的几个关键项:
DETECTOR.NAME:2D关键点检测器的名称,默认是keypoint_rcnn_R_50_FPN_3x。DETECTOR.CKPT:检测器权重路径。POSENET.CHECKPOINT:3D提升网络的权重路径,对应checkpoint/下的.pth.tar文件。DATASET.NUM_JOINTS:关键点数量,COCO格式是17个,Human3.6M格式是16个(还有根节点),要跟模型匹配。RENDERING.OUTPUT_HEIGHT/OUTPUT_WIDTH:输出视频的尺寸,默认值通常就是输入视频的尺寸。
实际推理时,脚本的工作流程是:读取视频 → 逐帧用Detectron2检测2D关键点 → 把2D关键点序列按设定窗口长度分段 → 输入3D提升网络,得到每帧的三维关节坐标 → 把3D坐标投影回图像平面,画上彩色骨骼并输出新视频。
初次跑的时候建议先拿一段10秒视频测试。检测阶段如果显存不够,可以适当降低输入分辨率,或者在yaml里调整DATASET.BATCH_SIZE。注意:调整关键点检测的batch size可能影响内存占用,也可以减小视频帧的缩放比例。
3.3 理解输出文件:视频和坐标数据
跑完infer_video.py后,除了生成一个带3D骨架叠加的视频,项目还会把每帧的3D关键点坐标保存下来,通常是一个.npz文件(在output/目录下)。这是整个流程最有价值的部分——视频只是可视化,坐标数据才是能用来做进一步分析的东西。
.npz里保存的数组形状通常是(num_frames, num_joints, 3),对应每帧每个关节的x、y、z坐标。关节顺序取决于训练数据集,COCO格式是17个点,Human3.6M格式则需要额外做坐标变换。
拿到坐标后,你可以做的扩展非常多:
- 计算关节角度变化,分析运动幅度。
- 把坐标序列保存为CSV或json,导入Excel做统计分析。
- 把3D坐标写入FBX或BVH格式,在Blender、Unity、C4D里驱动虚拟角色。
- 计算重心轨迹、躯干倾斜角等运动学参数,用于运动康复或者体育分析。
需要说明的是,VideoPose3d输出的3D坐标是相对相机坐标系(或者以人物根节点为参考的局部坐标系),不是绝对世界坐标。如果要做多相机拼接或者绝对位置分析,需要用多视角视频做三角化,那就不是基础教程的范围了。
3.4 画质提升的几个技巧
第一次跑通并看到自己视频中的3D骨架叠加时,心情肯定是兴奋的,但骨架可能比较“抖”,跟专业动捕效果差距很大。这是正常的,因为VideoPose3d的3D提升是逐帧独立输出的(虽然一定程度上利用了时序信息),模型对轻微的关键点检测噪声很敏感。
想提升视觉效果,可以从这几个方向入手:
- 在拍摄端提高2D检测质量:光线均匀、设备固定(用三脚架)、人物穿与背景颜色反差大的衣服。
- 视频剪裁:去掉首尾画面中人物不完整的帧。
- 使用更精确的2D检测器:Detectron2只是默认选项,你可以尝试HRNet、HigherHRNet等更强的检测器,把输出的2D关键点保存为VideoPose3d需要的格式后,再用
run_3d.py做3D提升。 - 后处理平滑:对输出的3D坐标做低通滤波(如Savitzky-Golay平滑),能明显减少抖动。这块可以单独写个小脚本,用scipy的
savgol_filter对每个关节的坐标序列做平滑即可。
4. 常见问题与调试实录
这里整理一下我实际操作中遇到的“名场面”,按出现频率排序,方便大家直接查表对照。
4.1 报错速查表
| 报错现象 | 可能原因 | 解决办法 |
|---|---|---|
ModuleNotFoundError: No module named 'detectron2' | Detectron2未安装或安装不完整 | 确认当前环境是videopose,按2.3节重新安装 |
RuntimeError: CUDA out of memory | 显存不足 | 降低视频分辨率,减小batch size,关闭其他占显存的进程 |
KeyError: 'keypoints' | 2D检测器输出格式不匹配 | 确认检测器是Keypoint RCNN类,不是纯目标检测模型 |
No such file or directory: 'checkpoint/xxx.pth.tar' | 模型权重没下载或路径不对 | 确认checkpoint/目录下文件存在,检查yaml里的路径 |
ffmpeg相关报错 | OpenCV和ffmpeg视频解码问题 | 安装opencv-python的完整版:pip install opencv-python;确认系统装了ffmpeg库 |
| 推理速度极慢,GPU利用率低 | CPU做2D检测,或数据加载瓶颈 | 确认视频解码的分辨率不要太大,打印日志看哪个阶段耗时高 |
4.2 关于“跑出来的骨架在无关物体上”
这是2D检测误检导致的。VideoPose3d只处理检测器找到的第一个“人”。如果你的视频里出现了椅子、人体模型、柱子这类容易被误判物体,画面里的骨架可能会飞到这些物体上。解决办法是:
- 在进入pipeline之前,先用视频剪辑工具裁剪画面,把人之外的东西尽量排除。
- 换用更强、更严格过滤的检测配置,比如提高检测置信度阈值,在yaml里调整
DETECTOR.NMS_THRESH或DETECTOR.SCORE_THRESH。
4.3 Windows用户的特殊坑
如果你在Windows上跑,有几个额外问题需要注意:
- 项目里的shell脚本(
download_models.sh)在Windows的PowerShell或cmd里不能直接执行。要么安装Git Bash,要么手动根据脚本内容下载模型文件。 - 文件路径分隔符问题。建议所有路径都用绝对路径或统一使用正斜杠
/。 - CUDA环境变量没配置好的话,PyTorch会退回CPU模式。确认
torch.cuda.is_available()为True。
4.4 关于 “2D关键点检测”和“3D提升”分开跑的方案
我个人的建议是,想深度使用这个项目的话,不要只依赖infer_video.py,尝试把两步拆开跑:
- 单独用Detectron2或HRNet跑2D关键点检测,保存成
.npz或.json文件。这样2D检测可以用自己更熟悉的框架,也方便检查中间结果。 - 用VideoPose3d的
run_3d.py加载该2D关键点文件,运行3D提升。
这种做法的优势在于可控性更强——如果3D结果不理想,你只需要检查2D关键点的质量,是检测错了还是提升出了问题一目了然,不用整套流程从头再跑。
具体做法是,准备一个.json文件,格式匹配VideoPose3d数据集的读取方式(一般包含positions_2d字段,shape为(1, num_frames, num_joints, 2)),然后修改run_3d.py的--dataset参数为自定义数据集,或者直接修改数据加载代码。这部分稍微偏进阶,但值得投入时间研究。
5. 理解原理与继续扩展
环境搭好、视频跑通后,千万别停下来。理解VideoPose3d背后的原理,能让你在遇到问题时更快定位,也能让你更好思考如何改进它。
5.1 为什么2D转3D是可行的
从2D关键点预测3D姿态,数学上是一个病态问题:同一个2D坐标可能对应无数种3D姿态,只要旋转或缩放就能发生巨大变化。但人体关节运动受生物力学约束,不是所有3D姿态都是合理的。VideoPose3d利用的就是这种隐含约束——通过对大量带标注的3D动作数据进行学习,网络学会了哪些3D姿态在物理上是可能的,从而在输入2D坐标时给出一个“最合理”的3D解。
关键点在于时序信息。如果只看单帧,2D到3D会存在严重歧义;但如果看连续多帧(比如48帧),人体运动的连贯性和速度,就能提供更多的几何线索,帮网络判断比如“这个人是手臂前伸还是回收”。VideoPose3d的时序卷积结构就是奔着“捕捉帧间依赖”去的,这也是为什么输入帧数(窗口大小)对结果影响很大。
窗口大小的设置是个取舍:窗口越大,3D姿态越平滑,但延迟越高,对快速动作的响应也越慢;窗口越小,结果更跟随当前帧,但抖动更明显。配置文件里默认是window_size=48,如果你做的是慢速动作分析,可以提高到243(项目里带的最大窗口模型),画面会稳定不少;如果是快速运动,用27或更低。
5.2 从VideoPose3d可以延伸到哪些方向
跑通了VideoPose3d,其实你就解锁了三维姿态估计的大门。可以试的东西很多:
- 换更先进的2D检测器:VideoPose3d的精度的天花板很大程度取决于2D检测器。换成RTMpose、ViTPose等新模型,3D结果会明显提升。
- 对接动画工作流:把输出的3D坐标转成BVH文件,驱动Blender里的角色模型,这是做低成本动捕最常见路径。社区里已经有人写了VideoPose3d到BVH的转换脚本,找来看一下就能接上。
- 实时推理改造:VideoPose3d的3D提升网络本身很快,实时性瓶颈在2D检测器上。把2D检测器换成轻量级方案,再配合ONNX导出,有可能实现接近实时的3D姿态输出。
- 多视角融合:如果有两个角度的摄像头,分别跑2D检测和3D提升,再用三角测量融合两组结果,能大幅提高3D精度和鲁棒性。这项工作已经有不少论文实现。
5.3 关键参数速查与推荐配置
为了让你不迷路,这里放一个常用参数清单,都是我实际测试过得出的参考值:
| 参数 | 适用场景 | 建议值 |
|---|---|---|
window_size | 慢速动作、追求平滑 | 48或243 |
window_size | 快速运动、追求实时性 | 27 |
| 输入视频帧率 | 常规动作 | 30fps |
| 2D检测器的置信度阈值 | 单人、背景简单 | 0.5左右 |
| 2D检测器的置信度阈值 | 多人、背景复杂 | 0.8以上 |
| 3D坐标平滑窗口 | 后期处理 | 5到15帧的Savitzky-Golay滤波 |
这些数值不是金科玉律,但作为初始起点很合适。实际效果好不好,还是得看你自己的视频数据类型,多试几组参数对比一下,就能找到最适合的组合。
最后分享一点自己的体会
如果在整个流程中只能给你一个建议,那就是:不要把VideoPose3d当成一个黑盒工具,跑通之后一定要去读一下inference/infer_video.py的源码,哪怕只看个大概,理解它是怎么把2D关键点喂给3D网络的,日后遇到问题会从容很多。我自己当时就是靠读源码,才弄明白了为什么换了一个2D检测器后输出骨架会偶尔跳帧——原来是关键点顺序不一致,在多了一个根节点的情况下没有做对齐。另外,做自己视频时,拍摄条件(光线、背景、人物服装)对最终效果的影响力,远超你用什么显卡、跑了多少帧。同样一段动作,站在杂乱背景前拍的视频和纯色背景下拍的视频,3D骨架质量能差出一个量级。这一点在你自己动手试过一次之后,应该会跟我一样深有体会。