Optical-Flow :Spynet

 

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层通过前一层上采样的光流场与目标光流场来计算残差,而是从上一层训练好的网络获得。
  • image_1dcg0to0g1e7917md1gr2chq19lc9.png-204.8kB
  • 训练数据集: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 网络结构

 
  1. ###Github:https://github.com/sniklaus/pytorch-spynet
  2. class Network(torch.nn.Module):
  3. def __init__(self):
  4. super(Network, self).__init__()
  5.  
  6. class Preprocess(torch.nn.Module):
  7. def __init__(self):
  8. super(Preprocess, self).__init__()
  9. # end
  10.  
  11. def forward(self, tensorInput):
  12. tensorBlue = (tensorInput[:, 0:1, :, :] - 0.406) / 0.225
  13. tensorGreen = (tensorInput[:, 1:2, :, :] - 0.456) / 0.224
  14. tensorRed = (tensorInput[:, 2:3, :, :] - 0.485) / 0.229
  15.  
  16. return torch.cat([ tensorRed, tensorGreen, tensorBlue ], 1)
  17. # end
  18. # end
  19.  
  20. class Basic(torch.nn.Module):
  21. def __init__(self, intLevel):
  22. super(Basic, self).__init__()
  23.  
  24. self.moduleBasic = torch.nn.Sequential(
  25. torch.nn.Conv2d(in_channels=8, out_channels=32, kernel_size=7, stride=1, padding=3),
  26. torch.nn.ReLU(inplace=False),
  27. torch.nn.Conv2d(in_channels=32, out_channels=64, kernel_size=7, stride=1, padding=3),
  28. torch.nn.ReLU(inplace=False),
  29. torch.nn.Conv2d(in_channels=64, out_channels=32, kernel_size=7, stride=1, padding=3),
  30. torch.nn.ReLU(inplace=False),
  31. torch.nn.Conv2d(in_channels=32, out_channels=16, kernel_size=7, stride=1, padding=3),
  32. torch.nn.ReLU(inplace=False),
  33. torch.nn.Conv2d(in_channels=16, out_channels=2, kernel_size=7, stride=1, padding=3)
  34. )
  35. # end
  36. def forward(self, tensorInput):
  37. return self.moduleBasic(tensorInput)
  38. # end
  39. # end
  40. self.modulePreprocess = Preprocess() ### 归一化处理
  41. # 构建{G0, …… , Gk}
  42. self.moduleBasic = torch.nn.ModuleList([ Basic(intLevel) for intLevel in range(6) ])

1.4 实验与分析

1.5 结论

2 代码分析

  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值