参考代码:openpose
导读:这篇文章提出了一种bottom-up的2D图像多人关键点(躯干/手脚/面部,使用掩膜控制训练整合数据集)检测算法,这样使得整体网络的运算时间并不与图像中人数呈现显著相关的关系。在这篇文章中提出了PAFs(Part Affinity Fileds)(用于去编码关键点的位置与方向信息),用于去建模每个部位之间的相互关系,并且文章发现同时去优化PAFs和人体的部位并不是最优的选择,先去优化PAFs而不是同时去优化它们两个能带来更好的性能表现。这篇文章的方法也是涵盖了人体大致的关键点检测问题,还是很具有意义和借鉴价值的,值得细读(在1080 Ti上能跑到22FPS,VGG19)。
2D图像人体姿态估计面临的问题:
现有的人体关键点的检测方法分类:
而文章的方法是通过bottom-up的方式进行关键点检测的,下图中上半部分是在2D图像中多人关键点检测的结果,下半部分是文章使用PAFs得到的关键点之间的联系关系图,用于将不同位置的关键点连接起来。
文章的整体算法流程见图2所示:
对于一张输入的图像 h ∗ w h*w h∗w,首先会在其基础上预测出关键点的特征图 S = ( S 1 , S 2 , … , S J ) , S j ∈ R w ∗ h , j ∈ { 1 , … , J } S=(S_1,S_2,\dots,S_J),S_j\in R^{w*h},j\in \{1,\dots,J\} S=(S1,S2,…,SJ),Sj∈Rw∗h,j∈{1,…,J},分别代表不同的关键点部位。之后会预测出关键点之间关系的向量 L = { L 1 , L 2 , … , L c } , L c ∈ R w ∗ h ∗ 2 , c ∈ { 1 , … , C } L=\{L_1,L_2,\dots,L_c\},L_c\in R^{w*h*2},c\in \{1,\dots,C\} L={L1,L2,…,Lc},Lc∈Rw∗h∗2,c∈{1,…,C},对应的就是图中b,c部分。最后在PAFs的基础上使用贪心算法得到人体关键点的连接关系。
文章的提出的关键网络结构部分见下图所示:
这里使用迭代的形式 t ∈ [ 1 , … , T ] t\in [1,\dots,T] t∈[1,…,T]递归优化关键点间关系预测与关键点定位(在相同条件下文章的实验结果表明将关系预测放在定位之前能带来更好的性能,反过来则不能带来结论就不成立),并且在对应的部分都有设置损失函数进行监督,从而级连优化回归的目标。而且文章还将之前论文中的 7 ∗ 7 7*7 7∗7的卷积替换成为了类似DenseNet的3个 3 ∗ 3 3*3 3∗3卷积的形式,从而使得在网络的精度和速度上均有所改善。
这篇文章使用VGG-19作为其backbone,其产哼的特征图为 F F F,之后送入关键点关联性预测得到 L 1 = ϕ 1 ( F ) L^1=\phi^1(F) L1=ϕ1(F),对应的上角标代表的是不同的迭代优化轮数。之后的关键点关联性采用迭代优化的形式进行:
L t = ϕ t ( F , L t − 1 ) , ∀ 2 ≤ t ≤ T p L^t=\phi^t(F,L^{t-1}),\forall 2\le t\le T_p Lt=ϕt(F,Lt−1),∀2≤t≤Tp
而关键点的定位也是跟关键点关联性预测类似的过程,完成最后的关联性预测之后于之前的特征整合就可以用来预测关键点: S T p = ρ t ( F , L T p ) , ∀ t = T p S^{T_p}=\rho^t(F,L^{T_p}),\forall t=T_p STp=ρt(F,LTp),∀t=Tp
那么对于后续阶段关键点定位的预测迭代形式为:
S t = ρ t ( F , L T p , S t − 1 ) , ∀ T p < t ≤ T p + T c S^t=\rho^t(F,L^{T_p},S^{t-1}),\forall T_p\lt t \le T_p+T_c St=ρt(F,LTp,St−1),∀Tp<t≤Tp+Tc
文章回归用的损失函数是 L 2 L_2 L2损失函数,并且由于文章是联合多个数据集进行训练的,因而会存在一些关键点不存在的问题,为此提出了一个二值掩膜 W W W,其在没有标注的地方将其值设置为 W ( p ) = 0 W(p)=0 W(p)=0。因而文章的关键点相关性与关键点位置的损失函数可以定义为:
f L t i = ∑ c = 1 C ∑ p W ( p ) … ∣ ∣ L c t i ( p ) − L c ∗ ( p ) ∣ ∣ 2 2 f_L^{t_i}=\sum_{c=1}^C\sum_pW(p)\dots||L_c^{t_i}(p)-L_c^{*}(p)||_2^2 fLti=c=1∑Cp∑W(p)…∣∣Lcti(p)−Lc∗(p)∣∣22
f S t i = ∑ j = 1 J ∑ p W ( p ) … ∣ ∣ S j t k ( p ) − S j ∗ ( p ) ∣ ∣ 2 2 f_S^{t_i}=\sum_{j=1}^J\sum_pW(p)\dots||S_j^{t_k}(p)-S_j^{*}(p)||_2^2 fSti=j=1∑Jp∑W(p)…∣∣Sjtk(p)−Sj∗(p)∣∣22
那么总的损失函数就是两者的和:
f = ∑ t = 1 T p f L t + ∑ t = T p + 1 T p + T c f S t f=\sum_{t=1}^{T_p}f_L^t+\sum_{t=T_p+1}^{T_p+T_c}f_S^t f=t=1∑TpfLt+t=Tp+1∑Tp+TcfSt
这篇文章中关键点的标注是使用高斯函数进行的,那么对于关键点坐标为 x j , k ∈ R 2 x_{j,k}\in R^2 xj,k∈R2其对应的回归目标为 S j , k ∗ S_{j,k}^{*} Sj,k∗,则其计算表达为:
S j , k ∗ ( p ) = e x p ( − ∣ ∣ p − x j , k ∣ ∣ 2 2 σ 2 ) S_{j,k}^{*}(p)=exp(-\frac{||p-x_{j,k}||_2^2}{\sigma^2}) Sj,k∗(p)=exp(−σ2∣∣p−xj,k∣∣22)
那么存在相邻关键点重叠的时候怎么办呢?文章中是使用最大值优先原则:
S j ∗ ( p ) = max k S j , k ∗ p S_j^{*}(p)=\max_kS_{j,k}^{*}{p} Sj∗(p)=kmaxSj,k∗p
使用最大值优先原则而不是平均值,这样可以使得相邻的关键点区分度得到保留,见下图所示:
对于关键点间关系的描述文章参考了一些策略,并得出一种切实可行的方案,见下图所示:
在图a中呈现了很多的关键点,那么怎么才能将这些关键点与单独的人关联起来,并且建模关键点之间的联系?一个简单的思路就是在关键点之间选择一个中间锚点,如图b所示。但是这种方法在人较为密集的时候就会存在关联错误的情况,导致关联错误的原因有:
对于这样的问题文章提出了图c中的策略,就是去建模关键点的位置与方向信息,也就是文章所说的PAFs。考虑下图中的人体肢体:
图中有两个关键点 x j 1 , k x_{j_1,k} xj1,k和 x j 2 , k x_{j_2,k} xj2,k,若是其中在肢体上存在一个点 p p p起对应的标注值为 L c , k ∗ ( p ) L_{c,k}^{*}(p) Lc,k∗(p) ,它是一个从点 j 1 j_1 j1到 j 2 j_2 j2的单位向量(用于表示关键点之间的方向信息),而其它的位置值就是0了。
那么对于在肢体上的点 p p p其对应生成的标注信息可以描述为:
其中, v = ( x j 2 , k − x j 1 , k ) ∣ ∣ x j 2 , k − x j 1 , k ∣ ∣ 2 v=\frac{(x_{j_2,k}-x_{j_1,k})}{||x_{j_2,k}-x_{j_1,k}||_2} v=∣∣xj2,k−xj1,k∣∣2(xj2,k−xj1,k)是一个单位向量,但是对于这样的标注点其也是有一个范围限定的,文章中将其限定为:
0 ≤ v … ( p − x j 1 , k ) ≤ l c , k , a n d ∣ v ⊥ … ( p − x j 1 , k ) ∣ ≤ σ l 0\le v\dots(p-x_{j_1,k})\le l_{c,k},and |v_{\perp}\dots(p-x_{j_1,k})|\le \sigma_l 0≤v…(p−xj1,k)≤lc,k,and∣v⊥…(p−xj1,k)∣≤σl
其中, σ l \sigma_l σl代表的是像素的距离, l c , k = ∣ ∣ x j 2 , k − x j 1 , k ∣ ∣ 2 l_{c,k}=||x_{j_2,k}-x_{j_1,k}||_2 lc,k=∣∣xj2,k−xj1,k∣∣2是肢体的长度, k k k代表的是不同的人。那么对应的关键点相关性信息标注(回归目标)就可以描述为(归一化):
L c ∗ ( p ) = 1 n c p ∑ k L c , k ∗ ( p ) L_c^{*}(p)=\frac{1}{n_c{p}}\sum_kL_{c,k}^{*}(p) Lc∗(p)=ncp1k∑Lc,k∗(p)
在进行infer的时候文章是通过预测出来的PAFs和关键点计算关键点之间的度量,因而对于两个预测出来的关键点 d j 1 , d j 2 d_{j_1},d_{j_2} dj1,dj2,它们之间的度量可以描述为:
E = ∫ u = 0 u = 1 L c ( p ( u ) ) … d j 2 − d j 1 ∣ ∣ d j 2 − d j 1 ∣ ∣ 2 d u E=\int_{u=0}^{u=1}L_c(p(u))\dots\frac{d_{j_2}-d_{j_1}}{||d_{j_2}-d_{j_1}||_2}d_u E=∫u=0u=1Lc(p(u))…∣∣dj2−dj1∣∣2dj2−dj1du
其中, p ( u ) = ( 1 − u ) d j 1 + u d j 2 p(u)=(1-u)d_{j_1}+ud_{j_2} p(u)=(1−u)dj1+udj2 ,两个点插值得到的结果。
在得到一堆关键点之后,可以通过上述内容中的计算公式得到任意两个关键点之间的相关度信息,但是怎么在这么多关键点之间寻找合适的组合分配仍然是一个很难的问题,见下图6(a)所示:
在文中用 z j 1 j 2 m n ∈ { 0 , 1 } z_{j_1j_2}^{mn}\in \{0,1\} zj1j2mn∈{0,1}表示两个关键点是否连接,那么对于整个检测出来的关键点其需要优化的模型为:
但是直接去解决上面的问题是NP难的,为此文章将这个问题使用两个简化的问题并使用贪心的策略去解决它。文中将原问题做了如下的简化:
之后文中提到是使用贪心的算法进行关键点的连接,并且还做了一些关键点过滤的操作。