【论文阅读】Depth-Aware Video Frame Interpolation

项目主页:https://sites.google.com/view/wenbobao/dain
项目Git:https://github.com/baowenbo/DAIN
论文地址:https://arxiv.org/pdf/1904.00830.pdf

简介

近年来基于深度学习的视频插帧成为了计算机视觉的研究方向之一,视频插值主要一般会用于一下几个方面:

  • 慢动作视频生成(slow-motion)
  • 视角合成(view synthesis)
  • 视频码率提升(frame rate up-conversion)

首先作者分析了近年来的深度学习网络在应对视频插值任务时所遇到的主要问题和瓶颈,主要有两点:

  • 无法处理大规模运动场景(large motions)
  • 只有隐式的(implicitly)或干脆没有处理遮挡区域填充问题(occlusions)

作者针对这两点进行了优化,并达到了目前state-of-art的效果。这篇文章是作者团队基于其在2018年发表的论文MEMC-Net做的改进,下面来研究研究作者都做了哪些工作。

算法流程

先来看下整个算法的流程图:
【论文阅读】Depth-Aware Video Frame Interpolation

可以看到用到了几个部分:光流、深度、上下文特征、插值kernel等等,下面来分别看下每个部分。

光流

作者在文章中提出了两种根据光流warp原图的方式:

  • 根据光流F01F_{0\rightarrow1}和时间tt计算出I0I_0ItI_t的光流F0tF_{0\rightarrow t}并正向warp输入图I0I_0,这种操作会造成遮挡区域的空洞问题,也就是前景移走了之后背景没有内容来填充,对于I1I_1同理。
  • 根据光流F01F_{0\rightarrow1}和时间tt计算出ItI_tI0I_0的光流Ft0F_{t\rightarrow0},也就是说,如果0时刻像素yy的光流F01(y)F_{0\rightarrow1}(y)tt时刻穿过像素xx,则Ft0(x)F_{t\rightarrow0}(x)可以近似为tF01(y)-tF_{0\rightarrow1}(y),同理Ft1(x)F_{t\rightarrow1}(x)可以近似为(1t)F10(y)-(1-t)F_{1\rightarrow0}(y)
    对于tt时刻的每一个像素点寻找其在图像I0I_0上的位置,也就是做反向warp,这种不会出现空洞问题,但是会引入一些新问题,后面会提到。

深度 x 光流

【论文阅读】Depth-Aware Video Frame Interpolation

如上图所示,在0时刻的像素y1y_1和像素y2y_2根据各自的光流运动,得知他们在tt时刻经过像素xx,那么像素xx的反向光流Ft0(x)F_{t\rightarrow0}(x)便可以由tF01(y1)-tF_{0\rightarrow1}(y_1)tF01(y2)-tF_{0\rightarrow1}(y_2)经过计算近似得出。
在过去的网络模型中,此时的光流融合大多是采用的是计算平均值的方式,也就是图中的绿色向量。但是这种计算方法无法处理遮挡区域的问题,例如如果前景像素和背景像素运动到同一个位置,合成出的结果应该是前景像素占更大比重

【论文阅读】Depth-Aware Video Frame Interpolation

由此作者提出了一种使用深度辅助来计算tt时刻的光流融合结果。融合的权重使用的是深度值的倒数,简单的来说就是深度值越大的像素(距离越远的像素),在光流合成的时候所占的权重越小

【论文阅读】Depth-Aware Video Frame Interpolation

作者同时提出,当没有任何光流向量在tt时刻经过像素xx时,则会在xx周围四连通邻域寻找有光流穿过的像素,并对它们求平均,得出xx位置的光流。

上下文特征

作者提出,在CtxSynNet论文中已经证明上下文信息(contextual feature)的加入对视频插值有一定帮助,这里的上下文信息我理解为浅层的、全局的图像特征,作者所举的例子是ResNet中经过第一个7x7 convolution layer之后的feature maps可以作为上下文特征。

插值kernel估计和自适应warping layer

这部分内容是在作者团队在2018年发表的MEMC-Net中首次提出。

【论文阅读】Depth-Aware Video Frame Interpolation【论文阅读】Depth-Aware Video Frame Interpolation【论文阅读】Depth-Aware Video Frame Interpolation

主要思想是通过光流找到像素xx的新位置后,将其新位置周围4x4范围内与一个特殊的kernel相乘后作为该点的像素值。这个kernel由两部分相乘得出,一部分是我们图像缩放时常用的双线性插值,其中每个位置的权重只与坐标距离有关,另一部分也是一个内插值kernel,是通过网络学习得出的。

模型实现

光流

使用光流的SOTA模型PWC-Net的预训练模型参数作为初始化,并开放梯度回传。

深度

使用单目深度模型MegaDepth的预训练模型参数作为初始化,并开放梯度回传。

上下文特征

作者在前文也提到了分类网络中的上下文信息,也就是ResNet中第一个7x7卷积网络之后的feature maps,但是作者同时又提出分类网络的feature不一定适用于视频插值任务,所以作者基于Residual block自己设计了一个提取上下文特征的网络,并从头开始训练。

【论文阅读】Depth-Aware Video Frame Interpolation

帧合成

将前文得出的warp后的原图,warp后的深度,warp后的上下文特征,tt时刻的反向光流,插值kernel传入最后网络,最后的网络由三个residual block组成。

训练细节

Loss函数

【论文阅读】Depth-Aware Video Frame Interpolation

作者使用Charbonnier Loss(一种L1 loss的变种,加了一个正则项),这个Loss是在LapSRN首次提出的,可以有效减少生成图的一些artifact。

数据集

  • 训练集 Vimeo-90k
  • 测试集 MiddleBury、UCF101、Vimeo-90k

训练策略

这里就不翻译了,直接贴截图。

【论文阅读】Depth-Aware Video Frame Interpolation

模型分析

在于其他网络结果对比之前,作者首先对自己的模型做了一些分析:

光流模块

【论文阅读】Depth-Aware Video Frame Interpolation【论文阅读】Depth-Aware Video Frame Interpolation

上图区分了四种不同的情况:

  • DA-None:不使用深度网络,直接用平均值计算tt时刻光流
  • DA-Scra:使用深度网络结构,不使用预训练参数,从零开始训练
  • DA-Pret:使用深度网络结构和参数,不做梯度回传
  • DA-Opti:使用深度网络结构和参数,并做梯度回传

很明显第四行也就是作者原文所说的结构是结果最好的,不过这里有比较大的疑问,比如第二行从零开始训练深度网络,在训练时并没有相关约束来告诉深度网络部分哪样变化是更好的,最终训练出来的是什么谁也说不清楚。

上下文特征模块

【论文阅读】Depth-Aware Video Frame Interpolation【论文阅读】Depth-Aware Video Frame Interpolation

同样也是区分了四种不同的情况

  • PCF:使用ResNet预训练模型的conv1后的feature maps,锁住梯度回传
  • LCF:使用ResNet预训练模型的conv1后的feature maps,并开放梯度回传
  • LHF:使用作者设计的上下文特征提取结构
  • D:使用深度信息单独作为上下文特征

这里从数据对比和效果图上看大都是作者提出的方法以占了微弱的优势,个人认为这部分没有很大的分析价值。

结果对比

【论文阅读】Depth-Aware Video Frame Interpolation【论文阅读】Depth-Aware Video Frame Interpolation【论文阅读】Depth-Aware Video Frame Interpolation

放两张在不同数据集上与近年论文的优劣,这里不做过多分析。

算法瓶颈

【论文阅读】Depth-Aware Video Frame Interpolation

最后作者提出了这个网络结构的瓶颈,其实也就是计算光流是比较依赖的深度图精度。当深度图精度出现问题时,光流也会出现问题,会导致合成的结果有一定模糊,边缘不够锐利。

总结和贡献

  • 提出了一种depth-aware视频插帧方案,尝试显式的解决遮挡区域的问题。
  • 借用PWC光流coarse-to-fine的思路,尝试解决large motions的问题。
  • 使用LHF和深度作为上下文信息,更好的合成中间帧。

一些疑问

  • 为什么对预训练模型开放了梯度回传之后,深度估计模型可以学到更多东西?
  • interpolation kernels理论上应该是用来和光流图配合来warp输入图时候用到的,为什么要传入最后的frame synthesis网络中?
  • 4x4双线性插值的kernel具体是怎么计算的?

20191024更新:

看了一下作者的supplementary资料,没有解释单目深度模型从头开始训练时学到的是什么,也没有解释是如何在训练过程中学到更多内容的,毕竟没有直接的loss来约束,只是做了梯度回传而已。
另外作者开源的代码,应该是传了一个简易版本到github上面,很多文章中提到的部分没有做实现,例如Interpolation kernel部分,直接使用双线性插值代替,于是也就没有传入最后的frame synthesis网络中。双线性kernel的计算方式与文章中提到的相同,和我们日常用的双线性插值没有太大区别。