0 光流简介
1 光流模型SPyNet-Spatial-Pyramid-Network精读
1.1 摘要及简介
- SPyNet是通过将经典的空间金字塔方法与深度学习结合来计算光流的模型,与纯深度学习方法FlowNet计算光流方法不同的是,SPyNet不需要处理较大的motions,这些都是金字塔来处理,这样SPyNet有三个优势:
- 1、在模型参数方面,SPyNet更小更简单,仅为FlowNet的4%,更有利于嵌入式开发;
- 2、因为金字塔每层要处理的motions很小,对一组变形后的图片使用卷积的方法是有效的;
- 3、与FlowNet不同的是,SPyNet网络学习到的过滤器与经典的时空过滤器非常相似,这有助于模型的优化。
- 总之,SPyNet在标准的数据集上的准确率和速度都优于FlowNet,证明将经典的光流方法和深度学习结合是个很好的趋势。
- 目前,在光流计算方面存在两种比较主流的模型:
- 基于传统假设的‘经典公式’来计算光流;
- (1)相邻帧之间的亮度恒定;
- (2)相邻视频帧的取帧时间连续,或者,相邻帧之间物体的运动比较“微小”;
- (3)保持空间一致性;即,同一子图像的像素点具有相同的运动
- 缺点:根据如此假设计算出来的光流最多只能是粗糙的近似,严重限制了光流提取的质量
- 基于深度学习模型计算光流;
- 抛弃了所有的传统的假设,依旧是‘黑箱’操作,直接计算;
- 采用一对或一个序列的图片作为输入;
- 理想情况下,深度学习的模型应该学习到以下特征:
- 从图片到光流过程中一些恒定不变的特征;
- 光流的空间特征以及光流;
- 图片之间的空间结构特征的关系;
- ……
- 缺点:目前主流的深度学习模型,虽然不负所望,抛却了传统的假设后依然可以计算光流,但是其精度并不理想;
- 当前计算光流存在的最大的问题:
- 作者分析指出:目前的很多方法都是采用2帧图片堆叠的方法,当两帧图片之间的运动距离大于1(或几个)pixel的时候,卷积网络很难学习到有意义的过滤器。
- 本文的目标就是,结合两种方法的优势:
- 同时提升神经网络和经典方法的表现;
- 设计一个真正实时计算,且精度更高的模型;
- 更小的模型占有空间,在嵌入式开发方面更加的实用。
- 需要解决的问题及方法
- 远程相关性 - 本文:Spatial pyramid
- 计算光流时需要的细节、亚像素和精确的运动边界 - 本文:deeplearning
1.2 相关工作
- 略
1.3 SPyNet-Spatial-Pyramid-Network模型
1.3.1 空间采样
- 降采样downsampling:使用表示
- 假设原图为,那么的大小为
- 同样的过程同样会对光流场结果进行操作
- 上采样upsampling:使用表示
- 假设上采样之前图片大小为,那么的大小为
- 同样的过程同样会对光流场结果进行操作
- 图像扭曲warp:使用表示
- 将图片I根据光流场V,使用二线性插值的方法进行扭曲,得到一张的图片
1.3.2 推断
- 其中:,,表示一组训练好的卷积神经网络模型
- 表示第k层光流残差,由模型根据在k层的视频帧,及上一层的光流场上采样的结果进行计算;
- 表示扭曲的新图片,由上一层的光流场上采样结果,对k层的第二张图片进行扭曲;
- 表示第k层的光流场结果,通过上一层的光流场上采样结果和当前层光流残差相加后获得,即公式2;
- 具体流程如下:
- 从下采样好的图片,即金字塔的最顶层开始,初始化‘上一层’光流场残差为0,通过网络计算残差;
- 利用公式2计算网络层的光流场;
- 将计算的光流场结果传递给,并通过计算残差;
- 利用公式2计算网络层的光流场;
- 重复前面的操作,计算残差,并最终计算出光流场(网络仅有3层)。
1.3.3 训练与网络结构
- 对卷积网络,,的训练,采用的是独立且序列化的方式:通过给定的输入,在K层通过前一层上采样的光流场与目标光流场来计算残差,而是从上一层训练好的网络获得。
- 训练数据集:Flying Chairs dataset
- 训练了5个卷积网络,,
- 每个有5层卷积层,每层后(除了最后一层)接ReLU激活;
- 每层在不同的分辨率下训练,其中使用的是24*32的下采样图片进行训练;
- 下一层的图片尺寸都是上一层尺寸的倍数,其中训练的图片尺寸为384*512;
- 训练网络采用7*7的卷积核,实验验证其比小的卷积核效果更好;
- 每个卷积网络卷积核的个数为,,,,;
- 输入::8通道数据
- :RGB通道图片1
- : RGB通道warp图片2
- :两通道光流场上采样结果
- 输出:两通道的光流场(x方向,y方向)
- 网络初始化:训练网络时采用的参数作为初始化参数
1.3.4 数据增强
- 随机的改变图片的大小,缩放因子[1,2];
- 在[-17°, 17°]对图片进行随机的旋转;
- 进行随机的裁剪,裁剪到训练网络的尺寸;
- 随机的增加高斯噪声,;
- 随机的颜色抖动:
- 随机的对图片增加服从高斯分布的亮度、对比度和饱和度;
- 最后对图片进行归一化操作
- 采用从ImageNet数据集上获得的平均值和标准差。
1.3.5 网络结构
###Github:https://github.com/sniklaus/pytorch-spynet
class Network(torch.nn.Module):
def __init__(self):
super(Network, self).__init__()
class Preprocess(torch.nn.Module):
def __init__(self):
super(Preprocess, self).__init__()
# end
def forward(self, tensorInput):
tensorBlue = (tensorInput[:, 0:1, :, :] - 0.406) / 0.225
tensorGreen = (tensorInput[:, 1:2, :, :] - 0.456) / 0.224
tensorRed = (tensorInput[:, 2:3, :, :] - 0.485) / 0.229
return torch.cat([ tensorRed, tensorGreen, tensorBlue ], 1)
# end
# end
class Basic(torch.nn.Module):
def __init__(self, intLevel):
super(Basic, self).__init__()
self.moduleBasic = torch.nn.Sequential(
torch.nn.Conv2d(in_channels=8, out_channels=32, kernel_size=7, stride=1, padding=3),
torch.nn.ReLU(inplace=False),
torch.nn.Conv2d(in_channels=32, out_channels=64, kernel_size=7, stride=1, padding=3),
torch.nn.ReLU(inplace=False),
torch.nn.Conv2d(in_channels=64, out_channels=32, kernel_size=7, stride=1, padding=3),
torch.nn.ReLU(inplace=False),
torch.nn.Conv2d(in_channels=32, out_channels=16, kernel_size=7, stride=1, padding=3),
torch.nn.ReLU(inplace=False),
torch.nn.Conv2d(in_channels=16, out_channels=2, kernel_size=7, stride=1, padding=3)
)
# end
def forward(self, tensorInput):
return self.moduleBasic(tensorInput)
# end
# end
self.modulePreprocess = Preprocess() ### 归一化处理
# 构建{G0, …… , Gk}
self.moduleBasic = torch.nn.ModuleList([ Basic(intLevel) for intLevel in range(6) ])
1.4 实验与分析
- 略
1.5 结论
- 略