Two-Stream Convolutional Networks for Action Recognition in Videos
1.背景
在传统的基于深度学习的行为检测中,视频常常被看做连续的图片,使用处理图片的方式来处理视频。这样的网络关注于空间特征却忽略了时间特征,有些时间特征明显而空间特征不明显的动作(如坐椅子)难以检测出来。在手工设计特征的时代,人们使用光流图(optical flow)来描述物体的运动信息,但是光流图抛弃了物体本身的静态特征(比如形状、颜色)。本文通过训练两个卷积网络,通过时间流(输入为光流图)和空间流(输入为RGB图),将两个卷积网络的结果融合,最终达成任务要求。
光流是一种描述物体运动的矢量,光流组成的矢量图叫做光流图。可以理解为通过图片的明暗变化来判断物体运动的方向和速度。一般光流图会分解成水平分量的光流图和垂直分量的光流图,在卷积网络中可以看做是两个特征通道。光流分为密集光流和稀疏光流,稀疏光流是跟踪移动的物体上某个点做做光流,密集光流是计算图像上所有的点的光流。本文使用的是密集光流参与卷积。
(a)he(b)是相邻的两帧,(c)是(a)(b)青色框中的光流图,可以很清楚的看到手臂每个点的运动方向,(d)(e)是光流垂直分量和水平分量的图。
2.网络总体结构
网络上面是空间流,就是传统卷积网络处理视频的方法,因为是RGB图,有三个色彩通道,所以第一层输入通道数是3。下面是时间流,仅仅是吧RGB图换成了光流图,因为有两个分量,第一层输入通道数是2。最后一层是late fusion,将两个网络的输出通过某些方法融合起来,可以是使用softmax score average or a linear SVM。
3.实现细节
3.1 光流图处理
由于处理的是视频数据,光流图也需要一些处理变成“视频”,比较广泛使用的是光流堆叠(optical flow stacking),就是关注于一个固定的像素,每次计算光流都只着眼于目前相邻两帧的光流情况,而不关注之前的帧。作者提出了一种叫轨迹叠加(trajectory stacking)的方法,即从初始帧起,每次光流计算都要加上之前物体运动的轨迹,相当于对物体上的一个定点进行跟踪,我们把初始帧的每个像素都想象成一个存放数据的容器,虽然在之后的图像中物体可能不在这个像素上,但这个像素存放着初始帧时该物体这一个像素点的运动轨迹,但这种方法在之后的实验中证实效果并不好。
I
τ
(
u
,
v
,
2
k
−
1
)
=
d
τ
+
k
−
1
x
(
u
,
v
)
I
τ
(
u
,
v
,
2
k
)
=
d
τ
+
k
−
1
y
(
u
,
v
)
,
u
=
[
1
;
w
]
,
v
=
[
1
;
h
]
,
k
=
[
1
;
L
]
.
\begin{array}{l} I_{\tau}(u, v, 2 k-1)=d_{\tau+k-1}^{x}(u, v) \\ I_{\tau}(u, v, 2 k)=d_{\tau+k-1}^{y}(u, v), \quad u=[1 ; w], v=[1 ; h], k=[1 ; L] . \end{array}
Iτ(u,v,2k−1)=dτ+k−1x(u,v)Iτ(u,v,2k)=dτ+k−1y(u,v),u=[1;w],v=[1;h],k=[1;L].
光流堆叠的递推公式,
I
τ
I_\tau
Iτ表示任意一帧
d
x
d^x
dx和
d
y
d^y
dy表示水平和竖直分量,(
u
,
v
u,v
u,v)表示坐标,
w
,
h
w,h
w,h表示长宽,
L
L
L表示总帧数。
I
τ
(
u
,
v
,
2
k
−
1
)
=
d
τ
+
k
−
1
x
(
p
k
)
I
τ
(
u
,
v
,
2
k
)
=
d
τ
+
k
−
1
y
(
p
k
)
,
u
=
[
1
;
w
]
,
v
=
[
1
;
h
]
,
k
=
[
1
;
L
]
p
1
=
(
u
,
v
)
;
p
k
=
p
k
−
1
+
d
τ
+
k
−
2
(
p
k
−
1
)
,
k
>
1
\begin{array}{l} I_{\tau}(u, v, 2 k-1)=d_{\tau+k-1}^{x}\left(\mathbf{p}_{k}\right) \\ I_{\tau}(u, v, 2 k)=d_{\tau+k-1}^{y}\left(\mathbf{p}_{k}\right), \quad u=[1 ; w], v=[1 ; h], k=[1 ; L]\\ \mathbf{p}_{1}=(u, v) ; \quad \mathbf{p}_{k}=\mathbf{p}_{k-1}+\mathbf{d}_{\tau+k-2}\left(\mathbf{p}_{k-1}\right), k>1 \end{array}
Iτ(u,v,2k−1)=dτ+k−1x(pk)Iτ(u,v,2k)=dτ+k−1y(pk),u=[1;w],v=[1;h],k=[1;L]p1=(u,v);pk=pk−1+dτ+k−2(pk−1),k>1
p
k
p_k
pk是沿着轨迹的第k个点。
左图是光流堆叠,右图是轨迹叠加。
3.2 双向光流
上述讲的都是单向光流,即以某一帧为初始帧,计算后面的光流。双向光流是以当前帧为中间帧,光流场来源于前面几帧和后面几帧计算出的光流的叠加。
3.3 测试
测试阶段,等距抽取25帧(无论视频有多少帧),从每一帧中,通过裁剪和翻转四个角和帧的中心来获得10个卷积输入,相当于做了一次数据增广。然后,通过对采样帧和数据增广之后的数据的分数进行平均,可以获得整个视频的分类分数。
3.4 光流图压缩
由于光流图及其庞大,作者对光流图进行了压缩。现将光流图中的数据全都rescale到[0,255],然后转化成JEPG图,使用JEPG默认的压缩算法,这个方法对减少内存占用十分有效。
4 一些启示
- 视频数据十分容易做数据增广。
- 可以借助图片或视频的压缩算法来减少内存使用。
- 双向光流,或其他的双向数据训练,是很不错的trick,一般不会掉点。
- 在测试阶段有很多方法来测试,本文中一次使用了250帧(25*10)来进行测试,称为250 view。