3D人体姿态估计(3 Demensional Human Pose Estimation)的目标是在单张/多张RGB图片或2D人体姿态坐标的基础上,预测人体的三维坐标。目前流行的方法包括由单张图像直接预测3维姿态坐标、由多目图像构建3D空间位置信息、由2D姿态坐标预测3D姿态等。
其中第一种方法最为直接,通过深度学习模型建立单目RGB图像到3维坐标的端到端映射,但是对于单一模型来说需要学习的特征太过复杂,目前流行的网络模型难以达到理想的性能,大部分实验中表现较好的模型需要额外的信息如相机参数等作为计算3D坐标的辅助参数,或使用GAN等特殊网络结构来学习参数进行训练。
第二种方法使用多目图片获得3维空间位置信息,在已知镜头位置或拍照角度的情况下可以通过数学运算或机器学习方法构建空间坐标系,从而在预测出2D姿态的后直接加入深度信息,可以达到不错的性能;但是这种方法需要多目图像作为输入,在进行应用时对输入设备的数量和摆放位置等具有较高要求。
第三种方法相当于在单张图像的基础上先得到了2D姿态信息,减少了模型在2D姿态估计上的学习压力,能够通过简单的矩阵相乘或轻量级网络学习3D姿态,但是由于缺少原始图像输入,可能会丢失一些空间信息,造成预测时误差;另外,由于这种方法依赖于2D姿态输入,因此2D姿态估计的误差会在3D估计的过程中放大。
下面介绍2019CVPR中两种3D姿态生成的方法,根据目前个人业务的需要都是通过2D姿态估计的结果生成。
Semantic Graph Convolutional Networks for 3D Human Pose Regression (2019CVPR)
github
首先了解一下图卷积(GCN)的基本概念:
现有的卷积神经网络研究的对象大多数是图像、语音、文本这种能够用一维、二维的矩阵表示的数据,这种数据有天然的维度对齐特性,即使不同的数据也可以对齐到同样的特征尺度和矩阵维度。
但是,计算机数据结构中的图、树,大数据知识图谱等数据不满足这种特性。这些数据结构每个节点的连接数量、方向等都不相同,在深度学习中常见的处理方法是转换成列矩阵或按最大图结构转换成稀疏矩阵,这两种方法会导致空间信息的丢失或者特征维度的膨胀,采用图卷积是当前对这种数据最有效的分析处理方式之一。
图卷积的基本计算公式,是由卷积基本公式经过傅里叶变换得到的,在这里不展开讲,可以在这里看到推导:
其中c是归一化因子,N表示节点i的邻居,R表示节点i的类型,W表示权重,外层非线性变换。
其计算过程为:
第一步:发射(send)每一个节点将自身的特征信息经过变换后发送给邻居节点。这一步是在对节点的特征信息进行抽取变换。
第二步:接收(receive)每个节点将邻居节点的特征信息聚集起来。这一步是在对节点的局部结构信息进行融合。
第三步:变换(transform)把前面的信息聚集之后做非线性变换(ReLU等),增加模型的表达能力。
GCN四个特征:
本文方法采用的语义图卷积模型,就是传统图卷积的一种延伸。可以看出2D姿态坐标在原图中的连接方式就是一种图连接,而我们的需求就是生成一个3D的姿态坐标,同样是一种图数据,非常适合使用图卷积进行端到端学习。
目前GCN的结构局限于卷积滤波器的小接收域和每个节点的共享变换矩阵。SemGCN的提出一定程度上解决了这些局限性,论文提出了全新的语义图卷积网络,用于处理具有图结构数据的回归任务。SemGCN学习捕获在图中没有显式表示的语义信息,例如局部和全局节点关系。这些语义关系可以通过端到端训练学习,而不需要额外的监督或手工特征。实验结果表明,SemGCN在使用的参数减少了90%的情况下,性能仍优于现有的技术水平。
论文由GCN的基本公式(下式)出发,加入了残差设计作为工作的Baseline,称之为ResGCN。
在本文中,GCN的基本公式有两点不足:
在此基础上作者与传统的CNN结构相结合,提出了语义图卷积。主要思路是将CNN中单个卷积核提取多维特征的能力引用到GCN上,首先对每一个位置学习独立的权重向量a,然后使用一个共享的转换矩阵W把不同的a结合起来,因此上式可以转换为:
这里ρ是对节点i的所有输入矩阵进行的Softmax变换;⊙是一个矩阵元素级别的运算:如果在ρ操作后矩阵A中元素的值为1或是指数非常接近0的负数,那么运算将返回对应M中对应位置的值。矩阵A用来约束每个节点每次只计算其相邻节点的权重。
进一步地,可以把公式延伸成下式:
其中Md是在不同通道上的权重矩阵,结果通过||进行通道维度的拼接,这里wd是不同通道上的转换矩阵。
上图解释了SemGCN与CNN的对比关系,图a中CNN每个3x3卷积相当于对卷积核覆盖区域中的每个点学习一个权重向量,再通过转换矩阵W把它们结合起来。图b中的卷积GCN仅学习了所有节点共享的转换矩阵W0,图c和图d对应了上面的两个公式,采用分离每个节点权重向量和转换矩阵的形式实现感受野的扩大,同时学习全局与局部特征。网络结构如下:
网络中的Non Local模块进行如下操作:
其中W初始化为0,f是成对的函数操作,用于学习节点i和除此之外所有节点j之间的密切程度。
整个模型的结构如下:
在应用过程中,网络可以采用原始图像或2D关节点作为输入,如果输入图像则使用ResNet提取特征,采用RoIAlign提取卷积层输出,与2D坐标进行拼接后输入SemGCN。网络的损失函数为:
由于图方法只关注于点以及点之间的连接,而不需要一整个图像矩阵作为输入,因此可以大大减少参数量和运算速度。从下表可知,本文方法较其他方法节省90%的参数,并达到同等效果。
阅读代码,对于16个节点的输入,每个 ResGraphConv (X)的操作为:
Input = X: batch, 16, channels
W: 2, channels, 128
h0 = X*W[0]: 16, 128
h1 = X*W[1]: 16,128
adj: 16, 16 描述节点关系的稀疏矩阵(没有节点、没有连接的下标对应元素为0,其余按节点和连接分配权重)
M: 16, 16 对角矩阵
Out = (adj•M)*h0 + (adj•(1-M))*h1
以上为一个block,执行两次加X作为残差,输出。
每个Graph_non-local (X)的操作为:
g_x = X: batch,128,16 – conv1d(128,64):batch, 64, 16
– maxpool1d(2):batch, 64, 8 – trans:batch, 8, 64
theta_x = X: batch,128,16 - conv1d(128,64):batch, 64, 16 – view:batch,64,16,1
phi_x = X: batch,128,16 - conv1d(128,64):batch, 64, 16
– maxpool1d(2):batch, 64, 8 – view:batch,64,1,8
f = theta_x与phi_x对齐,拼接: batch, 128, 16, 8
– conv2d(128,1):1,1,16,16 – view: batch, 16, 16
f_div_C = f/16
y = f_div_C*g_x: 1, 16, 64 – conv1d(64,128): batch, 16, 128
RepNet: Weakly Supervised Training of an Adversarial Reprojection Network for 3D Human Pose Estimation (2019CVPR)
github
首先了解GAN的基本概念:
GAN的基本原理其实非常简单,这里以生成图片为例进行说明。假设我们有两个网络,G(Generator)和D(Discriminator)。它们的功能分别是:
• G是一个生成图片的网络,它接收一个随机的噪声z,通过这个噪声生成图片,记做G(z)。
• D是一个判别网络,判别一张图片是不是“真实的”。它的输入参数是x,x代表一张图片,输出D(x)代表x为真实图片的概率,如果为1,就代表100%是真实的图片,而输出为0,就代表不可能是真实的图片。
在训练过程中,生成网络G的目标就是尽量生成真实的图片去欺骗判别网络D。而D的目标就是尽量把G生成的图片和真实的图片分别开来。在最理想的状态下,G可以生成足以“以假乱真”的图片G(z)。对于D来说,它难以判定G生成的图片究竟是不是真实的,因此D(G(z)) = 0.5。
训练的目的就是得到一个生成式模型G,用来生成图片。
以上只是大致说了一下GAN的核心原理,论文里的损失函数公式为:
本文采用弱监督学习方法,使用GAN生成的鉴别器网络来学习3D人体姿态分布,从而摆脱了训练数据对3D姿态标签的依赖。另一个神经网络学习从检测到的2D关键点分布到3D关键点分布的映射,其映射的3D结果送入鉴别器网络进行判断。从生成对抗网络的角度来看,可以将其看做生成器网络。为了使生成器网络生成与2D观测结果相匹配的3D姿态,作者还添加了第三个神经网络,该网络能够根据输入数据预测出摄像机参数。推断出的摄相机参数用于将估计的3D姿态重新投影回2D,从而判断预测姿态与原始2D输入的偏差。
上图展示了该方法由包含噪声的2D关键点坐标预测出3D姿态坐标,这个弱监督方法不需要2D到3D对应的坐标点信息,而在3D投影回2D时由判别器强行约束计算一个可信的3D姿态。即使原始输入包括是强烈的变形和奇怪的相机角度,此模型也可以重建3D姿态。
下图是网络结构:
该模型包含三个结构:
普通GAN大多是由特定分布作为生成器输入,而RepNet直接采用2D姿态+噪声。
在作者的代码中,使用Keras定义了四个网络:
cam_net = Model(inputs=pose_in, outputs=cam_out)
rep_net = Model(inputs=pose_in, outputs=rec_pose)
generator = Model(inputs=pose_in, outputs=pose_out)
discriminator = Model(inputs=d_in, outputs=d_out)
上面四个网络中的前三个的输入都是长为2*关节点个数的坐标序列,将他们包装为生成式模型,计算3个loss:
adversarial_model = Model(inputs=[generator_input],
outputs=[discriminator_layers_for_generator,
rep_net_layers_for_generator,
cam_net_layers_for_generator])
而判别式模型就是discriminator网络。
训练时每个epoch对两个模型进行训练,先训练判别式,再训练生成式。
实验结果:
以上为对两篇论文的自己理解,如有问题还需分析指正