最近需要做视频分类相关的工作,在做技术调研过程中,了解到视频分类包含了两种形式,(1)通用的多标签视频分类,它的特点是标签为静态的,也即做分类时不需要考虑图像帧之间的关联性,因此跟基于图片的分类没什么差异了。(2)行为识别,因为是“行为”,所以这类任务需要考虑图像帧之间的关联性,比如“芭蕾舞”、“绘画”等,包含了3D卷积和Two-stream两种方法,在看了这方面的综述文章后发现是全新的方向。因为笔者之前一直做的2D目标检测方向,为了能更好地王行为识别方向过渡,选择先从2D的行为识别啃起,也即人体关键点检测,因此后面的几篇博文都是围绕关键点检测展开的。
说起人体关键点检测,就不得不提OpenPose算法了,它因为速度和精度的权衡在实际中得到了广泛的应用,它包含了人体骨骼关键点检测和脸部关键点检测。笔者在阅读它所使用的人体骨骼关键点检测算法后,有了对这个方向新的理解,故这里记录下来。
人体姿态估计可以分为两种思路,(1)“top-down”,它指先检测人体区域,再检测区域内的人体关键点。(2)“bottom-up”,它指先检测图片中所有的人体关键点,然后将这些关键点对应到不同的人物个体。这里需要提及一下,第一种方案因为需要对检测出的每个人体区域,分别做前向关键点检测,所以速度较慢,而OpenPose采用的则为第二种方案。
(1)未利用全局上下文先验信息,也即图片中其他人的身体关键点信息;
(2)将关键点对应到不同的人物个体,算法复杂度太高。
论文中提出了新的概念“Part Affinity Fields (PAFs)”,笔者将其翻译成关节联通区域。每个像素是2D的向量,用于表征位置和方向信息。基于检测出的关节点和关节联通区域,使用greedy inference算法,可以将这些关节点对应到不同人物个体。
整个的技术方案为“two-branch multi-stage CNN”,如下图,其中一个分支用于预测打分图 S S S,另外一个分支用于预测关节联通区域 L L L。
符号说明:
S = ( S 1 , S 2 , . . . , S J ) S=(S_{1}, S_{2}, ..., S_{J}) S=(S1,S2,...,SJ):score maps,其中 J J J表示关节点个数, S i ∈ R w × h S_{i}\in R^{w\times h} Si∈Rw×h用于表征第 i i i个关节点的score map;
L = ( L 1 , L 2 , . . . , L C ) L=(L_{1}, L_{2}, ..., L_{C}) L=(L1,L2,...,LC):part affinities,其中 C C C表示关节连通域(关节点对)的个数, L c ∈ R w × h × 2 L_{c}\in R^{w\times h\times 2} Lc∈Rw×h×2用于表征第c个关节联通域的联通情况,2D表征像素点的位置和方向,图像化表示如下,
其中,左图为"right elbow"和“right wrist”对应的关节联通域。右图为局部图像块放大后的表示;
论文中所提的多任务网络架构,能够同时预测detection confidence maps和affinity fields,前者用于表征每个像素点是否为关节点的置信度,后者用于表征关节点之间的关联性。
输入图像经过VGG-19的backbone网络,输出特征图 F F F,然后 F F F经过Branch 1和Branch 2,分别得到Stage 1对应的confidence map和affinity field。其中, ρ t 、 ϕ t \rho^{t}、\phi^{t} ρt、ϕt表示Stage t不同分支的推理CNN,公式表示如下,
然后,将Stage 1的输出 S 1 、 L 1 S^{1}、L^{1} S1、L1和 F F F做concate操作,作为Stage 2的输入,Stage 2负责对confidence map和affinity field做refinement操作,图像化表示如下,
关于两个分支的损失函数,作者均采用了 L 2 L_{2} L2 loss函数。而且,在每个Stage均进行监督,解决了“消失梯度”问题。另外,考虑到有些训练数据集只标注了图片中部分人物的关节点,因此对损失函数采用了空域加权操作,公式表示如下,
其中, S j ∗ S^{*}_{j} Sj∗表示groundtruth关节点置信度图, L c ∗ L^{*}_{c} Lc∗表示groundtruth关节连通域图, W W W表示二值化mask矩阵,当位置 p p p的标签缺失时其值为0,否则值为1。显然,对于未被标记的人物关节点, W ( p ) = 0 W(p)=0 W(p)=0,而被标记的人物关节点和非关节点, W ( p ) ̸ = 0 W(p)\not=0 W(p)̸=0,所以未被标记的人物关节点不会影响模型的学习过程,整个CNN网络架构的优化目标函数如下,
也即,综合考虑了所有Stage的关节点和联通区域检测。
论文中,使用2D高斯分布建模groundtruth关节点置信度图。记第 k k k个人的第 j j j个关节点的置信度图为 S j , k ∗ S^{*}_{j, k} Sj,k∗,第 k k k个人的第 j j j个关节点的groundtruth位置为 x j , k ∈ R 2 x_{j, k} \in R^{2} xj,k∈R2,那么 S j , k ∗ S^{*}_{j, k} Sj,k∗中位置 p ∈ R 2 p\in R^{2} p∈R2的像素值定义如下,
然后在channel维度做max pooling操作,得到Branch1网络的输出,公式如下,
所以,输出channels个数等于关节点个数,每一个feature map表示某一类关节点的confidence map。
在inference阶段,考虑到一张图片中不同人的相同关节点距离较大,作者对网络输出结果使用了non-maximum suppression操作,过滤掉距离较近的关节点。
上面3.2的内容给出了每类关节点的confidence map,那么问题来了,怎么把这些检测出来的关节点进行重组,得到不同的人体骨骼结构呢?
设想一下,如果我们知道了每一对关节点的相关性,也即每一对关节点是否属于同一个人,那么问题就解决了。
怎么知道每一对关节点是否属于同一个人呢?比较直接的方法是,检测人体所有骨骼的midpoint,比如手腕和肘部之间的midpoint,然后校验其它关节点,若某一对关节点位于midpoint两侧,则它们是一对,也即对应了同一个人。这种思路是有问题的,比如下图(b),红色和蓝色分别表示人体骨骼点,黄色表示midpoint,对于每一条黑线,满足这里的约束,然而对于绿线,是因为中间的黄点带来的歧义,所以这种方案不可行。
不可行的原因:(1)只对骨骼(limb)的位置编码,而忽略了方向信息;(2)只用了一个点表征骨骼区域,信息量不充分。
第二种解决办法,也即原论文中的最大创新,使用part affinity fields(PAF)建模骨骼区域,对于骨骼区域内的每一个像素,使用2D向量同时表征位置和方向信息,这里的方向指代当前骨骼对应的关节点对的连接方向。
以下图的骨骼区域为例,
其中, x j 1 , k x_{j_{1}, k} xj1,k和 x j 2 , k x_{j_{2}, k} xj2,k分别表示关节点 j 1 , j 2 j_{1}, j_{2} j1,j2的groundtruth位置。 k , c k, c k,c分别表示原始大图中的人物索引和关节点对索引,位置 p p p处的groundtruth关节联通域向量定义如下,
其中,
也即 v v v表示位置 j 1 j_{1} j1指向位置 j 2 j_{2} j2的单位向量。
点集 p p p定义成上图中绿色虚线内的区域,数学公式表示如下,
其中, 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表示骨骼长度, σ l \sigma_{l} σl衡量了骨骼的粗细。这里大家可以对照本文的第一张图来理解,就比较容易懂了。
然后,在channels维度做average pooling操作,得到Branch2网络的输出,用于表征不同关节点对的特征图,公式表达如下,
其中, n c ( p ) n_{c}(p) nc(p)表示所有人中位置 p p p处非0向量的个数。
(ps:为什么关节点定位使用max pooling操作,而骨骼定位却使用average pooling操作呢?欢迎大家留言讨论)。
在推理的时候,对于任意两个关节点位置 d j 1 d_{j_{1}} dj1和 d j 2 d_{j_{2}} dj2,通过计算PAF联通区域的线性积分来表征骨骼点对的相关性,也即表征了骨骼点对的置信度,公式表示如下,
其中, p ( u ) p(u) p(u)是对两个关节点位置 d j 1 d_{j_{1}} dj1和 d j 2 d_{j_{2}} dj2做插值操作得到的,公式如下,
因为计算机不支持积分运算,所以在实际运算过程中,将公式(10)分解成对 u u u的均匀采样,近似计算出这两个关节点之间的相关性。
由于图片中可能有多个人,或者算法预测的false positive点,导致每个关节点feature map中可能存在多个预测点的位置,使用公式(1)计算点对的置信度,只能保证局部最优,那么如何保证全局最优呢?这里的全局指人体整个骨骼结构。
在原论文中,作者采用了greedy relaxation的思想生成全局较优的搭配。
具体来说,引入如下数学符号,
(1) D J = { d j m : f o r j ∈ 1... J , m ∈ { 1 , . . . , N j } } D_{J}=\{d_{j}^{m}: for j \in {1... J}, m \in \{1, ..., N_{j}\}\} DJ={djm:forj∈1...J,m∈{1,...,Nj}},其中, N j N_{j} Nj表示关节点j对应的预测位置个数, d j m ∈ R 2 d_{j}^{m}\in R^{2} djm∈R2表示第j类关节点对应的第m个预测candidate, D J D_{J} DJ表示所有类关节点对应的所有预测candidate;
(2) z j 1 j 2 m n ∈ { 0 , 1 } z_{j_{1}j_{2}}^{mn}\in\{0, 1\} zj1j2mn∈{0,1}表示两个预测candidate d j 1 m 和 d j 2 n d_{j_{1}}^{m}和d_{j_{2}}^{n} dj1m和dj2n的连通状态;
因此,优化目标为:针对所有可能的连接, Z = { z j 1 j 2 m n : f o r j 1 , j 2 ∈ { 1... , J } , m ∈ { 1... , N j 1 } , n ∈ { 1... , N j 2 } } Z = \{z_{j_{1}j_{2}}^{mn}: for j_{1}, j_{2} \in \{1...,J\}, m\in \{1...,N_{j_{1}}\}, n\in \{1...,N_{j_{2}}\}\} Z={zj1j2mn:forj1,j2∈{1...,J},m∈{1...,Nj1},n∈{1...,Nj2}},寻找全局最优解。
比较简单的情况,先考虑一对关节点类型 j 1 j_{1} j1和 j 2 j_{2} j2,对应了第c个骨骼,那么寻找最优连接等价于求解加权二分图匹配最大化问题。
让笔者来更加形象地解释待优化的问题,网络结构中的Branch 1会输出多个feature map图,每一个feature map表示某一个关节点的所有预测candidates,因此包含了图片上所有人的该关节点预测结果。以肘部和手腕这两个feature map为例,这里要解决的问题就是,将同一个人的肘部和手腕位置构成一个match,如果这样的match越多,那么匹配成功的人数就越多,也就意味这对肘部和手腕连接情况的预测效果越好。
为了求解Graph匹配问题,这里以论文中插图5b为例,图中的node表示预测关节点 D j 1 D_{j_{1}} Dj1和 D j 2 D_{j_{2}} Dj2,edge表示预测关节点对的连通性,这里的连通性用公式(10)中的骨骼点对置信度来衡量,在公式(12)中用 E m n E_{mn} Emn表示。匹配最优化问题就转换成新的问题,即寻找edge子集合,且满足子集合中任意两条edge无共享node,公式表示如下,
其中, E c E_{c} Ec表征了关节点对(骨骼) c c c总的匹配置信度,这个优化问题可以使用Hungarian算法来求解。
(1)采用了coarse-to-fine的逐阶段思路;
(2)采用了“bottom-up”的思想,算法耗时跟图片中人物数量基本无关,速度快;
(3)开源软件OpenPose采用该方法定位人体,可以在服务器端做到实时,在工业场景中得到广泛应用。
https://arxiv.org/abs/1611.08050
https://github.com/CMU-Perceptual-Computing-Lab/openpose