【知识点】OpenPose姿态检测
编辑
2025-06-02
深度学习
00

目录

1. OpenPose的输入和输出形状
输入形状:
输出形状:
2. OpenPose的网络结构
主干网络(基于VGG):
多阶段细化结构:
3. OpenPose的后处理
非极大值抑制(NMS):
部位连接算法:
二部图匹配:
4. OpenPose的损失函数
5. OpenPose用于摔倒检测
人体追踪:
摔倒检测的实现思路:

的问题:

1. OpenPose的输入和输出形状

输入形状:

cpp
展开代码
// 从 src/openpose/net/netCaffe.cpp:218 可以看到 if (inputData.getNumberDimensions() != 4 || inputData.getSize(1) != 3) error("The Array inputData must have 4 dimensions: [batch size, 3 (RGB), height, width].");

输入张量形状: [batch_size, 3, height, width]

  • batch_size: 批次大小,通常为1
  • 3: RGB三通道
  • height, width: 图像的高度和宽度

输出形状:

cpp
展开代码
// 从文档 doc/advanced/heatmap_output.md:66 可以看到 assert x[0] == 3 # First parameter saves the number of dimensions (18x300x500 = 3 dimensions) shape_x = x[1:1+int(x[0])] assert shape_x[0] == 18 # Size of the first dimension assert shape_x[1] == 300 # Size of the second dimension assert shape_x[2] == 500 # Size of the third dimension

输出热图形状: [num_channels, height, width]

  • 对于BODY_25模型: [78, H/8, W/8] (26个关键点热图 + 52个PAF通道)
  • 对于COCO_18模型: [57, H/8, W/8] (19个关键点热图 + 38个PAF通道)

2. OpenPose的网络结构

主干网络(基于VGG):

prototxt
展开代码
# 从 models/pose/body_25/pose_deploy.prototxt 可以看到 input: "image" input_dim: 1 # batch size input_dim: 3 # RGB channels input_dim: 16 # height (runtime defined) input_dim: 16 # width (runtime defined) # VGG前几层 conv1_1 -> relu1_1 -> conv1_2 -> relu1_2 -> pool1_stage1 conv2_1 -> relu2_1 -> conv2_2 -> relu2_2 -> pool2_stage1 conv3_1 -> relu3_1 -> conv3_2 -> relu3_2 -> conv3_3 -> relu3_3 -> conv3_4 -> relu3_4 -> pool3_stage1 conv4_1 -> relu4_1 -> conv4_2 -> relu4_2 -> conv4_3_CPM -> relu4_3_CPM -> conv4_4_CPM -> relu4_4_CPM

多阶段细化结构:

cpp
展开代码
// Stage 1: 初始预测 // Stage 2-6: 迭代细化 // 每个stage输出: // - 关键点热图 (Confidence Maps) // - 部位亲和场 (Part Affinity Fields, PAFs)

数学公式: St=ϕt(F,St1,Lt1)\mathbf{S}^t = \phi^t(\mathbf{F}, \mathbf{S}^{t-1}, \mathbf{L}^{t-1}) Lt=ψt(F,St1,Lt1)\mathbf{L}^t = \psi^t(\mathbf{F}, \mathbf{S}^{t-1}, \mathbf{L}^{t-1})

其中:

  • St\mathbf{S}^t: 第t阶段的关键点热图
  • Lt\mathbf{L}^t: 第t阶段的PAF
  • F\mathbf{F}: VGG特征图
  • ϕt,ψt\phi^t, \psi^t: 第t阶段的CNN预测函数

3. OpenPose的后处理

非极大值抑制(NMS):

cpp
展开代码
// 从 src/openpose/net/nmsBase.cpp 可以看到NMS的实现 // 找到热图中的局部最大值点作为关键点候选

部位连接算法:

cpp
展开代码
// 从 src/openpose/net/bodyPartConnectorBase.cpp:26 可以看到PAF计算 const auto vectorAToBNormX = vectorAToBX/vectorNorm; const auto vectorAToBNormY = vectorAToBY/vectorNorm; auto sum = T(0); auto count = 0u; for (auto lm = 0; lm < numberPointsInLine; lm++) { const auto score = (vectorAToBNormX*mapX[idx] + vectorAToBNormY*mapY[idx]); if (score > interThreshold) { sum += score; count++; } }

PAF连接分数公式scoreAB=1nuline(A,B)L(u)ABAB\mathit{score}_{AB} = \frac{1}{n} \sum_{u \in \mathit{line}(A,B)} \mathbf{L}(u) \cdot \frac{\overrightarrow{AB}}{|\overrightarrow{AB}|}

其中:

  • L(u)\mathbf{L}(u): 位置u的PAF向量
  • AB\overrightarrow{AB}: 从关键点A到B的向量
  • nn: 线段上的采样点数

二部图匹配:

使用匈牙利算法进行最优关键点配对。

4. OpenPose的损失函数

虽然这是推理代码,但根据论文,训练时使用的损失函数是:

L=t=1Tj=1JWSjt(p)Sj(p)22+t=1Tc=1CWLct(p)Lc(p)22L = \sum_{t=1}^{T} \sum_{j=1}^{J} \mathbf{W} \cdot ||S_j^t(\mathbf{p}) - S_j^*(\mathbf{p})||_2^2 + \sum_{t=1}^{T} \sum_{c=1}^{C} \mathbf{W} \cdot ||L_c^t(\mathbf{p}) - L_c^*(\mathbf{p})||_2^2

其中:

  • SjtS_j^t: 第t阶段第j个关键点的预测热图
  • SjS_j^*: 第j个关键点的真实热图
  • LctL_c^t: 第t阶段第c个PAF的预测
  • LcL_c^*: 第c个PAF的真实值
  • W\mathbf{W}: 二进制掩码,避免标注不明确区域的惩罚
  • TT: 阶段数
  • JJ: 关键点数
  • CC: PAF数

5. OpenPose用于摔倒检测

从源码分析,OpenPose本身不直接做摔倒检测,但提供了基础功能:

人体追踪:

cpp
展开代码
// 从 src/openpose/tracking/personTracker.cpp 可以看到追踪功能 class PersonTracker { void track(Array<float>& poseKeypoints, Array<long long>& poseIds, const Matrix& cvMatInput); // 使用光流法追踪关键点 };

摔倒检测的实现思路:

python
展开代码
# 基于关键点坐标实现摔倒检测的示例代码 def detect_fall(keypoints): # 1. 计算身体姿态角度 hip_center = (keypoints[8] + keypoints[11]) / 2 # 髋部中心 shoulder_center = (keypoints[2] + keypoints[5]) / 2 # 肩部中心 # 2. 计算身体倾斜角度 body_angle = math.atan2(shoulder_center[1] - hip_center[1], shoulder_center[0] - hip_center[0]) # 3. 摔倒判定条件 fall_conditions = [ abs(body_angle) > threshold_angle, # 身体严重倾斜 shoulder_center[1] > hip_center[1] + height_threshold, # 肩膀低于髋部 motion_velocity > speed_threshold # 快速运动 ] return all(fall_conditions)

摔倒检测算法

Fall={1,if θ>θth and Δy>yth and v>vth0,otherwise\text{Fall} = \begin{cases} 1, & \text{if } |\theta| > \theta_{th} \text{ and } \Delta y > y_{th} \text{ and } v > v_{th} \\ 0, & \text{otherwise} \end{cases}

其中:

  • θ\theta: 身体与垂直方向的夹角
  • Δy\Delta y: 肩膀与髋部的垂直距离差
  • vv: 运动速度
  • θth,yth,vth\theta_{th}, y_{th}, v_{th}: 对应的阈值

总结:OpenPose提供了强大的2D人体姿态估计能力,通过多阶段CNN网络输出关键点热图和部位亲和场,经过NMS和二部图匹配等后处理得到最终的人体关键点。虽然不直接支持摔倒检测,但可以基于其输出的关键点坐标和追踪功能来实现摔倒检测算法。

如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:Dong

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!