Stacked Hourglass Networks - 堆叠沙漏网络结构详解

1.概述

姿态估计(pose estimation)在计算机视觉领域是一个非常重要的方向,人类动作理解,人机互动等等应用都需要精确的姿态识别。目前,绝大多数的2d姿态识别都是识别人体的关键点,比如,给定一张普通的RGB图像,算法会给出人体的脚踝,胳膊,面部等区域的关键点(keypoint)目前,基于stacked Hourglass Model的各种变种算法,牢牢占据了姿态检测的半壁江山,所以,非常有必要搞清楚stacked hourglass model

2.结构概览

2.1 CNN的多层次特征

CNN深度卷积网络如vgg16,resnet,近几年在推动人工智能的发展上,做出了巨大的贡献,原因就在于CNN可以自动提取对分类/检测/识别任务有帮助的特征,不再需要传统人工设计特征,如SIFT/HOG等。
CNN通常含有很深的网络层,每一层代表对图像的特征提取,被成为feature map.卷积网络对图像特征的提取,是随着网络的层数的加深,而从低层特征描述逐渐抽象为高层特征描述。这是什么意思呢,举个人脸识别的例子。
在这里插入图片描述
上图是一个人脸识别的CNN,layer1提取出低层次特征,如轮廓。layer2基于layer1提取更高层一些的语义特征,如眼睛,鼻子,嘴巴。顶层的layer3则提取和识别任务相关性最大的特征feature-map-3,如完整的人脸轮廓。然后将feature- map-3输入到一个分类器里(如SVM),给出识别结果。更详细的CNN解释可以参考这篇文章
注意下,这里只是简单的示例,实际的cnn要比上图更复杂,比如这三层的特征,正常情况下需要几十层更细致的特征来代替才能达到好的识别效果。

2.2 提出同时使用多层特征

stacked hourglass model(以下简写做SHM)的主要贡献在于利用多尺度特征来识别姿态。以前估计姿态的网络结构,大多只使用最后一层的卷积特征,这样会造成信息的丢失。事实上,对于姿态估计这种关联型任务,全身不同的关节点,并不是在相同的feature map上具有最好的识别精度。举例来说,胳膊可能在第3层的feature map上容易识别,而头部在第5层上更容易识别,见下图。所以,需要设计一种可以同时使用多个feature map的网络结构。

在这里插入图片描述

3.Stacked HourGlass 网络结构详解

在我刚开始接触SHM时,无论是原文还是其他博客,看起来云里雾里的,不是很明白具体的网络结构到底是什么样的,直到后面阅读源码才对细节一清二楚。这里吐槽一句,大部分paper,不给你源码,你绝无可能自己复现出来,甚至某些开放了源码的,都无法跑出文章给的结果!所以一切不给源码的paper都是在耍流氓。当然了,这里我会详细的叙述我对SHM网络结构的理解,然而还是建议你们去细细阅读源码(by tensorflow)

3.1 Hourglass Network

细心的读者可能注意到了,这里为什么少了个Stacked?因为堆叠沙漏网络是多个沙漏网络串联起来的,首先要明白单个的Hourglass Network如何工作的。串联的Stacked Hourglass相比单个网络主要是复用全身关节信息来提高单个关节的识别精度,后面会进一步解释。

在这里插入图片描述

上图就是原论文里给出的HourGlass Model,跟2.2节中的网络结构(c1-c7)相比,有两个显著不同:(1)右边就像左边的镜像一样,倒序的复制了一份(c4b-c1b),整体上看起来就是一个沙漏(2)上面也复制了一份(c4a-c1a),而且每个方块还通过加号与右边对应位置的方块合并。

我们来分析下c4b这个网络层,它是由c7和c4a合并来的,这里有两块操作:
(1)c7层通过上采样将分辨率扩大一倍,上采样相当于pool层的反操作,为了将feature map的分辨率扩大,比如c7的kernel size为 4x4 ,那么上采样后得到的kernel size 为 8x8 。
(2)c4a层与c4层的大小保持一致,可以看作是c4层的“副本”,它的kernel size 是c7的两倍,刚好与被上采样后的c7大小一致,可以直接将数值相加,那么就得到了c4b

用python伪代码写下来上述操作如下:

c7_up = up_sample(c7)   #   1x4x4x256 -> 1x8x8x256
c4_a = residual(c4)     #   1x8x8x256 -> 1x8x8x256     
                        #   c4_a相当于c4的副本,但是经过了一个residual处理
                        #   后面会解释这个操作,这里可以简单理解为复制了一份c4 
c4b = c4_a + c7_up      #   1x8x8x256

接下来就是c3b这个网络层,同样的,先对c4b进行上采样,然后与c3a合并,python伪代码如下:

c4_up = up_sample(c4_b)     #   1x8x8x256 -> 1x16x16x256
c3_a = residual(c3)         #   1x16x16x256 -> 1x32x32x256     
c3b = c3_a + c4_up          #   1x16x16x256

后面的层不再赘述。

这样将feature map层层叠加后,最后一个大的feature map - c1b 既保留了所有层的信息,又与输入原图大小,意味着可以通过1x1卷积生成代表关键点概率的heat map ,上图中并未画出该部分

3.2 Heat Map

大部分姿态检测的最后一步,是在feature map上对每个像素做概率预测,计算该像素是某个关节点的概率。

在这里插入图片描述

上图就是各个关节点的heat map,左边第一张为输入图像以及最终的预测关节点位置,第二张为对颈部节点的概率预测,红色和黄色代表着对应像素位置是颈部的概率很高,其他蓝色区域意味着这里几乎不会是颈部位置。

实际代码里,所有关节的预测是一起的,放在一个大的高维矩阵里,上图是为了演示才分开画的。

[ px1_of_c1b ]->[socre_of_neck,score_of_wrist,socre_of_knee,... ]
[ px2_of_c1b ]->[score_of_neck,score_of_wrist,score_of_knee,... ]

#   px1_of_c1b,px2_of_c1b 是特征层c1b上的两个像素
#   score_of_neck 是预测该点为颈部关键点的得分

3.3 关节点间的相互参考

3.1节给出的hourglass network 其实已经可以用来训练姿态估计了,但是为什么作者还要将沙漏网络串联呢?

关节点之间是可以互相参考预测的,即知道双肩的位置后,可以更好的预测肘部节点,给出腰部和脚踝位置,又可以用于预测膝盖。其他姿态估计文章有利用图模型(Graphic Model)来结合CNN做预测的,这个图模型就是对人体关节点的结构做抽象归纳。但是目前的图模型效果一般。

既然热力图代表了输入对象的所有关节点,那么热力图就包含了所有关节点的相互关系,可以看作是图模型。所以将第一个沙漏网络给出的热力图作为下一个沙漏网络的输入,就意味着第二个沙漏网络可以使用关节点件的相互关系,从而提升了关节点的预测精度。

在这里插入图片描述

如上图,N1代表第一个沙漏网络,提取出的混合特征经过1个1x1全卷积网络后,分成上下两个分支,上部分支继续经过1x1卷积后,进入下一个沙漏网络。下部分支先经过1x1卷积后,生成heat map,就是图中蓝色部分.

上图中蓝色方块比其他三个方块要窄一些,这是因为heat map矩阵的depth与训练数据里的节点数一致,比如 [1x64x64x16],其他几个则具有较高的depth,如 [1x64x64x256]

heat_map继续经过1x1卷积,将depth调整到与上部分支一致,如256,最后与上部分支合并,一起作为下一个沙漏网络的输入。

3.4 中间监督(Intermediate Supervision)

传统的识别或者检测网络,loss只比较最后的预测与ground truth之间的差异。因为堆叠沙漏网络的每一个子沙漏网络都会有heat map作为预测,所以将每个沙漏输出的heat map参与到loss中,实验证实,预测精确度要远远好于只考虑最后一个沙漏预测的loss,这种考虑网络中间部分的监督训练方式,就叫做中间监督(Intermediate Supervision)

展开阅读全文

没有更多推荐了,返回首页