论文:https://arxiv.org/pdf/1603.06937.pdf

代码:http://www-personal.umich.edu/~alnewell/pose

Stacked Hourglass Networks for Human Pose Estimation

Abstract

本文为人体姿态估计任务提出了一种新的卷积网络结构。所有尺度上的特征都被处理和整合,以最佳地捕捉与身体相关的各种空间关系。我们展示了重复的bottom-up、top-down处理如何与中间监督结合使用是提高网络性能的关键。我们将该体系结构称为“stacked hourglass”网络,它基于连续的池化和上采样步骤,这些步骤用于生成最终的一组预测。在FLIC和MPII基准上取得了最先进的结果,超过了所有最近的方法。

 

1 Introduction

在图像和视频中理解人的关键一步是准确的姿态估计。对于单一的RGB图像,我们希望确定人体重要关键点的精确像素位置。了解一个人的姿势和肢体的关节对于动作识别等高级任务很有用,在人机交互和动画等领域也被作为基本工具。

作为一个公认的视觉问题,姿态估计多年来以各种艰巨的挑战困扰着研究人员。一个好的姿态估计系统必须对遮挡和严重变形以及对罕见的和新奇的姿态有良好的鲁棒性,并且不受服装和灯光等因素引起的外观变化的影响。早期的工作利用鲁棒图像特征和复杂的结构预测[1-9]解决了这些困难:前者用于产生局部翻译,而后者用于推断全局一致的姿态。

然而,卷积神经网络(ConvNets)[10-14]极大地改变了这一传统管道。卷积神经网络是许多计算机视觉任务性能爆发式提升的主要驱动因素。最近的位姿估计系统[15-20]普遍采用ConvNets作为其主要组成部分,在很大程度上取代了手工特征和图形模型;这种策略在标准基准上产生了巨大的改进[1,21,22]。

我们继续沿着这条轨道前进,并引入了一种新颖的“stacked hourglass”网络设计,用于预测人体姿势。该网络在图像的各个尺度上捕获并整合信息。我们将这种设计称为houorglass,它基于用来获得网络最终输出的pooling和后续的上采样步骤的可视化。与许多产生像素级输出的卷积方法一样,houorglass网络池化到非常低的分辨率,然后在多个分辨率[15,23]上采样并组合特征。另一方面,houorglass与以前的设计主要不同的是其更对称的拓扑结构。

我们通过端到端连续地将多个houorglass模块放置在一起来扩展单个houorglass。这允许跨尺度的重复bottom-up、top-down的推断。与中间监督的使用相结合,重复的双向推断对网络的最终性能至关重要。最终的网络架构在两个标准姿态估计基准(FLIC[1]和MPII人体姿态[21])上取得了显著的改进。在MPII测试中,所有关节的平均精确度提高了2%以上,而对于更困难的关节,如膝盖和脚踝,则提高了4-5%。

 

2 Related Work

随着Toshev等[24]引入“DeepPose”,人体姿态估计的研究开始从经典方法[1-9]转向深度网络。Toshev等人使用他们的网络直接回归关节的x、y坐标。Tompson等人的工作是[15]生成热图,方法是将一幅图像并行地运行在多个分辨率库中,同时捕捉不同尺度的特征。我们的网络设计很大程度上基于他们的工作,探索如何捕获跨尺度的信息,并调整他们的方法来结合不同分辨率的特性。

Tompson等人[15]提出的方法的一个关键特征是卷积网络和图形模型的联合使用。他们的图形模型学习了典型的关节之间的空间关系。最近,其他一些人用类似的方法解决了这个问题[17,20,25],他们在如何实现一元分数生成和成对比较相邻关节方面做了一些变化。Chen等人[25]聚类检测到典型的方位,当他们的分类器进行预测时,可以获得额外的信息来指示相邻关节的可能位置。我们实现优越的性能,没有使用图形模型或任何显式的人体建模。

有几个用于位姿估计的连续预测方法的例子。Carreira等人[19]使用他们所说的 Iterative Error Feedback。输入中包含了一组预测,每一个通过网络的预测都会进一步改进这些预测。他们的方法需要多阶段的训练,每次迭代的权重都是共享的。Wei等人的[18]建立在多级位姿机[26]的工作上,但现在使用ConvNets进行特征提取。鉴于我们使用了中间监督,我们的工作在精神上与这些方法相似,但是我们的构建块(hourglass模块)是不同的。Hu & Ramanan[27]的架构与我们的更类似,也可用于多个阶段的预测,但他们的模型将权重限制在自底向上和自顶向下的计算部分以及跨迭代。

Tompson等人在[15]工作的基础上使用级联来完善预测。这有助于提高效率和减少他们的方法的内存使用,同时在高精度范围提高定位性能[16]。一个考虑是,对于许多失败的情况下,在一个局部窗口的位置细化不会提供很大的改善,因为错误的情况往往包括遮挡或错误归属的四肢。对于这两种情况,任何在局部尺度的进一步评估都不会改善预测。

姿态估计问题的变化包括使用额外的特征,如深度或运动线索。[28-30]还有一个更具有挑战性的任务,即多人同时进行标注[17,31]。此外,还有类似Oliveira等人[32]的工作,基于全卷积网络[23]进行人体部分分割。我们的工作主要集中在RGB图像中单个人姿态的关键点定位。

我们在堆叠(stacking)前的hourglass模块与全卷积网络[23]等在多尺度处理空间信息进行密集预测的设计紧密相连[15,33 - 41]。Xie等[33]对典型的架构进行了总结。我们的hourglass模块与这些设计的主要不同之处在于,它在bottom-up处理(从高分辨率到低分辨率)和top-down处理(从低分辨率到高分辨率)之间更对称地分配容量。例如,全卷积网络[23]和整体嵌套架构[33]都侧重于bottom-up的处理,而不重视top-down的处理,后者只包含跨多个尺度的预测合并(加权)。全卷积网络的训练也是分多个阶段进行的。

堆叠前的hourglass模块也与conv-deconv和encoder-decoder架构有关[42-45]。Noh等[42]使用conv-deconv架构进行语义分割,Rematas等[44]则使用它预测物体的反射率图。zhao等人[43]通过增加一个重构损失,开发了一个监督学习、非监督学习和半监督学习的统一框架。Yang等人的[46]采用了无skip connections的编解码器架构来生成图像。Rasmus等人[47]提出了一种用于无监督/半监督特征学习的去噪自动编码器,它具有特殊的“modulated”skip connections。这些网络的对称拓扑是相似的,但操作的性质是完全不同的,因为我们没有使用unpooling或deconv层。相反,我们依赖于简单的最近邻上行采样和skip connections进行top-down处理。我们工作的另一个主要区别是,我们通过叠加多个hourglass来执行重复的bottom-up、top-down的推断。

 

3 Network Architecture

3.1 Hourglass Design

hourglass的设计受到了从各个尺度获取信息的需要的启发。虽然局部证据对于识别面部和手部等特征至关重要,但最终的姿势评估需要对整个身体的一致理解。人的方向,他们四肢的排列,和邻近的关节的关系是图像不同尺寸的许多线索中最容易识别的线索。hourglass是一种简单、最小化的设计,它能够捕获所有这些特性,并将它们结合在一起输出像素级预测。

网络必须具有某种机制来有效地处理和整合跨尺度的特征。有些方法通过使用不同的管道来解决这个问题,这些管道在多种分辨率下独立处理图像,然后在网络中结合特征[15,18]。相反,我们选择使用带有skip层的单个管道来在每个分辨率下保存空间信息。网络的最低分辨率为4x4像素,允许使用更小的空间过滤器来比较图像的整个空间的特征。

hourglass的设置如下:Convolutional和max pooling层的结构用于将特征下降到低分辨率。在每个max pooling步骤中,网络分支(分为skip分支和接着下采样的分支)并在原来的pre-pooled分辨率上应用更多的卷积(这个即下采样分支)。在达到最低分辨率后,网络开始top-down的上采样序列和跨尺度的特征组合。为了将两个相邻分辨率的信息结合在一起,我们遵循Tompson等人[15]所描述的过程,对低分辨率进行最近邻的上采样,然后后面跟着一个像素级的两特征集求和(即同分辨率的skip分支求和)。hourglass的拓扑结构是对称的,所以每一向下层都有对应的一个向上层。

在达到网络的输出分辨率后,使用连续的两轮1x1卷积来产生最终的网络预测。网络的输出是一组热图,对于给定的热图,网络预测了每个像素点上一个关点存在的概率。完整的模块(不包括最后的1x1层)如图3所示。

位姿估计 - 1 - Stacked Hourglass Networks for Human Pose Estimation - 1 - 论文学习 

(很像U-Net网络)

 

3.2 Layer Implementation

在保持整体hourglass形状的同时,在具体的层实现中仍然有一些灵活性。不同的选择可能会对网络的最终性能和训练产生适度的影响。我们探索了在我们的网络层设计的几个选项。最近的研究显示了1x1卷积的简化步骤的价值,以及使用连续的较小过滤器来捕获更大的空间上下文的好处。例如,可以将一个5x5滤波器替换为两个单独的3x3滤波器。我们测试了我们的整体网络设计,基于这些见解在不同的层模块中进行交换。我们经历了一个网络性能的提升,从带有大过滤器和没有缩减步骤的标准卷积层切换到新的方法,如He等人[14]和基于“Inception”的设计[12]所提出的残差学习模块。在这些设计类型的最初性能改进之后,各种额外的探索和修改对进一步提高性能或训练时间没有什么帮助。

我们的最终设计充分利用了残差模块。大于3x3的过滤器不被使用,bottlenecking限制了每一层的参数总数,从而减少了总的内存使用。我们的网络中使用的模块如图4所示。为了将其置于完整网络设计的上下文中,图3中的每个框表示单个残差模块。

在256x256的全输入分辨率下运行需要大量的GPU内存,因此hourglass的最高分辨率(因此最终的输出分辨率)是64x64。这并不影响网络产生精确联合预测的能力。整个网络从一个stride=2的7x7卷积层开始,接着是一个残差模块和一轮max pooling,将分辨率从256降低到64。在图3所示的hourglass之前有两个接着的残差模块。整个hourglass的所有残差模块输出256个特征。

位姿估计 - 1 - Stacked Hourglass Networks for Human Pose Estimation - 1 - 论文学习

 (右边结构的代码实现是:

class PoseNet(nn.Module):
    def __init__(self, nstack, inp_dim=256, oup_dim=16, bn=False, increase=0, **kwargs):
        super(PoseNet, self).__init__()
        
        self.nstack = nstack
        self.pre = nn.Sequential(
            Conv(3, 64, 7, 2, bn=True, relu=True),
            Residual(64, 128),
            Pool(2, 2),
            Residual(128, 128),
            Residual(128, inp_dim)
        )
        
        self.hgs = nn.ModuleList( [
        nn.Sequential(
            Hourglass(4, inp_dim, bn, increase),
        ) for i in range(nstack)] )
        
        self.features = nn.ModuleList( [
        nn.Sequential(
            Residual(inp_dim, inp_dim),
            Conv(inp_dim, inp_dim, 1, bn=True, relu=True)
        ) for i in range(nstack)] )
        
        self.outs = nn.ModuleList( [Conv(inp_dim, oup_dim, 1, relu=False, bn=False) for i in range(nstack)] )
        self.merge_features = nn.ModuleList( [Merge(inp_dim, inp_dim) for i in range(nstack-1)] )
        self.merge_preds = nn.ModuleList( [Merge(oup_dim, inp_dim) for i in range(nstack-1)] )
        self.nstack = nstack
        self.heatmapLoss = HeatmapLoss()

    def forward(self, imgs):
        ## our posenet
        x = imgs.permute(0, 3, 1, 2) #x of size 1,3,inpdim,inpdim, [1,3,256,256]
        x = self.pre(x) ##size is [batch_size, inp_dim=256, 64, 64]
        combined_hm_preds = []
        for i in range(self.nstack):
            hg = self.hgs[i](x)
            feature = self.features[i](hg) #size is [batch_size, inp_dim=256, 64, 64]
            preds = self.outs[i](feature) ##size is [batch_size, oup_dim=16, 64, 64]
            combined_hm_preds.append(preds)
            if i < self.nstack - 1:
                # size is [batch_size, inp_dim=256, 64, 64]
                x = x + self.merge_preds[i](preds) + self.merge_features[i](feature)

        #把nstack个[batch_size, 16, 64, 64]合并成[batch_size, nstack, 16, 64, 64]
        return torch.stack(combined_hm_preds, 1) 
View Code

相关文章:

  • 2022-01-21
  • 2021-08-19
  • 2021-04-13
  • 2021-05-19
  • 2022-02-07
  • 2022-01-14
  • 2021-06-29
猜你喜欢
  • 2021-07-19
  • 2021-08-03
  • 2021-10-09
  • 2021-07-20
  • 2022-12-23
  • 2021-10-10
相关资源
相似解决方案