OpenPose:实时多人 2D 姿态估计
什么是 OpenPose
OpenPose 是一个实时多人关键点检测库,能够同时检测图像或视频中所有人的身体、手部、面部和脚部关键点。它由卡内基梅隆大学感知计算实验室开发,基于深度神经网络,可以高效地在单张图像上估计多人 2D 姿态。
与单人的姿态估计算法不同,OpenPose 不需要提前框定人体位置,而是通过部位关联场(Part Affinity Fields, PAFs) 将检测到的关键点正确分配给每一个人,从而实现真正意义上的多人姿态估计。
它为什么重要
- 实时性:针对 GPU 高度优化,可达到视频帧率级别的推理速度。
- 多人无先验:不需要目标检测器前置,直接从全局推断所有人。
- 多部位覆盖:身体关节(18/25 个关键点)、手部(21 个关键点)、面部(70 个关键点)、脚部(3 个关键点)。
- 鲁棒性:对遮挡、拥挤场景有较好的处理能力。
核心原理速览
整体流程
- 输入图像 → 经过一个卷积神经网络(通常为 VGG-19 前几层)提取特征。
- 两个并行分支:
- 关键点置信图(Keypoint Confidence Maps):预测每个身体部位(如左肩、右膝)在空间上出现的概率。
- 部位关联场(Part Affinity Fields, PAFs):一个 2D 向量场,表示肢体区域中从一个关键点指向另一个关键点的方向。
- 后处理解析:通过贪心算法,利用置信图找到关键点候选,再利用 PAF 将候选点连接成完整的人体骨骼,并为每个人分配独立的骨骼。
这种自底向上的方法非常适合多人场景,因为网络的复杂度与画面中的人数几乎无关。
关键点模型
OpenPose 提供了多种身体关键点模型:
- BODY_25:25 个身体关键点(包含脚部),速度快且效果较好。
- COCO:18 个关键点(不包含脚部),兼容 COCO 数据集格式。
- MPI:15 个关键点,主要用于单人姿态估计。
手部和面部模型则使用单独的网络进行精细化检测。
安装与环境配置
OpenPose 支持 Windows、Linux (Ubuntu) 和 macOS。推荐使用预编译版本或 conda 环境,以降低配置门槛。
方式一:Conda 安装(最简)
conda create -n openpose python=3.7
conda activate openpose
pip install openpose-python
部分构建版本可能需要安装额外的依赖:
conda install -c conda-forge opencv
方式二:从源码编译(功能完整)
-
克隆仓库
git clone https://github.com/CMU-Perceptual-Computing-Lab/openpose.git cd openpose -
安装依赖
- Caffe (OpenPose 自带 Caffe 构建脚本,无需单独安装)
- CMake ≥ 3.1
- OpenCV ≥ 3.2
- 在 Ubuntu 下可运行:
sudo apt install cmake libopencv-dev libboost-all-dev
-
编译
mkdir build && cd build cmake .. make -j`nproc` -
Python API 使用
编译后,进入build/python目录,运行:sudo make install或将路径添加到
PYTHONPATH。
快速上手:使用 Python API
基本示例代码
import cv2
from openpose import pyopenpose as op
# 配置参数
params = {
"model_folder": "./models/",
"body": 1, # 启用身体关键点
"hand": True, # 启用手部关键点
"face": False, # 如需面部可设为 True
"number_people_max": 6, # 最大检测人数
}
# 初始化 OpenPose 对象
opWrapper = op.WrapperPython()
opWrapper.configure(params)
opWrapper.start()
# 读取图像
image = cv2.imread("people.jpg")
datum = op.Datum()
datum.cvInputData = image
opWrapper.emplaceAndPop(op.VectorDatum([datum]))
# 可视化结果
output_image = datum.cvOutputData
cv2.imshow("OpenPose Output", output_image)
cv2.waitKey(0)
关键参数说明
| 参数名 | 含义 | 典型值 |
|---|---|---|
model_folder |
预训练模型存放路径 | "./models/" |
body |
身体模型选用 | 1(BODY_25), 2(COCO) |
hand |
是否检测手部关键点 | True/False |
face |
是否检测面部关键点 | True/False |
net_resolution |
网络输入分辨率,如 "656x368" |
影响速度和精度 |
number_people_max |
最多同时检测人数 | -1 表示不限制 |
获取关键点坐标
检测后,关键点数据存储在 datum.poseKeypoints、datum.handKeypoints 和 datum.faceKeypoints 中。对于身体关键点,它是一个形状为 [人数, 关键点数量, 3] 的 numpy 数组,最后一维的三个值分别是 (x, y, 置信度)。
if datum.poseKeypoints is not None:
for person_id in range(len(datum.poseKeypoints)):
for kp_id in range(datum.poseKeypoints.shape[1]):
x, y, conf = datum.poseKeypoints[person_id][kp_id]
# 可根据置信度阈值过滤 (conf > 0.3)
实战:从视频流实时检测
使用 OpenCV 读取摄像头,逐帧送入 OpenPose,是构建姿态交互应用的基础。
import cv2
from openpose import pyopenpose as op
params = {
"model_folder": "./models/",
"body": 1,
"net_resolution": "320x176", # 低分辨率加快速度
}
opWrapper = op.WrapperPython()
opWrapper.configure(params)
opWrapper.start()
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret: break
datum = op.Datum()
datum.cvInputData = frame
opWrapper.emplaceAndPop(op.VectorDatum([datum]))
cv2.imshow("Real-time Pose", datum.cvOutputData)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
当需要更高性能时,可以:
- 降低
net_resolution。 - 关闭手部/面部检测。
- 使用 GPU 模式(编译时启用
GPU_MODE)。
常见问题与排错
模型文件缺失
将 .caffemodel 和 .prototxt 文件放入 models/ 目录下对应的子文件夹:
models/pose/body_25/pose_iter_584000.caffemodelmodels/hand/pose_iter_102000.caffemodelmodels/face/pose_iter_116000.caffemodel
可从官方 GitHub Release 页面下载完整模型包。
内存不足(Out of Memory, OOM)
- 减少
number_people_max。 - 使用更小的
net_resolution,如"288x160"。 - 限制总视频帧速率。
关键点不稳定跳动
- 适当提高
net_resolution提升精度。 - 对连续帧应用平滑滤波(如指数滑动平均)。
- 使用
heatmaps_scale参数调整热图尺度。
多人场景下关键点连接错误
- 检查
model_pose是否与模型文件匹配。 - 略微降低 PAF 连接阈值参数
interperson_threshold,或使用更优后处理策略。
进阶思路
- 数据导出:将关键点坐标实时保存为 JSON,用于动作分析或数据集制作。
- 动作识别:基于一段时间内的关键点轨迹,训练 LSTM 或时序卷积网络识别特定动作。
- 手势控制:利用手部 21 个关键点的位置关系,定义手势规则来控制设备或应用。
- 3D 姿态扩展:结合三角测量或多视图,使用 OpenPose 输出作为 3D 姿态估计的基础。
OpenPose 作为姿态估计领域的经典开源项目,至今仍广泛应用于体育分析、人机交互、康复医疗和安防监控等领域。掌握其基本使用方法,你就拥有了一个强大的视觉感知工具。