使用深度学习做深度估计最经典的两篇文章应该属于Eigen组2014,2015年的两篇工作:
Depth Map Prediction from a Single Image using a Multi-Scale Deep Network (2014 NIPS)
Predicting Depth, Surface Normals and Semantic Labels with a Common Multi-Scale Convolutional Architecture (ICCV 2015)
在NIPS2014的文章中, 如下图所示,作者提出了一个Multi-Scale的深度神经网络用来解决深度预测的问题.Coarse 网络是一个经典的AlexNet(NIPS 2012)结构,除了最后一层从1000个分类器换做了一个coarse的depth map,因为当时Fully Convolutional Networks还没有出来,主流的做法都是从分类的全连接层恢复图片. 在Fine网络中,作者先采用大步长的卷积核将图片的大小变小之后的卷积核并没有再去降低特征的大小,而是采用了步长为1,大小为5的卷积核去进行特征提取并结合之前Coarse网络的结果得到最终预测的结果.在训练的时候,此网络先训练Coarse网络然后再固定Coarse网络的训练参数再去训练Fine网络.
在目标函数方面,作者采用了一个Scale-Invariant Error:
这里y是真实的深度,y*是合成的深度,i,j分别为深度图中的某一对像素点.
说几个非常有意思的点:
在ICCV2015的这篇工作中,作者将上述工作进行了拓展.
除了在scale1上将AlexNet换成了更深的VGG16,增加了multi-scale的数目,还有就是在网络设计方面抛弃了之前保持fine层不变的思路,在这篇文章中,scale2和scale3的网络都是有pooling layer和upsampling参与的,并没有具体的实验指出上种做法和这种做法的好坏,我更倾向于上一种思路,在这篇文章中我觉得是由于GPU内存的妥协.同时这篇文章也从单一预测深度变成了从单张图片预测深度,法线和label.因为深度信息和法线都属于三维特征,而深度也是和图片的语义分割信息具有很强的相关性.所以在文章中也提到了,预测深度的网络和预测法向量的网络共同使用了一个scale1来加速训练.
Fully Convolutional Networks (FCN)就不用我瞎比吹了,这篇文章2015CVPR, 至今2000+的引用量就说明了一切.还是来总结一下这篇文章的贡献点把.区别于以往pretrained的网络采用固定的全连接层大小来得到image-to-image的转换.这篇文章直接把全连接层去掉了,取而代之的是一个和pretrain网络结构的网络用来将high-level的特征返回到和原图一样的大小.整个网络可以看做是一个encoder-decoder的过程.这样做呢有两个好处,第一个是全连接层几乎拥有整个网络的90%以上的参数,去掉全连接层可以更好的利用GPU. 其次全连接层固定了网络输入输出的大小,只有固定大小的图片才能够被处理.而FCN就可以直接处理几乎所有的图片大小.几乎所有的意思在于,在大多数情况下,stride>1卷积核会改变图片的大小,FCN在输出得到的大小会与原图特征大小不相同.这样也会影响网络的处理结果.
在此基础上,Deeper Depth Prediction with Fully Convolutional Residual Networks(FCRN)这篇文章尝试了更深层次的网络带来的好处:
在上图中,前两行是一个pretrained的ResNet50结构,最后一行为一系列类似于逆卷积的结构,目的是为了让输出图达到与输入内容相差不大的结果.这篇文章最让我感到惊叹的是pretrain的网络结构带来优势真的很大,如下表中,从AlexNet到VGG再到ResNet,效果几乎提升了一倍:
前些日子在这个架构上尝试了DenseNet,得到了更好的结果,所以说pretrained的网络真是的居家旅行必备良品.这篇文章的其他贡献点如同鸡肋就不赘述了.总结就是:pretrained大法好!
虽说数据上的情况如上,但是我们再来看看视觉上的感受,从上图可以看到,VGG16预测得到的深度图有更清晰的轮廓并且细节比较丰富,而ResNet50由于网络比较深,得到的结果比较smooth.这也和网络的结构有关.下图分别为VGG16和ResNet50的网络结构,可以看到VGG16在初始阶段并没有减少特征的大小,而ResNet50在刚开始就进行了stripe为2的卷积,紧跟了一个maxpool.所以以输入为224计算,VGG16会在完整图片上采集更多的信息,而ResNet50虽然在刚开始使用了一个大的卷积核但是特征方面的处理大多数都是在224/4这个特征大小上进行卷积的.
再来对比一下FCRN和Eigen的文章,以下截图接上一个对比:
proposed为FCRN的方法,右图为eigen的方法,可见,虽然FCRN在整体的深度预测上表现的更好(使用了更深的ResNet50网络),而Eigen的细节要丰富一点(使用了VGG16),而且轮廓要更锋利一点.
所以就留下了一个疑问,如何在保留细节的基础上得到更好的整体效果呢?这个其实在语义分割问题上已经有了很多解决方法,比如基于图论的条件随机场Conditional Random Fields as Recurrent Neural Networks(CRFasRNN 2015 ICCV), 基于全尺寸网络的Full-Resolution Residual Networks for Semantic Segmentation in Street Scenes(FRRN 2017 CVPR).
A Two-Streamed Network for Estimating Fine-Scaled Depth Maps from Single RGB Images https://arxiv.org/pdf/1607.00730.pdf
算法框图如下:
深度与深度梯度各自均进行同样操作,深度梯度可以获取深度细节。这两个分支有着同样的形式,一个是图像解析块,接着是特征融合块最后是修正块。
图像解析块是由VGG和两个全连接网络构成。第二个全连接层的输出reshaped成55×75×D的特征块。接着传入特征融合层。D=1的时候是深度分支,D为2时为梯度分支。其他的预训练网络也可以代替此处的VGG-16,比如说VGG-19和ResNet。(此处的D看似这么方便表示,但是caffe实现的时候必须还得分成两个部分,因为即使是3D卷积也没法满足这样的功能,它需要的是多特征之间乘积相加而做不到完全的独立)
对于特征融合块,是先由一个9×9卷积和池化层,后面接着八个连续的5×5卷积,无池化构成。它的输入有三个:1,图像原图,2,VGG输出,3,图像解析输出。
该层有很多的skip connection,VGG的pool3特征在第二个卷积fused,VGG的pool4的特征在第四个卷积fused,图像解析层的输出在第六个卷积层fused。skip connection 可以共享阶段性的信息,可以发现这个网络训练起来更加容易收敛。
修正块,与特征融合块是类似的,由一个9×9卷积池化和五个5×5不带池化的卷积层构成。输入是:1,图像RGB输入。2,特征融合块的双线性上采样输出,3,以及与第三个卷积层的skip connection。这个块的工作映射尺寸大小是111×150.
再后面的深度和梯度混合块将两个不同的分支变成一个单独融合的深度估计。我们提出两种操作可能性,一个是一个端到端网络,还有一个是通过数值优化。+
loss:针对图像进行数据增强后与对应深度图的L2loss(相同的数据生成的train data之间的相关性,其恢复得到的深度要尽可能接近,因此构建了基于set of transformed images的loss的约束)
梯度loss
融合loss
结果:
利用了深度信息的基本特征:图片中的点与点之间的是有相对远近关系的。NIPS2016这篇文章自己构建了一个相对深度的数据库,每张图片之中仅仅标注两个随机点之间的相对远近关系,通过一个神经网络的训练就能得到原图之中的相对深度信息。而且,一般的方法通常是针对某个数据库的数据范围的(NYUv2用来做室内深度预测,深度的ground truth 是 0~10m,KITTI用来处理行车道路信息,深度的ground truth 是 0~70m),这篇文章的深度是没有这种限制的。 但是缺点也很明显,由于是相对深度信息仅仅得到的数据表示了当前图片中物体的远近关系和真实深度信息有很大的区别。Single-Image Depth Perception in the Wild (NIPS2016)。测试结果发现深度图并不理想。
以上这类方法有一个缺点就是在训练的过程中,我们需要预先知道大量的输入的图片所对应深度值的参考标准作为训练的约束,从而对神经网络进行反向传播,训练出我们的神经网络用来对于相似的场景进行深度预测。这类方法也就是常说的“监督学习”。但是现实情况下,求取场景所对应的深度值并不是一件容易的事。目前比较常用的方法是从kinect的红外传感器中得到深度(NYU Depth V2)或者借助于激光雷达(KITTI),kinect虽然比较廉价,但是所采集到的深度范围(超过4m kinect估计的深度的精度就会下降)和精度都有限。而激光雷达的成本就比较高了。那有没有一种方法能够在训练的时候不需要在已知深度的情况下得到一个估计深度的神经网络呢?本节中我们介绍几种通过非监督学习的方法进行单目深度估计的例子。
自然界的大多物种都是和人一样,需要两只眼睛来做三维空间定位。那为什么需要两只眼睛呢?
因为一只眼睛看到的图像是二维的,二维的信息是无法用来表示三维的空间的,如上图所示,虽然处于同一水平面上的照相机L,R拍摄了同一个物体,两者之间产生的图片是不同的。并且这种不同是不能通过平移生成的图片所消除的。离照相机近的物体偏离的位置比较大,离照相机远的物体偏离的比较少。这种差异性的存在就是三维空间带来的。(这部分请参考双眼可以测距和建立立体环境,双摄像头可以吗?)。同时同一水平线上的两个照相机拍摄到的照片是服从以下物理规律的:
在图中, 为场景所距离我们的深度, 为三维场景映射到的二维图像平面,也就是最终我们得到的二维图像所在的平面。 为相机的焦距。 为两个相机之间的距离, 和 分别为相同物体在左右两个不同相机中成像的坐标。根据以上信息,和简单的三角形相似规律我们可以得到:
这里 就是我们常说的视差 (disparity), 代表了 这个点在照相机 和照相机 中成像的偏离值。也就是说这个值代表了左照相机中的像素需要通过平移 才能形成右照相机中相应的像素。所以两个视角之间的关系可以写作:
假设我们有一个很强大的函数 ,没错这个函数就是神经网络,使得 ,那么就有:
只要我们以 作为训练的输入, 作为所对应的参考标准,建立如上关系的神经网络 ,通过大量的双目图片对的训练,得到的神经网络 就是一个 输入一张图片 来预测所对应的视差 的函数,这样就将一个没有约束的问题变成了符合如上规律的问题,就可以采用常规思路进行求解了。同时视差 在已知照相机参数 的情况下,就能求取相对应的深度 。
总结以上规律我们得到:因为单目求深度需要昂贵的激光雷达,但是两个同一水平线上的两个照相机所拍摄的照片却相对容易得到。只要我们通过单张输入图片求取相对应的disparity ,同时在得知照相机参数( )的情况下也就能求得所对应的深度 。
这种思路最先应用于使用单张图片生成新视角问题:DeepStereo 和 Deep3d之中, 在传统的视角生成问题之中,首先会利用两张图(或多张)求取图片之间的视差d,其次通过得到的视差(相当于三维场景)来生成新视角。深度学习在这方面也有很多漂亮的工作,这个新坑以后再填。
在之前我们将单目深度估计问题写成了一个简单的函数:
通过本篇文章第一节的内容,这个函数可以进化成如下形式:
其中 为所预测的深度, 为固定相机下的视差, 为相机两个镜头之间的距离, 为焦距。
那我们知道, 这种关系可以轻而易举的使用CNN模拟出来,而(3)中的关系就有一个问题,我们预测到的d是连续的浮点数,如果使用 的套路,那么很有可能会落入到不在(整数)像素点的位置,同时由于不同位置 不同,也有可能有一个 中的像素点 接受多个来自 的像素点颜色,因为它们都满足 。而也有一些点并没有相符合的 ,因为这些点由于视差的原因在原图中可能根本不可见。为了解决这个问题,一般采用backward(reverse) mapping的方法,如下图所示:
这两种方法的区别在于,在forward mapping中,我们得到 中的点可能会落在不是整数像素点的位置,这时只能通过最近原则将原图 中的像素点对应到 中去,而在Inverse mapping中,我们从 出发(也就是 ),去寻找相对应的原图中的点,这样能够确保 中的每一个点都有赋值不会出现空洞,并且如果 得到的原图中的点不属于(整数)像素点,这时可以通过插值的方法求得所对应非像素点的位置。一般在这里采用双线性插值的方法,而且它在sub-pixel level是可导的[Spatial Transformer Networks]。所以我们就可以end-to-end的来训练网络啦。
所以在训练的时候我们的网络分为了以下步奏:
而所对应的损失函数为:
至此,正向传播过程通过 来得到所对应的视差 ,mapping过程将右图转换成左图,损失函数计算当前的准确度并且进入优化过程,反向传播过程如下式所述:
上式中, 为 中需要优化的神经网络的参数, 由损失函数得到, 由mapping方法提供, 由神经网络自己back-propagation得到。测试过程只需要将 传入神经网络 就能得到所对应的视差,结合相机参数,就能求得深度。大功告成!接下来看看各路神仙都是怎么用这个思路来做深度预测的吧!
Unsupervised CNN for Single View Depth Estimation: Geometry to the Rescue(ECCV 2016)
这篇文章所采用的方法和我上述描述稍有不同,我所采用的是:
而文章中所采用的是:
第一个不同在于mapping方程的求导方法上,在这篇文章中为了求得mapping相对于d的导数,使用泰勒展开式来得到。相当于一个numeric的求导过程:
而我们上一节中介绍的方法是通过线性插值来求导,更快,准确度更高。
第二个不同就是它通过 来map回 ,同时约束了输入图 与生成的输入图 之间的关系。但是不要小看这个区别,我的方法所预测的disparity描述了 经过 生成 的过程,而文章中预测到的disparity描述了 通过 生成 的过程。根据本文之前讨论的,输入图片的内容中由于不同视角物体的遮挡关系,原图 所表现出来的像素点位置可能在新视角 中并不存在。所以我预测到的 是 所对应的深度,而文章中预测到的则是 所对应的深度,虽然这两者在大部分的像素点的深度范围都相同,但也就是这样的细节告诉了我们,为什么人家的方法能够发ECCV而我只能发知乎专栏都是有原因的。
在网络方面,这篇文章采用了一个类似FCN的结构,没有全连接层的参与,体量小速度快。同时skip-connect的参与保证了输出特征细节的相对完整性,再其次就是可以使用pre-trained的网络结构作为encoder部分,在数据不足的情况下也能达到相对好的效果。
在刚才的文章中,我们介绍了Naive的方法来求解深度,同时也指出了我介绍的方法的不足,但是有没有方法能够结合这两种估计深度的方法得到更多的约束呢?接下来我们就来介绍一种robust,multi-level,multi-loss的方法用来做非监督的深度估计。
Unsupervised Monocular Depth Estimation with Left-Right Consistency(2017 CVPR)
这篇文章方法上的贡献点可以参考上图,naive可以说是ECCV 2016的方法,No LR是本文之前介绍的方法,这篇文章相当于结合了这两个方法得到的结果。通过 进入神经网络可以求得 和 , 通过输入不同的参考图片在mapping中可以得到相对应的原图 和右图 。所以ECCV2016的损失函数仅仅是 ,而这一篇文章可以加的约束就多很多了:
如上图所示,第一对 表示了图片重建的损失函数,在这里,作者采用了一个SSIM和L2相结合的损失函数,因为L2并不能很好的表示真实的图片分布(相关讨论可以看损失函数的讨论和SRGAN):
其次,理想状况下, 和 之间也存在着与原图相同的视差关系,也就是说:
所以,当预测的深度达到最优时,以下损失函数达到最小值,同理,交换 和 的位置所得等式依旧成立,这一项也就是本节文章题目中所说得到的left-right Consistency:
关于损失函数中的 部分,作者提出了一个edge preserving的损失函数,主要的意图是因为depth的不连续性往往发生在边缘附近。提出了这个损失函数用来保证所得到的深度图的光滑性与图像梯度一致。
说完了损失函数再来说说网络:
这篇文章所使用的网络和之前的方法类似,均采用了FCN的方法进行训练,不同的是在decoder部分的最外面4层,作者都估计了当前特征大小所对应的视差的值,并且将它上采样后传递给了decoder的下层,这样能确保每一层都在做提取disparity这件事,同时也相当于做了一个coarse-to-fine的深度预测,同时由于我们采用了双线性差值,梯度的范围始终来自于周围的4个坐标点,coarse-to-fine的预测能够让梯度来自于离当前位置更远的坐标点,6中也讨论了这个问题。
对于一个robust的系统来说 ,这篇文章可以说是典范了。各种novel的损失函数,multi-level的结果,solid的实验结果,加上简单有效的贡献点。五星推荐。所以这篇文章出来之后,就有人想,能不能结合有监督学习和无监督学习来共同进行深度预测?
Semi-Supervised Deep Learning for Monocular Depth Map Prediction(2017 CVPR)
理解了上一篇就知道作者为什么要来写这一篇了。既然无监督学习深度能够取得好的效果,那么我们将传感器得到的稀疏的深度作为参考标准,和4中提到的完全非监督的方法共同去估计深度应该也会有好的效果。所以这篇文章的贡献点主要集中在损失函数部分,既有监督学习得到的loss(稀疏深度和预测到的深度的差值),又有非监督学习得到的loss(生成的新视角图片之间的差值),还有深度域上的正则项(depth梯度的正则)。结合以上一起用来训练。这篇文章的对比实验部分很详细,感觉可以挖掘出很多信息。
如图所示,[9]为我们之前在4中介绍过的"Unsupervised Monocular Depth Estimation with Left-Right Consistency”,[6]为我们在3中介绍过的"Unsupervised CNN for Single View Depth Estimation: Geometry to the Rescue",可以看到当前的方法仅仅采用非监督学习的方法是要差于[9]的,因为[9]中用了multi-scale的深度估计,left-right consistency的损失项等等。
同理我们再来比较一下每一个贡献点之间方法关系:
效果提升最明显有以下几个部分:1. 非监督学习和监督学习相结合,更多的监督数据得到更好的效果。2. skip-connection。 3. Gaussian smoothing 也就是文章所说的正则项。第一个可以说是它这篇文章的主要贡献点,第二个则是一个非常general的方法。第三个算是一个很小的贡献点(这种smooth在上篇文章中也有用到)。所以这篇文章的自身的贡献点还是集中于非监督学习和监督学习的结合。
所以这篇文章(CVPR Spotlight)是没有上一篇文章(CVPR oral)好的。
Unsupervised Learning of Depth and Ego-Motion from Video(CVPR 2017)
这篇文章的方法可以说是继承与ECCV2016这篇文章。在之前的文章中我们介绍到,在已知相机参数的情况下,我们可以通过视差 来得到相对应的深度 。那如果相机不在同一个平面并且参数我们也不知道呢?
如下图所示,先将 输入到Depth CNN 中用来预测深度 ,其次将 输入到pose CNN中来预测得到的照相机参数,所以就有 和 。这里G代表了depthCNN, F代表poseCNN, 通过深度 和照相机的参数 和两者之间的关系V,能够算出在t-1时刻或者t+1时刻所得到的重建图 ,以视角合成问题作为监督学习,所预测到的深度depth 和照相机的pose都是通过非监督学习过程得到的。网络方面这篇文章还是采用了FCN的结构(看来FCN这种结构已经制霸image-to-image translation领域了)
同时这篇文章的损失函数是很有意思的,这一系列视频帧中其实只是有一部分出现在了最后重建的结果之中,那么就需要对于每一帧有一个mask能够让我们挑选出出现在最终结果之中的部分,也就是这里的 用来过滤没有用的信息。我们知道,如果非监督学习来做这个问题我们拿到的数据就只有视频帧,是没有mask的参考标准的,如果我们通过如下损失函数去进行预测,那么当E中所有的值为0时,损失函数达到最小。但是这并不是我们想要的。所以这里作者使用了一个约束,用来得到E:假设mask所有的值都为1,然后使得像素值均为1的mask和 之间的交叉熵(cross-entropy loss)尽可能小(意味着两者更相似)。这也就意味着,我们需要得到一个尽可能大的mask,并且这个mask能够让重建的损失函数达到最小!
个人觉得是很聪明的做法,所以整个损失函数就变成了,其中smooth为预测的深度图的正则项:
还有就是因为这篇文章中的算法是纯非监督学习的(甚至是照相机的参数),所以预测得到的深度相比前两篇CVPR的文章稍差一点。不过我觉得方法和适用性可以说是这三者里最好的一个了。
这篇文章和SfM-Learner都是出自Google。论文的核心思想也是利用photometric constancy来计算pose,depth。除此之外,作者还计算了光流,scene flow,3D point cloud等。可以说是SfM-Learner的升级版。
图7. SfM-Net 网络结构
论文:Sudheendra Vijayanarasimhan, Susanna Ricco, Cordelia Schmid, Rahul Sukthankar, Katerina Fragkiadaki, “SfM-Net: Learning of Structure and Motion from Video”, Learning of Structure and Motion from Video
代码:还没有
另外一篇和SfM-Net,SfM-Learner比较相似的文章:DeMoN,使用pose, depth作为监督信息,来估计pose和depth。最后的效果非常不错。网络的核心部分如图所示
图8. DeMoN网络核心结构
论文:Benjamin Ummenhofer, Huizhong Zhou, Jonas Uhrig, Nikolaus Mayer, Eddy Ilg, Alexey Dosovitskiy, Thomas Brox, "DeMoN: Depth and Motion Network for Learning Monocular Stereo", in CVPR 2017,https://arxiv.org/abs/1612.02401
代码:lmb-freiburg/demon
2.9 Single View Stereo Matching
方法分两部:利用左图合成右图及利用左图和生成的右图进行视差图的合成。训练时需要有左右双目图及深度图。
CNN-SLAM。该文章使用直接法估计相机姿态,使用CNN来估计Depth,以及做图像语义分割。然后将Geometry和semantic融合起来,生成具有语义信息的map。
图9. CNN-SLAM pipeline
论文:Keisuke Tateno, Federico Tombari, Iro Laina, Nassir Navab, "CNN-SLAM: Real-time dense monocular SLAM with learned depth prediction", in CVPR 2017, https://arxiv.org/abs/1704.03489
CRF之前一直在语义分割问题上表现的很好,包括CRFasRNN,DeepLab等等,几乎成为了这种回归问题的标配。这一类的方法采用CRF是因为通常CNN用来做回归时产生的图都比较糊(blur), CRF可以通过条件概率建模的方法将糊的图片变得不糊。这是一种纯数学解决问题的方法,与深度信息本身的物理性质关系不大。
Deep Convolutional Neural Fields for Depth Estimation from a Single Image(2015 CVPR)
Depth and surface normal estimation from monocular images using regression on deep features and hierarchical CRFs(2015 CVPR)
Multi-Scale Continuous CRFs as Sequential Deep Networks for Monocular Depth Estimation (2017 CVPR)
xiaogang wang他们的成果,这篇主要是CNN和Graphical Model的结合。
主要的motivation:
1.在CNN解决pixel级的classification/regression问题时,引入multi-scale的信息可以更好的结合low-level和high-level的feature。
2.在semantic segmentation问题中,CRFasRNN中将CRF的mean-field解法展开用RNN网络的结构实现,使得CNN+CRF可以进行end-to-end的优化,这是针对discrete domain的问题,而对于continuous domain的regression问题,还没有这样翻译成网络的CRF层的存在。
3.以及图模型有很好的表达能力,可以与CNN模型的特征表达结合,得到更好的效果。
因此作者提出了Multi-scale CRFs和Cascade CRFs两个模块。
代码:danxuhk/ContinuousCRF-CNN 基于caffe框架。