从COCO数据集到OpenPose模型:手把手教你生成训练所需的Heatmap与PAF真值

张开发
2026/4/25 18:24:44 15 分钟阅读

分享文章

从COCO数据集到OpenPose模型:手把手教你生成训练所需的Heatmap与PAF真值
从COCO标注到OpenPose训练数据Heatmap与PAF生成全解析在计算机视觉领域人体姿态估计一直是研究热点之一。OpenPose作为其中的佼佼者以其多人实时检测能力广受关注。然而许多开发者在尝试训练自定义OpenPose模型时往往在数据准备阶段就遇到瓶颈——如何将标准的COCO关键点标注转换为模型所需的Heatmap和PAFPart Affinity Fields真值本文将深入剖析这一过程的技术细节带你从零理解OpenPose训练数据的生成逻辑。1. 数据准备与环境配置1.1 COCO数据集结构解析COCO数据集的关键点标注以JSON格式存储每个标注包含以下核心信息{ keypoints: [x1,y1,v1,...,x17,y17,v17], num_keypoints: int, bbox: [x,y,width,height] }其中v表示关键点可见性0未标注1标注但被遮挡2标注且可见1.2 开发环境搭建推荐使用以下环境配置conda create -n openpose python3.8 conda install pytorch torchvision cudatoolkit11.3 -c pytorch pip install pycocotools matplotlib numpy关键参数设置示例class Config: STRIDE 8 # VGG19的下采样倍数 SIGMA 7.0 # 高斯核标准差 INPUT_SIZE (368, 368) # 模型输入尺寸 LIMB_IDS [ # 肢体连接关系定义 [1,8], [8,9], [9,10], [1,11], [11,12], [12,13], [1,2], [2,3], [3,4], [2,14], [1,5], [5,6], [6,7], [5,15], [1,0], [0,14], [0,15], [14,16], [15,17] ]2. Heatmap生成原理与实现2.1 高斯热图数学原理对于每个关键点我们在对应位置放置一个二维高斯分布$$ G(x,y) \frac{1}{2\pi\sigma^2}e^{-\frac{(x-x_0)^2(y-y_0)^2}{2\sigma^2}} $$其中$(x_0,y_0)$是关键点坐标$\sigma$控制分布范围。2.2 代码实现细节def putGaussianMaps(center, gaussian_map, sigma, grid_y, grid_x, stride): start stride / 2.0 - 0.5 y_range [i for i in range(grid_y)] x_range [i for i in range(grid_x)] xx, yy np.meshgrid(x_range, y_range) xx xx * stride start yy yy * stride start d2 (xx - center[0]) ** 2 (yy - center[1]) ** 2 exponent d2 / 2.0 / sigma / sigma gaussian_map np.exp(-exponent) return gaussian_map注意实际实现时需要处理多个关键点的叠加情况通常采用取最大值的方式合并2.3 特殊处理颈部关键点COCO原始标注不包含颈部关键点我们需要通过左右肩计算得出def add_neck(keypoints): left_shoulder keypoints[5] right_shoulder keypoints[6] if left_shoulder[2] 0.5 and right_shoulder[2] 0.5: neck [(left_shoulder[0]right_shoulder[0])/2, (left_shoulder[1]right_shoulder[1])/2, 2] return np.vstack([keypoints, neck]) return keypoints3. PAF生成机制详解3.1 部件关联场数学定义PAF是一个向量场对于每个肢体连接如左肩-左肘它在连接线段上的每个点都保存一个单位向量$$ \vec{v} \frac{\vec{p_2}-\vec{p_1}}{||\vec{p_2}-\vec{p_1}||} $$其中$\vec{p_1}$和$\vec{p_2}$是肢体两端的关节点坐标。3.2 关键实现步骤def putVecMaps(centerA, centerB, accumulate_vec_map, count, grid_y, grid_x, stride): centerA centerA / stride centerB centerB / stride limb_vec centerB - centerA norm np.linalg.norm(limb_vec) if norm 0: return accumulate_vec_map, count limb_vec_unit limb_vec / norm threshold 1 # 计算肢体区域边界 min_x max(int(round(min(centerA[0], centerB[0]) - threshold)), 0) max_x min(int(round(max(centerA[0], centerB[0]) threshold)), grid_x) min_y max(int(round(min(centerA[1], centerB[1]) - threshold)), 0) max_y min(int(round(max(centerA[1], centerB[1]) threshold)), grid_y) # 生成网格并计算距离 range_x list(range(min_x, max_x, 1)) range_y list(range(min_y, max_y, 1)) xx, yy np.meshgrid(range_x, range_y) # 计算点到线段的距离 ba_x xx - centerA[0] ba_y yy - centerA[1] limb_width np.abs(ba_x * limb_vec_unit[1] - ba_y * limb_vec_unit[0]) mask limb_width threshold # 更新向量场 vec_map np.zeros_like(accumulate_vec_map) vec_map[yy, xx] np.repeat(mask[:, :, np.newaxis], 2, axis2) vec_map[yy, xx] * limb_vec_unit[np.newaxis, np.newaxis, :] # 处理重叠情况 mask np.logical_or.reduce((np.abs(vec_map[:, :, 0]) 0, np.abs(vec_map[:, :, 1]) 0)) accumulate_vec_map np.multiply(accumulate_vec_map, count[:, :, np.newaxis]) accumulate_vec_map vec_map count[mask] 1 # 计算平均值 mask count 0 count[mask] 1 accumulate_vec_map np.divide(accumulate_vec_map, count[:, :, np.newaxis]) count[mask] 0 return accumulate_vec_map, count3.3 多人物处理策略当图像中存在多个人时PAF生成需要特殊处理对每个人单独计算肢体向量场在重叠区域取平均值最终输出通道数为2×肢体连接数COCO为38通道4. 可视化与调试技巧4.1 Heatmap可视化def visualize_heatmap(heatmap): plt.figure(figsize(10,10)) for i in range(heatmap.shape[-1]): plt.subplot(5,4,i1) plt.imshow(heatmap[:,:,i], cmapjet) plt.axis(off) plt.tight_layout() plt.show()4.2 PAF可视化方案def visualize_paf(paf, limb_id): plt.figure(figsize(12,6)) plt.subplot(1,2,1) plt.imshow(paf[:,:,limb_id*2], cmapjet) plt.title(X component) plt.subplot(1,2,2) plt.imshow(paf[:,:,limb_id*21], cmapjet) plt.title(Y component) plt.show()4.3 常见问题排查问题现象可能原因解决方案Heatmap全零关键点坐标超出图像范围检查标注归一化处理PAF方向混乱肢体端点顺序错误确认LIMB_IDS定义训练不收敛高斯核σ设置不当调整σ值并重新可视化在实际项目中数据生成环节往往占据整个训练流程30%以上的调试时间。一个实用的建议是先在小批量数据10-20张上验证生成结果确认无误后再扩展到全量数据集。

更多文章