Hourglass Net是一个进行人体位姿估计的卷积神经网络(也可以用在人脸关键点检测等领域)。它结合了身体上的空间关系和多种尺寸上得到特征。作者采用了将多个Hourglass模块堆叠的方法,并且将中继监督运用进来,这些对于提高网络性能至关重要。这个方法在当时可以在FLIC数据集和MPII上达到state-of-art的效果。
准确的人体关键点对于理解视频和图片中的人物状态是至关重要的。Hourglass网络和通常的卷积方法一样,最终可以产生像素级别的结果(Hourglass的结果是N个关键点的heatmap图,)。每个hourglass 模块会pool down到一个非常小的尺寸,然后再上采样(上采样的同时加上pool down时相同尺寸的feature map)。
人体位姿估计主要有几个方法:
作者的网络建立在上述方法的基础上,探究了如何捕获多个尺度的信息,并且如何对不同的尺寸的特征进行整合。
对各种前人的网络介绍中,提及到Tompson et al. 使用级联(cascade)网络进行预测,并解释说级联网络的优点是减少内存使用的同时提高最终的效果。
整个网络的输入是256*256,首先做一个7*7的卷积,然后做了1个Bottleneck, 在做了1个max_pooling, 之后做了2个BottleNeck,此时的尺寸是64*64
作者在论文中说,将输入从256*256降低到64*64,这样做主要是因为256*256需要消耗大量的GPU资源。缩小尺寸没有影响网络的预测。
我认为,使用bottleneck模块相比直接用一堆卷积、池化操作的优点是:
hourglass的设计目的是捕获多个尺度的特征。因为最终位姿估计需要对整个人体进行理解,例如人的方向,胳膊腿的顺序等。而Hourglass是一个精简且设计优良的网络,它能捕获以上提及的特征,并且将它们结合起来产生最终的预测结果。
对于以上需求,很多方法使用多个pipeline独立的处理不同尺度的输入,并且最终将结果整合到一起。而作者的方法,只使用一个单独的pipeline,并且在同时使用skip layer避免每个尺度空间信息的损失。网路feature map最小达到4*4.
stacked hourglass model的主要贡献在于利用多尺度特征来识别姿态。以前估计姿态的网络结构,大多只使用最后一层的卷积特征,这样会造成信息的丢失。事实上,对于姿态估计这种关联型任务,全身不同的关节点,并不是在相同的feature map上具有最好的识别精度。举例来说,胳膊可能在第3层的feature map上容易识别,而头部在第5层上更容易识别,见下图。所以,需要设计一种可以同时使用多个feature map的网络结构。
对于具体的网路结构觉得有个博客写的挺好,下面引用一下,原文在参考里的1链接:
细心的读者可能注意到了,这里为什么少了个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 ,上图中并未画出该部分。
好了,继续自己写。
上面提到了上采样,https://blog.csdn.net/A_a_ron/article/details/79181108 详细介绍了unsampling, unpooling, deconvolution。
到达一个houglass module的结尾,应用一个1*1的卷积来产生最终的预测。预测结果是一系列headmap(比如人脸的关键点是68个,预测就是一个 68 ∗ 1 ∗ w ∗ h 68*1*w*h 68∗1∗w∗h的形状,每个heatmap代表对于每个点的概率预测)
同时,作者还在整个网络中加入了residual module,
Inception v2那篇论文曾经提到,可以将5*5的卷积转换成2个3*3的卷积,这样可以不对结果产生影响的同时,减少参数量。还有另外一点,“reduction steps with 1*1 convolution”,这个具体的操作就是在大的卷积核前面加上1*1的小卷积核, 这样操作首先可以减少计算量,因为1*1的卷积通常配有更小的filter,而且卷积后通常加Relu,这样可以增加非线性。
这篇文章的作者使用了相同的思路,将以上两点加入网络中,对最终结果有一定提升。
整个网络由多个Hourglass 模块堆叠而成。中继监督就是对每个Hourglass 模块的结果都计算损失。具体来说,每个Hourglass 模块都生成heatmap,根据groudtruth 计算损失;同时,我们对heapmap进行1*1的卷积,让其和Hourglass模块结果的channel相同,并将其加入进原本Houglass模块的输出。
Illustration of the intermediate supervision process. The network splits and produces a set
of heatmaps (outlined in blue) where a loss can be applied. A 1x1 convolution remaps
the heatmaps to match the number of channels of the intermediate features. These are
added together along with the features from the preceding hourglass.