1、OpenPose
OpenPose(OpenPose: Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields)首次提出一种自下而上描述关联分数的方法:Part Affinity Fields(PAF),PAF是一组对位置和肢体方向进行编码的2D矢量场,这些自下而上的检测和关联表示能够很好地编码全局上下文,以一小部分计算成本获得高质量的结果。上图给出了OpenPose的整体流程:
(
b
)
(b)
(b)生成编码人体关键点部位的置信度图
S
S
S;
(
c
)
(c)
(c)生成编码各位置的肢体向量场
L
L
L;
(
d
)
(d)
(d)贪婪推理,解析
S
S
S 和
L
L
L,输出每一个人的2D关键点。前向网络同时预测一组身体部位位置的2D置信度图
S
S
S 和编码一组身体部分之间关联程度(亲和度)的2D矢量场
L
L
L。
S
=
(
S
1
,
S
2
,
.
.
.
,
S
J
)
,
S
j
∈
R
w
∗
h
,
j
∈
1...
J
S=(S_1,S_2,...,S_J),S_j∈R^{w∗h},j∈1...J
S=(S1,S2,...,SJ),Sj∈Rw∗h,j∈1...J具有
J
J
J 个置信图,每个关键点部位一个。
L
=
(
L
1
,
L
2
,
.
.
.
,
L
C
)
,
L
c
∈
R
w
∗
h
∗
2
,
c
∈
1...
C
L=(L_1,L_2,...,L_C),L_c∈R^{w*h*2},c∈1...C
L=(L1,L2,...,LC),Lc∈Rw∗h∗2,c∈1...C具有
C
C
C 个矢量场,每个肢体1个。
(1)网络结构
上图给出的是最新版OpenPose的网络结构示意图,需要注意的是:原版OpenPose中 S S S 和 L L L 的计算学习是交替进行的,也就是每一个stage都需要各自计算一次;后来作者发现,二者可以分开,先计算PAF(每个位置的2D矢量场,进行4次),然后计算PCM(每个位置的置信度图,进行2次)。最开始的输入 F F F 是通过VGG-19的前10层提取的图像特征映射, ϕ t \phi^t ϕt 表示的是进行一个PAF预测的CNN网络, ρ t \rho^t ρt 表示的是进行一个PCM预测的CNN网络。用数学表达式来解释就是 { L 1 = ϕ 1 ( F ) , t = 1 L t = ϕ t ( F , L t − 1 ) , ∀ 2 ≤ t ≤ T P S T P + 1 = ρ t ( F , L T P ) , t = T P + 1 S t = ρ t ( F , L T P , S t − 1 ) , ∀ T P + 2 ≤ t ≤ T P + T C \begin{cases} \mathbf{L}^{1}=\phi^{1}(\mathbf{F}),t=1 \\ \mathbf{L}^{t}=\phi^{t}\left(\mathbf{F}, \mathbf{L}^{t-1}\right),\forall 2 \leq t \leq T_{P} &\\ \mathbf{S}^{T_{P}+1}=\rho^{t}\left(\mathbf{F}, \mathbf{L}^{T_{P}}\right),t=T_{P}+1 \\ \mathbf{S}^{t}=\rho^{t}\left(\mathbf{F}, \mathbf{L}^{T_{P}}, \mathbf{S}^{t-1}\right),\forall T_{P}+2 \leq t \leq T_{P}+T_{C} \\ \end{cases} ⎩⎪⎪⎪⎨⎪⎪⎪⎧L1=ϕ1(F),t=1Lt=ϕt(F,Lt−1),∀2≤t≤TPSTP+1=ρt(F,LTP),t=TP+1St=ρt(F,LTP,St−1),∀TP+2≤t≤TP+TC
(1)根据上图的示意, ρ \rho ρ 的范围是 ( T P , T C ] (T_P,T_C] (TP,TC],并不包括 t = T P t=T_P t=TP,原文中公式(2)(3)似乎有错, ρ \rho ρ 也写成了 ϕ \phi ϕ。
(2)着重要注意每一层网络的输入, ρ \rho ρ 网络的每一层都需要将 L T P L^{T_P} LTP 作为输入包含进来。
(2)损失函数
网络在每一层给出一个损失函数,具体的定义如下:
f
L
t
i
=
∑
c
=
1
C
∑
p
W
(
p
)
⋅
∥
L
c
t
i
(
p
)
−
L
c
∗
(
p
)
∥
2
2
f
S
t
k
=
∑
j
=
1
J
∑
p
W
(
p
)
⋅
∥
S
j
t
k
(
p
)
−
S
j
∗
(
p
)
∥
2
2
\begin{aligned} f_{\mathbf{L}}^{t_{i}} &=\sum_{c=1}^{C} \sum_{\mathbf{p}} \mathbf{W}(\mathbf{p}) \cdot\left\|\mathbf{L}_{c}^{t_{i}}(\mathbf{p})-\mathbf{L}_{c}^{*}(\mathbf{p})\right\|_{2}^{2} \\ f_{\mathbf{S}}^{t_{k}} &=\sum_{j=1}^{J} \sum_{\mathbf{p}} \mathbf{W}(\mathbf{p}) \cdot\left\|\mathbf{S}_{j}^{t_{k}}(\mathbf{p})-\mathbf{S}_{j}^{*}(\mathbf{p})\right\|_{2}^{2} \end{aligned}
fLtifStk=c=1∑Cp∑W(p)⋅∥∥Lcti(p)−Lc∗(p)∥∥22=j=1∑Jp∑W(p)⋅∥∥Sjtk(p)−Sj∗(p)∥∥22其中,
W
(
p
)
\mathbf{W(p)}
W(p) 是一个二进制位,当p点所在位置没有标注时
W
(
p
)
=
0
\mathbf{W(p)}=0
W(p)=0,它的目的是避免在训练过程中惩罚真正积极的预测(指的是轻微遮挡的位置?);
L
c
t
i
(
p
)
、
S
j
t
k
(
p
)
{\mathbf{L}}_c^{t_i}(\mathbf{p})、{\mathbf{S}}_j^{t_k}(\mathbf{p})
Lcti(p)、Sjtk(p) 表示网络在p点的预测值,
L
c
∗
(
p
)
、
S
j
∗
(
p
)
{\mathbf{L}}_c^{*}(\mathbf{p})、{\mathbf{S}}_j^{*}(\mathbf{p})
Lc∗(p)、Sj∗(p) 表示p点的真实值(也就是需要事先定义好的label,它来自于对图像的标注)。
S
j
,
k
∗
(
p
)
=
exp
(
−
∥
p
−
x
j
,
k
∥
2
2
σ
2
)
S
j
∗
(
p
)
=
max
k
S
j
,
k
∗
(
p
)
\begin{array}{l}{\mathbf{S}_{j, k}^{*}(\mathbf{p})=\exp \left(-\frac{\left\|\mathbf{p}-\mathbf{x}_{j, k}\right\|_{2}^{2}}{\sigma^{2}}\right)} \\ {\mathbf{S}_{j}^{*}(\mathbf{p})=\max \limits_k \mathbf{S}_{j, k}^{*}(\mathbf{p})}\end{array}
Sj,k∗(p)=exp(−σ2∥p−xj,k∥22)Sj∗(p)=kmaxSj,k∗(p)这里的
k
k
k 表示的是第
k
k
k 个人,因为每个人都拥有关键点
p
j
p_j
pj,该位置附近的置信度类似呈高斯分布;如果是多人的情况,
S
j
S_j
Sj 置信度图上将有多个类似高斯分布,它们之间会有交集,这时作者采取求并集、取最大值的方法来获取最终的
S
j
S_j
Sj。
σ
\sigma
σ 控制了真实关节点的控制范围,该参数值越大
S
j
,
k
∗
(
p
)
\mathbf{S}_{j,k}^*(\mathbf{p})
Sj,k∗(p) 就越大,预测准确性相对会减小。
L
c
,
k
∗
(
p
)
=
{
v
if
p
on limb
c
,
k
0
otherwise.
L
c
∗
(
p
)
=
1
n
c
(
p
)
∑
k
L
c
,
k
∗
(
p
)
v
=
(
x
j
2
,
k
−
x
j
1
,
k
)
/
∥
x
j
2
,
k
−
x
j
1
,
k
∥
2
\begin{array}{l} {\mathbf{L}_{c, k}^{*}(\mathbf{p})=\left\{\begin{array}{ll}{\mathbf{v}} & {\text { if } \mathbf{p} \text { on limb } c, k} \\ {\mathbf{0}} & {\text { otherwise. }}\end{array}\right.} \\ {\mathbf{L}_{c}^{*}(\mathbf{p})=\frac{1}{n_{c}(\mathbf{p})} \sum_{k} \mathbf{L}_{c, k}^{*}(\mathbf{p})} \\ \mathbf{v}=\left(\mathbf{x}_{j_{2}, k}-\mathbf{x}_{j_{1}, k}\right) /\left\|\mathbf{x}_{j_{2}, k}-\mathbf{x}_{j_{1}, k}\right\|_{2} \end{array}
Lc,k∗(p)={v0 if p on limb c,k otherwise. Lc∗(p)=nc(p)1∑kLc,k∗(p)v=(xj2,k−xj1,k)/∥xj2,k−xj1,k∥2上面的三个公式给出了从标注数据计算PAF-label的方法:如果点
p
p
p 在第
k
k
k 个人的肢体
c
c
c 上,那么它的矢量方向就是
v
v
v(这是一个由
j
1
j_1
j1 指向
j
2
j_2
j2 的单位向量);如果有一点
p
p
p 被多个人共享,那么就取均值,这跟上面的
S
j
S_j
Sj 的多人处理方法稍有区别。还有一个问题就是,如何判断
p
p
p 是否位于肢体
c
c
c 上呢?下式给出判断公式:
0
≤
v
⋅
(
p
−
x
j
1
,
k
)
≤
l
c
,
k
and
∣
v
⊥
⋅
(
p
−
x
j
1
,
k
)
∣
≤
σ
l
0 \leq \mathbf{v} \cdot\left(\mathbf{p}-\mathbf{x}_{j_{1}, k}\right) \leq l_{c, k} \text { and }\left|\mathbf{v}_{\perp} \cdot\left(\mathbf{p}-\mathbf{x}_{j_{1}, k}\right)\right| \leq \sigma_{l}
0≤v⋅(p−xj1,k)≤lc,k and ∣v⊥⋅(p−xj1,k)∣≤σl现在我们有了每一点的置信度图
S
S
S 和
2
D
2D
2D 矢量场图
L
L
L,现在考虑如何通过这两个数据来获取最终的输出。
S S S:0-17号关键点,所以有18个和图像同尺寸的置信度图,每一个图有多个峰值点,理想情况是一个峰值点对应一个人,到目前为止还做不到,因为单个人的该关键点可能存在多个候选点;
L L L:一共有 c c c 个肢体,所以就有 c c c 个PAF图,每一个PAF图给出了每一点的矢量方向,这里就不再是像 S S S 中那样只有有限个峰值点,这里每个位置又会有一个矢量,只是矢量值有可能为0而已,而且这每一个位置的矢量值都有可能用到。
想一想:如果我们从所有的 S S S 候选点中去寻找最优的关节点,那么是不是同一个人的同一个关节点的候选位置也会参与到肢体连接的判断中?这将会是一个K分图的最优解问题,作者并没有这样做。注意到 S S S 中每一个置信度图其实是有顺序关系的,或者说可以人为给它们顺序: S 1 S_1 S1 是左膝关节, S 2 S_2 S2 是左脚踝, S 3 S_3 S3 是右膝关节, S 4 S_4 S4 是右脚踝,那么就只让 S 1 S_1 S1 和 S 2 S_2 S2 去做匹配, S 3 S_3 S3 和 S 4 S_4 S4 去做匹配, S 1 S_1 S1 和 S 1 、 S 3 、 S 4 S_1、S_3、S_4 S1、S3、S4 等是不需要做匹配的,这样就把问题转换成一个二分图的最大匹配问题。现在有候选点的集合 D J = d j m : for j ∈ 1 … J , m ∈ 1 … N j D_{J}=d_{j}^{m} : \text { for } j \in 1 \ldots J, m \in 1 \ldots N_j DJ=djm: for j∈1…J,m∈1…Nj d j m d_j^m djm就代表每一个置信度图上的候选点,对于 m m m 我们并不知道它归属于哪一个人。假设现在需要找到以关节点 j 1 、 j 2 j_1、j_2 j1、j2 作为端点的肢体连接,那就需要找到 D j 1 、 D j 2 D_{j_1}、D_{j_2} Dj1、Dj2 的带权最大匹配。
上图左边给出了一个带权匹配的示意, E 13 、 E 41 、 E 65 E_{13}、E_{41}、E_{65} E13、E41、E65 就是每条边的权值,每条边归属于一个人;右边的公式第一个是计算最大匹配的方法, z j 1 j 2 m n z_{j_1j_2}^{mn} zj1j2mn 表示候选点之间是否发生连接关系,例如 z j 1 j 2 13 = 1 z_{j_1j_2}^{13}=1 zj1j213=1 就表示发生连接, z j 1 j 2 34 = 0 z_{j_1j_2}^{34}=0 zj1j234=0 就表示不发生连接;下面两个公式是约束,意思就是:对于 D j 1 、 D j 2 D_{j_1}、D_{j_2} Dj1、Dj2 中的任何一个点,它只会与对面的集合中的一个点发生连接,不会有一对多的情况发生。没有发生连接的候选点就表示被抛弃掉了,意味着它是不准的。这里权值 E m n E_{mn} Emn 的计算方式为 E = ∫ u = 0 u = 1 L c ( p ( u ) ) ⋅ d j 2 − d j 1 ∥ d j 2 − d j 1 ∥ 2 d u p ( u ) = ( 1 − u ) d j 1 + u d j 2 \begin{aligned} E=& \int_{u=0}^{u=1} \mathbf{L}_{c}(\mathbf{p}(u)) \cdot \frac{\mathbf{d}_{j_{2}}-\mathbf{d}_{j_{1}}}{\left\|\mathbf{d}_{j_{2}}-\mathbf{d}_{j_{1}}\right\|_{2}} d u \\ \mathbf{p}(u) &=(1-u) \mathbf{d}_{j_{1}}+u \mathbf{d}_{j_{2}} \end{aligned} E=p(u)∫u=0u=1Lc(p(u))⋅∥dj2−dj1∥2dj2−dj1du=(1−u)dj1+udj2作者采用线积分的方式来计算权值, m 、 n m、n m、n 就对应了点 d j 1 、 d j 1 d_{j_1}、d_{j_1} dj1、dj1, L c L_c Lc 是前面网络输出的, p ( u ) \mathbf{p}(u) p(u) 表示两个端点之间的任意一点, u u u 的范围是 [ 0 , 1 ] [0,1] [0,1]。通过匈牙利算法就能够找到该肢体的最优候选端点,要找到所有肢体的最优端点,就用下式 max Z E = ∑ c = 1 C max Z c E c \max _{{Z}} E=\sum_{c=1}^{C} \max _{\mathcal{Z}_{c}} E_{c} ZmaxE=c=1∑CZcmaxEc最终我们要的就是这个最大匹配 Z Z Z,因为每一个关节点最多连接两个其他点,所以找到的最大匹配肢体串起来就形成单个人的姿态估计。
这里忽略了二分图匹配问题的介绍,以及匈牙利算法的具体内容,但是这两部分是最后“贪婪推理”的基础,需要理解。
(3)整体效果
OpenPose在速度、精度上都很优秀,不会因为人数增加而产生速度上的延迟,不依赖于人体的姿势;同时它并不仅仅针对人体关键点的检测,其他物体(例如汽车)也可以用同样的方式来实现关键点检测。
2、CPN
CPN(Cascaded Pyramid Network for Multi-Person Pose Estimation,级联金字塔网络)是2017 COCO Keypoints Challenge的冠军(同年亚军是AlphaPose),由旷视完成。它的主要工作是人体关键点检测,也就是说它是建立在人体边框检测的基础之上的,原文的人体边框检测是由FPN(就是Mask RCNN中用到的那个)完成的。
对于脸部特征来来说我们一般根据表观特征就能检测定位,但是对于膝盖、肘关节等位置,由于衣物的包裹它们是不容易仅仅靠外观表征去定位的。在遮挡、重叠、拥挤等情境下,这些难以被检测的关键点成为“hard-keypoints”,CPN的重点就是解决对于“hard-keypoints”的检测。CPN由两个环节构成:GlobalNet,RefineNet。
(1)GlobalNet
GlobalNet基于ResNet,作者分别在ResNet-50、ResNet-101做了研究,这里以ResNet-50为例来说明。ResNet-50有四级特征输出:conv2_x,conv3_x,conv4_x,conv5_x,GlobalNet就是在这四级特征(简称为C2/C3/C4/C5)上做文章。
浅层特征C2/C3 在定位上有着较高的空间分辨率,但是在识别上语义信息较少;由于卷积(和池化)的存在,深度特征层 C4/C5语义信息较多,但空间分辨率较低。因此GlobalNet引入 U 型结构,同时保留特征层的空间分辨率和语义信息。所谓的 U 型特征指的就是特征融合:GlobalNet将低层特征进行上采样,然后与上一层特征相加,实现不同尺度特征的融合。完了之后,再将融合的特征进行上采样,统一得到原始图像1/4大小的特征,进行该阶段的L2-loss计算。
GlobalNet对于简单点(人眼、耳)的识别是比较有效的,但是对于像left hip这样的位置则比较难识别(看上图右边)。这时就要将GlobalNet的四级特征送入RefineNet,进行再识别。
(2)RefineNet
RefineNet接受了GlobalNet传过来的所有特征,为提升信息传输的效率、保证信息完整性,RefineNet 在不同层之间传输信息,并通过上采样和连接把这些信息整合起来。同时RefineNet还加入了更多的bottleneck,在较小的空间尺度上可实现效率和性能的平衡。
需要注意的是:GlobalNet的L2-loss是将网络输出与所有label的groundtruth做计算,然后全部用于反向传播;但是在RefineNet中,计算loss后会将其从大到小排序,然后选择top-k进行反向传播,这就是为什么在上上图中有
L
2
−
l
o
s
s
∗
L2-loss^*
L2−loss∗ 的存在。这种方式可以让RefineNet更关注那些难以识别的关键点,而稍微放松对能够在GlobalNet中识别出来的简单点的约束。
这里要关注一下GlobalNet、RefineNet中的几个关键位置:
(1)C2-C5的重要性:作者最后通过对比试验 T a b l e − 5 Table-5 Table−5 得出,完整使用C2-C5效果是最好的;
(2)bottleneck的重要性:可以看对比试验的 T a b l e − 4 Table-4 Table−4 的对比;
(3) L 2 − l o s s ∗ L2-loss^* L2−loss∗ 中top-k的k取值: k = 8 k=8 k=8 是最好的,也就是说一般会有8个比较难识别的点,这是 T a b l e − 6 Table-6 Table−6 的结果。
(3)整体效果
CPN网络在Top-Bottom过程中扮演的是bottom的角色,也就是说它在一定程度上取决于top结果的好坏。CPN针对单人做姿态估计,单人所在区域不必太过精确,只需保证区域包含完整人体即可;在这种前提下,CPN的检测速度完全可以达到实时,且精度也很高(从肉眼上来看与OpenPose不相上下)。
其弊端在于,在多人情况下需要先执行人体检测,密集环境下人体存在重叠,RCNN/FRN等网络虽然可以快速准确地得到人体矩形框,但矩形框内部存在较高频率的人体重叠,会影响CPN的检测效果;Mask RCNN能得到个体的掩码,将个体掩码区域作为CPN的输入可以降低重叠对CPN的影响,但是效果依然不太理想。