最近在虎牙直播做了一些关于人体姿态估计的工作,也看了蛮多这方面的文章,于是对这个内容做了一些总结和梳理,希望能抛砖引玉吧。我们不妨先把问题抛出来,人体姿态估计是做什么?从名字的角度来看,可以理解为对“人体”的姿态(关键点,比如头,左手,右脚等)的位置估计。根据 RGB 图片里人体的数量,又可以分为单人姿态估计多人姿态估计

1. 单人姿态估计

1.1 问题

对于单人姿态估计,输入是一个 crop 出来的行人,然后在行人区域位置内找出需要的关键点,比如头部,左手,右膝等。对于多人姿态估计,目前主要有 2 种主流思路,分别是 top-down 以及 bottom-up 方法。对于 top-down 方法,往往先找到图片中所有行人,然后对每个行人做姿态估计,寻找每个人的关键点。单人姿态估计往往可以被直接用于这个场景。对于 bottom-up,思路正好相反,先是找图片中所有 parts (关键点),比如所有头部,左手,膝盖等,然后把这些 parts(关键点)组装成一个个行人。

1.2 数据集

  • LSP(Leeds Sports Pose Dataset):单人人体关键点检测数据集,关键点个数为14,样本数2K,在目前的研究中作为第二数据集使用。
  • FLIC(Frames Labeled In Cinema):单人人体关键点检测数据集,关键点个数为9,样本数2W,在目前的研究中作为第二数据集使用。
  • MPII(MPII Human Pose Dataset):单人/多人人体关键点检测数据集,关键点个数为16,样本数25K,是单人人体关键点检测的主要数据集。它是 2014 年由马普所创建的,目前可以认为是单人姿态估计中最常用的 benchmark, 使用的是 PCKh 的指标。
  • MSCOCO:多人人体关键点检测数据集,关键点个数为17,样本数量多于30W。目前是多人关键点检测的主要数据集,使用的是 AP 和 OKS 指标。
  • human3.6M:是 3D 人体姿势估计的最大数据集,由 360 万个姿势和相应的视频帧组成,这些视频帧包含11 位演员从4个摄像机视角执行 15 项日常活动的过程。数据集庞大将近100G。
  • PoseTrack:最新的关于人体骨骼关键点的数据集,多人人体关键点跟踪数据集,包含单帧关键点检测、多帧关键点检测、多人关键点跟踪三个人物,多于500个视频序列,帧数超过20K,关键点个数为15。

1.3 评估指标

Keypoint detection 度量方法的核心思想就是模仿 Object detection 的度量方法。在 Object detection 中,IoU 是作为一种相似度度量,它通过计算检测框之间的重合度来定义真实目标和预测值目标之间的距离。而在 Keypoint detection 则是根据预测关键点和真实关键点之间的欧式距离来评判的

  • PCK(Percentage of Correct Keypoints)

关键点正确估计的百分比,计算检测的关键点与其对应的 groundtruth 间的归一化距离小于设定阈值的比例。这是比较老的人体姿态估计指标,在17年以前广泛使用,现在基本不再使用。但是如果仅是用于工程项目中来评价训练模型的好坏还是蛮方便的,因此这里也记录下:

其中: i 表示关节点的编号, di 表示第i个关节点的预测值和 groundtruth 的欧氏距离。 d 是一个人体的尺度因子,在不同的数据集里的计算方法不同。例如 MPII 中 数据集是以头部长度作为归一化参考,即 PCKh

  • oks (object keypoint similarity)

oks 表示关键点的相似度,它和预测关键点和真实关键点之间的欧式距离有关,其范围值为 [0, 1]。当它们的欧式距离为 0 时,其 oks 相似度等于 1

其中:i 为关键点的编号,di 表示预测的关键点和 groundtruth 之间的欧式距离,S 是一个尺度因子,为人体检测框面积的平方根, oi 是一个归一化因子,和关键点标注的难易有关,是通过对所有样本的人工标注和真实值的统计标准差。 vi 表示当前关键点是否可见。

  • AP(Average Precision)

这个和目标检测里的 AP 概念是一样的,只不过度量方式 iou 替换成了 oks。如果 oks 大于阈值 T,则认为该关键点被成功检测到。单人姿态估计和多人姿态估计的计算方式不同。对于单人姿态估计的AP,目标图片中只有一个人体,所以计算方式为:

对于多人姿态估计而言,由于一张图像中有 M 个目标,假设总共预测出 N 个人体,那么groundtruth和预测值之间能构成一个 MxN 的矩阵,然后将每一行的最大值作为该目标的 oks,则:

2.1 过去和现在

在过去,传统方法一般是基于图结构和形变部件模型,设计 2D 人体部件检测器,使用图模型建立各部件的连通性,然后结合关键点之间的 pair-wise 关系来恢复人体的姿态。传统方法虽然拥有较高的时间效率,但是提取的都是人工设定的浅层特征(如 HOG,SIFT 等)。而在现在的深度学习时代,姿态估计的特征提取,分类,以及空间位置的建模都可以在一个网络中直接建模,不再需要独立的进行拆解,整个过程完全可以端到端进行。

2.2 过去的思路

在 2014 年以前,很多论文讲的都是利用传统方法去解决单人姿态估计的问题。这些工作都是在深度学习爆发之前,我们是如何处理人体姿态估计这个问题。从算法角度来讲,这部分的工作主要是希望解决单人的人体姿态估计问题,也有部分工作已经开始尝试做 3D 的人体姿态估计。可以粗略的方法分成两类。

第一类是直接通过一个全局 feature,把姿态估计问题当成分类或者回归问题直接求解。但是这类方法的问题在于精度一般,并且可能比较适用于背景干净的场景。第二类是基于一个图模型,比如常用pictorial structure model。一般包含 unary term, 是指对单个 part 进行 feature 的表示,单个 part 的位置往往可以使用DPM (Deformable Part-based model) 来获得。同时需要考虑 pair-wise 关系来优化关键点之间的关联。

总结一下,在传统方法里面,需要关注的两个维度是: feature representation 以及关键点的空间位置关系。特征维度来讲,传统方法一般使用的 HOG, Shape Context, SIFT 等浅层特征。 空间位置关系的表示也有很多形式,上面的 Pictorial structure model 可能只是一种。

2.3 现在的方法

自从 2012 年 AlexNet 开始,深度学习开始快速发展,从最早的图片分类问题,到后来的检测,分割问题。第一次有人在 2014 年成功使用 CNN 来解决单人的姿态估计问题。受限于当时的时代背景,整体网络结构比较简单并且同时也沿用了传统思路:首先是通过滑动窗口的方式,来对每个 patch 进行分类,找到相应的人体关键点。因为直接使用滑动窗口缺少了很多 context 信息,所以会有很多 FP 的出现。所以在 pipeline 中加了一个后处理的步骤,希望能抑制部分FP,具体的实现方式是类似一个空间位置的模型。从这个工作来看,有一定的传统姿态估计方法的惯性,改进的地方是把原来的传统的特征表示改成了深度学习的网络,同时把空间位置关系当成是后处理来做处理。总体性能在当时已经差不多跑过了传统的姿态估计方法。

2014 年的另外一个重要的进展是引入了 MPII 的数据集。此前的大部分 paper 都是基于 FLIC 以及 LSP 来做评估的,但是在深度学习时代,数据量还是相对偏少(K 级别)。MPII 把数据量级提升到 W 级别,同时因为数据是互联网采集,同时是针对 activity 来做筛选的,所以无论从难度还是多样性角度来讲,都比原来的数据集有比较好的提升。

现在几乎所有的主流方法都是围绕着下面两大块进行的:改善监督信息和网络结构。

3. 改善监督信息

根据真值标签 (Ground Truth) 的类型和监督训练的方式,单人姿态估计主要有 2 种思路:基于坐标回归和基于热图检测,它们各有优缺点。

3.1 基于坐标回归(代表作:Deep Pose)

基于坐标回归的算法是将关节点的二维坐标 (coordinate) 作为 Ground Truth,训练网络直接回归得到每个关节点的坐标,这样的好处在于可以得到 sub-pixel 级别的精度,而且速度会比较快(不需要后处理)。例如在一些人脸关键点检测算法(如 mtcnn)中,会在最后一层使用全连接层直接回归出 landmark 的坐标。

在人体姿态估计领域中,这类方法的代表作是谷歌大佬提出的 Deep Pose 网络。

在上图中:蓝色部分是卷积层,绿色部分是全连接层。Deep Pose 算法主要是通过训练一个级联的姿态回归器。在第一个阶段先粗略地估计出部分的姿态轮廓,然后在下个阶段将通过已知关键点的位置不断去优化其他关键点的位置。每个 stage 都使用已经预测的关键点来 crop 出基于这个关键点的邻域子图像并用于后续的网络输入,从而得到一个更加精准的位置信息。

但是值得注意的是:一方面,全连接层(fully connected layer)容易抹掉人体关键点在图像中的空间位置信息和 context 信息。如果缺乏 context 信息,会使得模型很难区分左右手,导致 FP 容易高。另一方面,人体姿态估计这个问题本身的自由度很大。直接 regression 的方式对自由度小的问题比如人脸 landmark 可能是比较适合的,但是这会对自由度较大的姿态估计问题整体的建模能力会比较弱。

人体姿态估计的自由度较大的地方在于:例如,人的左手腕关节点既可以出现在人体的左边,也可以出现在人体的右边,因此 context 和空间位置信息就显得很重要。

3.2 基于热图检测(代表作:Simple Baseline)

Heatmap 将每个骨骼节点的坐标分别都用一个概率图来表示,这个概率图的分辨率往往是原图的等比例缩放图(一般为 64x48),channel 的个数等于关键节点的数目。

热图中的每个像素位置都会给出一个概率,表示该点属于对应类别关键点的概率,比较自然的是,距离关键点位置越近的像素点的概率越接近 1,而距离关键点越远的像素点的概率越接近 0,具体可以通过相应函数进行模拟,如 Gaussian 函数等。

微软亚洲研究院的 xiao bin 于 2018 年提出了一种基于热图检测的极其简单的单人姿态估计网络。由于它简单有效,所以作者称之为 simple baseline。该网络只是在 ResNet 后面添加一些反卷积层,甚至都没有 skip connection,这种结构可以说是从 deep 和 low 分辨率特征生成热图的最简单也是最熟悉的方法。

最后加入 1×1 的卷积层,生成 k 个关键点的预测热图,与 ground truth 热图计算 MSE 损失。

import torch.nn as nn

class JointsMSELoss(nn.Module):
def __init__(self, use_target_weight):
super(JointsMSELoss, self).__init__()
self.criterion = nn.MSELoss(size_average=True)
self.use_target_weight = use_target_weight

def forward(self, output, target, target_weight):
batch_size = output.size(0)
num_joints = output.size(1)
heatmaps_pred = output.reshape((batch_size, num_joints, -1)).split(1, 1)
heatmaps_gt = target.reshape((batch_size, num_joints, -1)).split(1, 1)
loss = 0

for idx in range(num_joints):
heatmap_pred = heatmaps_pred[idx].squeeze()
heatmap_gt = heatmaps_gt[idx].squeeze()
if self.use_target_weight:
loss += 0.5 * self.criterion(
heatmap_pred.mul(target_weight[:, idx]),
heatmap_gt.mul(target_weight[:, idx])
)
else:
loss += 0.5 * self.criterion(heatmap_pred, heatmap_gt)
return loss / num_joints

4. 改善网络结构

后续 2D 人体姿态估计方法几乎都是围绕 heatmap 这种形式来做的:通过使用神经网络来获得更好的特征表示,同时把关键点的空间位置关系隐式地 encode 在 heatmap 中进行监督学习。随着基于热图检测的方法成为标准,往后越来越多的工作聚焦在了网络结构设计上。

4.1 CPM(Convolutional Pose Machines)

经典的卷积姿态机(Convolutional Pose Machines,CPM)是CMU Yaser Sheikh组的工作,后续非常有名的 openpose 也是他们的工作。CPM 在初始阶段 (stage 1) 只对输入图片进行卷积,输出所有关节点的 heatmap。在后面的每个阶段 中,CPM 首先设计了一个特征提取器 (FeatureExtractor) 将上一个阶段输出的 heatmap 和原始图像的 feature map 级联起来,然后将这种预处理过的融合 feature map 输入 本阶段的 FCN 进行处理,最终得到新的关节点 heatmap。

CPM 由多个 stage 网络级联而成,每个 stage 设计一个小型网络,用于提取 feature。中间层的信息可以给后续层提供 context,后续 stage 可以认为是基于前面的 stage 去做 refinement。这个 refinement 过程需要感受野提供更多的 context 信息,因此感受野会越来越大。

但是通过不断增加卷积层来改变感受野会给网络产生较大的训练负担,造成梯度消失等问题。为避免加大感受野带来的副作用,CPM 采用中继监督训练,将各个阶段产生的 heatmap 与 Ground Truth 产生的误差累加起来作为总误差进行迭代,同时将梯度从各个阶段网络的输 出层反向传播,避免梯度消失,最后得到各个阶段修正后的响应 feature map,即置信图 (belief map)。CPM 在测试时以最后一个阶段的响应图输出为准。

4.2 Stacked Hourglass Network

在 2016 年的 7 月份,Princeton 的 Deng Jia 组放出了另外一个非常棒的人体姿态估计工作,堆叠式沙漏网络(Stacked Hourglass Network)。它最大的特点就是,网络既简单优美又准确高效。从上图可以看出,网络由很多重复堆叠的 u-shape 模块(如下图所示)所组成。并且在每个 u-shape 模块的旁路都添加了残差模块(Residual Module)分支,它在网络的深层梯度传导和防止过拟合方面起到关键性作用。

作者在整个网络结构中堆叠了许多 hourglass 模块,从而使得网络能够不断重复自底向上和自顶向下的过程。类似于 CPM 的多阶段学习过程,堆叠式沙漏结构 同样采用了“配套的”中继训练。但它是对每一个阶段得到的关节点 heatmap 立即根据 Ground Truth 进行重绘 (remap),并得到当前的 belief map,而不是像 CPM 累 加所有阶段的总误差再进行迭代反馈。

Illustration of the intermediate supervision process. The network splits and produces a set of heatmaps (outlined in blue) where a loss can be applied. A 1x1 convolution remaps the heatmaps to match the number of channels of the intermediate features. These are added together along with the features from the preceding hourglass.

4.3 HRNet(High-Resolution Network)

从2012年以来随着 AlexNet 横空出世,神经网络在计算机视觉领域成为主流的方法。2014年谷歌发明出了 GoogleNet,牛津大学发明了 VGGNet,2015 年微软发明了 ResNet,2016 年康奈尔大学和清华大学发明了 DenseNet,以上都是围绕分类任务而发明的网络结构。这些网络结构的一个共同的特征便是:逐步减小空间的大小,最终得到一个低分辨率的表征。低分辨率的表征在图像分类任务中是足够的,因为在图像分类里面,只需要给一个全局的标签,而不需要详细的空间信息,我们称之为空间粗粒表征的学习。

但是在其它任务中,比如检测,我们需要知道检测框的空间位置,比如分割,我们需要每个像素的标签,在人脸和人体的关键点的检测中,我们需要关键点的空间位置,这样一系列的任务实际上需要空间精度比较高的表征,我们称之为高分辨率表征。

到了 2019 年, MSRA 的 wang jingdong 组出了一个很好的工作,提出了 spatial resolution 的重要性。他认为以前网络的套路都是 feature map 的分辨率一开始虽然很高,但是会慢慢降低,然后又慢慢升高。在这个过程中,先失去了空间精度,然后慢慢恢复,最终学到的特征空间精度较弱。

因此作者提出了一种新的网络结构:分成多个层级,但是始终保留着最精细的 spaital 那一层的信息,通过 fuse 从高分辨率到低分辨率的子网络输出,来获得更多的 context 以及语义层面信息。它能够在整个过程中保持高分辨率的表示。以高分辨率子网络开始作为第一阶段,逐步增加高分辨率到低分辨率的子网络。以此内推形成更多阶段,并将多分辨率子网络并行连接。在整个过程中,通过在并行的多分辨率子网络上反复交换信息来进行多尺度的重复融合。

一直保持高分辨率的特征能够很好地保留空间位置信息,而逐步增加高分辨率到低分辨率的子网络是为了添加更多丰富的语义信息。在低分辨率方面,它可以学习到很好的语义信息;在高分辨率里,它的空间精度非常强。在整个过程中,高中低分辨率不停地交互,使得高分辨率可以拿到低分辨率语义性比较强的表征,低分辨率可以拿到高分辨率的空间精度比较强的表征,不停地融合,最终取得更强的高分辨率表征。

5. 多人姿态估计

通过单人体态估计的方法可以得到人体的2D关节点坐标,但是在一张多人图像中,模型在区别不同人体 的关节点,避免不同人体的关节点之间进行误连时,需 要额外的策略作为指导。为此,多人姿态估计的相关研究大致提供了两种思路: 自顶向下(Top-Down) 和自底向上(Bottom-Up)的。

5.1 自底向上(Bottom-Up)

自底向上的思路为:首先用单人姿态估计的方法构建部件检测器将图片中所有的人体关节点全部检测出来,然后在第二个阶段对不同人体的关节点聚成一类并拼接在一起。这类的代表作为 Open Pose,它在 2016 年的 COCO 比赛中一举夺得第一名。 CMU 团队基于 CPM 为组件,先找到图片中每个 joint 的位置,然后提出部件亲和场(Part Affinity Field,PAF) 来做人体关键点的组装。

PAF 的基本原理是在两个相邻关键点之间,建立一个有向场,比如左手腕,左手肘。我们把 CPM 找到的所有的左手腕以及左手肘拿出来建立一个二分图,边权就是基于 PAF 场来计算的。然后进行匹配,匹配成功就认为是同一个人的关节。依次类别,对所有相邻点做此匹配操作,最后就得到每个人的所有关键点。

5.2 自顶向下(Top-Down)

虽然 2016 年 bottom-up 是一个丰富时间点,但是从 2017 年开始,越来的工作开始围绕top-down 展开,一个直接的原因是 top-down 的效果往往更有潜力。top-down 相比bottom-up 效果好的原因可以认为有两点。首先是人的 recall 往往更好。因为 top-down 是先做人体检测,人体往往会比 part 更大,所以从检测角度来讲会更简单,相应找到的recall 也会更高。其次是关键点的定位精度会更准,这部分原因是基于 crop 的框,对空间信息有一定的 align,同时因为在做单人姿态估计的时候,可以获得一些中间层的 context 信息,这对于点的定位是很有帮助的。当然,top-down 往往会被认为速度比 bottom-up 会更慢(特别是人数较多的场景)。所以在很多要求实时速度,特别是手机端上的很多算法都是基于 openpose 来做修改的。不过这个也要例外,我们自己也有做手机端上的多人姿态估计,但是我们是基于 top-down 来做的,主要原因是人体检测器可以做的非常快。

参考文献