深度学习:无监督深度测距:《Unsupervised Monocular Depth Estimation With Left-Right Consistency》论文笔记,视频笔记monodepth

总揽:论文干了啥:

一句话:采用Left-Right Consitency来优化。

也就是以左视图为输入,以右视图为training中的监督真值(gruond truth),生成右侧对应的视图;然后又以左视图为监督真值,根据右视图生成左视图。最小化这两个过程的联合loss则可以一个很好的左右视图对应关系。
最终网络得到一个四个scale大小的输出(disp1-disp4)

论文的代码

github在线看代码

如何做的,提出了什么新的想法

利用极坐标几何约束,我们可以用图像重建损失训练我们的神经网络,从而生成视差图。

我们还发现, 如果只用图像重建求深度图,会导致其质量较差。(之前的一些 DCNN方式 就是 用了 只用图像 的方式,直接求深度 图的方式,这种方式,在本文看来就是垃圾。)

为了解决这一问题,本文提出了一种新的损失函数,它加强了 左右视差图的一致性,与现有的方法相比,它提高了性能和鲁棒性。

1)你知道视差 和 深度 是有关系的

视差 和 深度 是有关系的;可以互相推算

disparity ~ depth

为什么 他们 可以互相推算: 一个 图解

假设 我们拍摄了两张图片, L, R

也就是 下面 图 里面 的 左右 两个 绿色框

现在 ,在 L 上 有 橙色 的一点,这个点, 可以来自于 其 射线 上 的:

  • 紫色
  • 绿色
  • 蓝色
    三个 可能 的位置;

当然实际上 有 无数可能性,而不仅仅是 这三个点; 我只是 用这三个 进行举例

假定 绿色 是真实 的位置

而 紫色 是 离镜头近 的一个 可能性 位置
蓝色 是 远一点的 可能性位置。

我们的模型,应该有能力 从 紫色 ,蓝色, 绿色 的可能性中,准确地知道,真实 的值 应该是 绿色 那个

如果 我们的模型 能知道 是绿色 那个,也就是说,我们的模型 具有 深度/距离 预测的功能了。

在这里插入图片描述
好的,如何 让模型 知道 是 绿色 呢?

我们从右图 出发,放大观察 一下 右图 的特点

在这里插入图片描述

(备注: 在上述两个图示中,我们有这样一个预设: 就是,左右两个相机是水平的,也就是说,它们拍摄得到的图像,在垂直的上下方向上没有什么错位,而仅仅在水平的, 左右的方向上存在错位,也就是,只在左右的 方向上,存在视差,而垂直的方向上,没有什么 视差)

退一步说,如果我们的模型 能 预测 绿色点 往左 多少 能 生成 一个 「紫色点 在 右图 的位置」, 能 预测 绿色点 能 往右多少,生成 的 是 「蓝色点 在 右图 的位置」。

这里的往左,往右,就是 一个 标量,用于和 左图 的 绿点 坐标进行 「某种计算」,从而产生位移,让位移的 绿点 变成 紫色点,or 蓝色点。

对于左图 的每个 像素(每个绿点) G r e e n P o i n t I m a g e L GreenPoint_{Image_L} GreenPointImageL,都有一个 对应的 d r d_r dr 与之匹配,能够 发生 这么一件事:

G r e e n P o i n t I m a g e R = G r e e n P o i n t I m a g e L ∗ d r GreenPoint_{Image_R} = GreenPoint_{Image_L} * d_r GreenPointImageR=GreenPointImageLdr // 这个公式的意思是: 右图上的绿点 来自 左图上的绿点 与 右向视差图 运算所得。

(想一想,这里真的是简单的乘法运算吗?还是带有加法的复杂矩阵运算呢?

那么 这个预测右图每一个绿点的能力,就是完成了这件事: 变向地预测了 绿点 离镜头 的距离

也就是说, 只要模型能预测 d r d_r dr ,就能 预测 d e p t h depth depth

记住这句话:

视差是按比例缩小的逆深度,disparity=fb/depth

其中 的 fb 是 我们 规定/从经验 ,或者 计算 中得到的。

fb 分别是:

  • f: 相机焦距(我们俩眼睛 的 晶状体 的 厚度导致的光线折射??)
  • b: baseline distance(我们俩眼睛的距离??)

在这里插入图片描述

2)你知道我们如何用深度网络估计【视差/距离】

论文给了三个 架构,用来强调第三个(论文提出的这个)是最牛逼的, 分别是

  • naive
  • NoLR
  • Ours (with LR)

在这里插入图片描述
从左到右,进行 解释:

naive的网络:

直接从Left image 生成 d r d_r dr , 然后 对 Left image 进行 采样 ,与 d r d_r dr 进行运算,得到 输出 :

估计的: I ~ r \widetilde{I}^r I r

然后 跟真实 的 I r I^r Ir 进行比对

结果不好

NoLR 的网络:

应该是没有 加上 left right consistency 的意思

这里的思路是:

直接从Left image 生成 d l d_l dl , 然后 对 Right image 进行 采样 ,与 d l d_l dl 进行运算, 得到 输出:

估计的: I ~ l \widetilde{I}^l I l

然后 跟真实 的 I l I^l Il 进行比对

结果是: 存在 很多 ‘贴图复制’ 的人工痕迹,并且深度不连续

见图片:

在这里插入图片描述

我们的方法:带有 left right consistency

在这里插入图片描述

仍然是从 图片 生成 disparity map, 但是这次,是从 left image 生成 d r d_r dr, 以及 d l d_l dl

然后 用相反 的 图片 进行采样

说清楚一点,就是, 和 d r d_r dr 做运算的 ,其采样来自 left image 也就是 左侧的蓝线(连接了 I l I^l Il d r d^r dr 后的sampler)
d l d_l dl 做运算的,其 采样来自 right image 也就是 右侧的蓝线 (连接了 I r I^r Ir d l d^l dl 后的 sampler)

然后生成 对应的 I ~ r \widetilde{I}^r I r , I ~ l \widetilde{I}^l I l , 跟真实 I r I^r Ir, I l I^l Il 对比

作者说的 4 个 scale 到底是什么意思?

下面 这个 图 就是在 讲 他们的 模型架构,写了每次层的参数,每一层的输入 是谁,

也就知道了 网络 的前后关系,各个层组件是什么了;

只不过,通过表格的方式,没有 通过 一个 流程图的方式 更好,所以希望 后期 我可以 把 一个 流程图 添加在这里(todo 2021-09-08 15:01:27)
在这里插入图片描述

注意 图中 的解释:

k: 就是 kernel size ,一般 就是 设定 为 3

s: 就是 stride 就是步长,一帮就是 1 或者 2

需要进一步 理解的东西:

channels

本身图片 就只有三个 通道,分别 是 rgb ,我们人类认识物体的颜色,就是这 三个 通道;
但是神经网络 可以 认识一些 更多 通道的信息,通道 的增加来自于 卷积 ,(aka 来自于 filter,来自于 kernel)

downscale factor

猜一下: 向下缩放的 因数,

单不知道是在缩放啥 todo 2021-09-08 14:44:50

upsampling

上采样,我猜测 就是 卷积 这个动作

根据维基百科 的解释: Upsampling

这是从低 波特率 的 序列中,进行 扩张,插值;以至于 最后得到的输出,很像 一个 从更高频率 下 采样得到的序列;

downsampling(就是卷积)

根据维基百科 的解释: Downsampling(signal_processing)

向下采样,类似于 音频里面 的 降低 波特率,压缩, 得到一个 品质稍微又些次的复制品,近似品。

它的同义词 叫做 decimation : 大规模歼杀;

我不是很理解的 loss function

在这里插入图片描述

我们拆开看:

第一个: appearance matching loss: C a p l C_{ap}^l Capl

在这里插入图片描述

这里 涉及 到了: SSIM , L1 正则化
L1 正则化

是为了 避免 模型 过于 复杂,避免 过 拟合

SSIM

来自一篇 2004 论文: Image quality assessment: from error visibility to structural similarity.

看 论文 的名字,大概 可以 知道 SSIM 是一种 评估 图像质量 的 指标,从 error 的可见性,到 结构 上 的相似度。

第二个: disparity smoothness loss

在这里插入图片描述

留待之后解释 todo

第三个: left right consistency loss

在这里插入图片描述

这篇论文的代码:

模型的代码:链接

在这里插入图片描述

有关 loss 的代码

在这里插入图片描述
这里参考了 这个博客

Training Loss
成本有如下三个部分ap,ds,lr,Cap是根据训练输入与它的重建图像相近的程度,
Cds限制了视差预测的平滑性,
Clr倾向于左右视差一致性。
只有左图经过卷积神经网络的洗礼
虽然每个主要的步骤当中都包含着左右两图。

1. Appearance Matching Loss

图像是通过空间转化网络(STN)与视差图从对应的立体匹配图片中
获取相应的像素值。
STN利用双线性采样,
这样输出像素是四个输入像素的加权之和。

2. Disparity Smooth Loss
这个项就是使得预测出来的视差变得非常的平滑,
所以就在视差梯度上面加了一个惩罚,
这个成本的权重是与图像梯度有关,就是边缘项

3. Left-right disparity consistency loss
没什么好讲的,直接上代码

至此,写完了 loss ,论文 就开始 实验,这个 上述 博客 也 结尾了。

所以,对 loss 的理解 还是 非常重要的。

你要理解下面 这几个 名词: todo: 2021-09-08 15:25:54

  • 空间转化网络(STN)
  • 双线性采样
  • 四个输入像素的加权之和
  • 视差梯度上面加了一个惩罚
  • 成本的权重是与图像梯度有关

一些 可以 继续探索 的文章 和 博客:

  • 被本文 参考 的: mayer: DispNet: 很像之前的: end-to-end deep optical flow network

研读3

研读4

研读5;推荐

2017 年的 CVPR 视频 观看笔记;趣味向

2017 年的 CVPR

from youtubeLink
在这里插入图片描述

是啥东西

这是个 输入 图像
然后

我们的工作能: 给出 一个 深度 图

like this:

为啥 depth 有用

导航,机器人拿东西,虚拟现实,桌子有多远,多大

为啥用 monocular:单目相机?

贫穷和普适

monocular 能行吗?

在这里插入图片描述

既然 探测器 和 海盗头子 都能 ,我们也能


以前的方法

在这里插入图片描述

  • ground truth 值很难获得

数据集很难搞

kitti 数据集 本身 也有误差

或者说 遗漏: 见图片:

img

那咱么 可以用 双目 立体 几何 的手段

去训练

数学原理是:

在这里插入图片描述

原理就是上面这个原理,意思就是: L 和 R 之间的 差异 就是 跟 depth / 距离有关


现在 有很多 双目 设备:

在这里插入图片描述

我们不是第一个 用 双目 去做测距的:

在这里插入图片描述

多说一句:

在这里插入图片描述

这个文章 可能 就是 比较 早期 的 使用 双目 的 无监督 的 方法;

再补充一下:

在这里插入图片描述
这个文章 则是 使用 了 监督 的;

后记;视频里面的一些 细节

在这里插入图片描述

似乎上面 是在 讲 一个 baseline 的 模型,

下面 才是 我们的 的模型

在这里插入图片描述
我们 的 模型,似乎 是 可以 通过 生成 左右 两个 图片 进行 balalba。。。


一个 重要 组件

differentiable image smapler

他可以 把 left input image 转成 targe 的 input right image

看看这个图:

在这里插入图片描述

注意 线 1 和 线 2 ,这些 线 把 原始i 的 input 数据 ,打入 内部 走线 的输出

内部 走线 的输出 ,就是 一个 disparity 图片??

我的 理解 是 :

  • 上面 的 R disparity 图像 ,是 left image 通过 线 1 , 进行 变化,从而 达到 逼近 right image 的 一个 转换器/convert
  • 下面 的 L disparity 图像,虽然 也是 left image 输入 而 产生的,但是 是 用做 给 right image 用的,right iamge 通过 线 2 经历 了 L disparity 所代表的 convert 过程,就能 把 right image 自己 给 convert 成 一个 逼近 的 left image

有关于 架构

你可以 使用 任何 的 encoder: VGG ,ResNet

在这里插入图片描述

有关 结果

在这里插入图片描述

RTFSC (Read the f*cking source code )

读论文是RTM,Read the manual;接下来就是 RTFSC

但是 RTFSC 的过程中 也离不开 「STFW (Search The F*cking Web)」

所以,这一部分 记录 一下 这两个 步骤的 内容;

为了看懂代码:在网络上搜索到的tf相关知识

在monodepth_model.py 这个文件里

有这么一个类
在这里插入图片描述

有个 build_model() 函数:

def build_model(self):
	# 使用 arg_scope 函数 (见 tt3 ) 为 conv2d, conv2d_transpose 都设定 同一个 elu 激励函数 
    with slim.arg_scope([slim.conv2d, slim.conv2d_transpose], activation_fn=tf.nn.elu):
        with tf.variable_scope('model', reuse=self.reuse_variables):

            self.left_pyramid  = self.scale_pyramid(self.left,  4)
            # 如果 是训练  阶段,那么 就 需要 右边的 缩放图 来帮忙
            if self.mode == 'train':
                self.right_pyramid = self.scale_pyramid(self.right, 4)
            # 如果 开启了 立体的选项,那么 就把模型的input 制作为 左右图的 一起连接
            if self.params.do_stereo:
                self.model_input = tf.concat([self.left, self.right], 3)
            else:
            # 如果没有开启 立体 选项,那么 就是  仅仅 用 左图;
                self.model_input = self.left

            #build model
            # 如果 使用 vgg 的编码器
            if self.params.encoder == 'vgg':
                self.build_vgg()
            # 如果使用 resnet 的编码器
            elif self.params.encoder == 'resnet50':
                self.build_resnet50()
            else:
                return None

里面用到的 scale_pyramid 函数 ,是如下定义:

在这里插入图片描述
这个函数 整体 的流程 ,就是 确定输入;不过是加上了 scale_pyramid 这种方式 来重制了 输入;

好了,如果我们有了输入,剩下的,就是把输入打到模型里,

它给了两种 model 的可选

  • 一个是 vgg
  • 一个是 resnet50

我们看一看 vgg 这种模型;

build_vgg()

todo 2021-09-09 12:03:06 variable_scope https://blog.csdn.net/UESTC_C2_403/article/details/72328815

函数如下,有点长,但是有重复部分,不虚;

def build_vgg(self):
    #set convenience functions
    # 这里 使用 了 卷积;见 tt1
    conv = self.conv
    # 这里 分为 deconv 和 upconv ;见 tt2 
    if self.params.use_deconv:
        upconv = self.deconv
    else:
        upconv = self.upconv

    with tf.variable_scope('encoder'):
        conv1 = self.conv_block(self.model_input,  32, 7) # H/2
        conv2 = self.conv_block(conv1,             64, 5) # H/4
        conv3 = self.conv_block(conv2,            128, 3) # H/8
        conv4 = self.conv_block(conv3,            256, 3) # H/16
        conv5 = self.conv_block(conv4,            512, 3) # H/32
        conv6 = self.conv_block(conv5,            512, 3) # H/64
        conv7 = self.conv_block(conv6,            512, 3) # H/128

    with tf.variable_scope('skips'):
        skip1 = conv1
        skip2 = conv2
        skip3 = conv3
        skip4 = conv4
        skip5 = conv5
        skip6 = conv6
    
    with tf.variable_scope('decoder'):
        upconv7 = upconv(conv7,  512, 3, 2) #H/64
        concat7 = tf.concat([upconv7, skip6], 3)
        iconv7  = conv(concat7,  512, 3, 1)

        upconv6 = upconv(iconv7, 512, 3, 2) #H/32
        concat6 = tf.concat([upconv6, skip5], 3)
        iconv6  = conv(concat6,  512, 3, 1)

        upconv5 = upconv(iconv6, 256, 3, 2) #H/16
        concat5 = tf.concat([upconv5, skip4], 3)
        iconv5  = conv(concat5,  256, 3, 1)

        upconv4 = upconv(iconv5, 128, 3, 2) #H/8
        concat4 = tf.concat([upconv4, skip3], 3)
        iconv4  = conv(concat4,  128, 3, 1)
        self.disp4 = self.get_disp(iconv4)
        udisp4  = self.upsample_nn(self.disp4, 2)

        upconv3 = upconv(iconv4,  64, 3, 2) #H/4
        concat3 = tf.concat([upconv3, skip2, udisp4], 3)
        iconv3  = conv(concat3,   64, 3, 1)
        self.disp3 = self.get_disp(iconv3)
        udisp3  = self.upsample_nn(self.disp3, 2)

        upconv2 = upconv(iconv3,  32, 3, 2) #H/2
        concat2 = tf.concat([upconv2, skip1, udisp3], 3)
        iconv2  = conv(concat2,   32, 3, 1)
        self.disp2 = self.get_disp(iconv2)
        udisp2  = self.upsample_nn(self.disp2, 2)

        upconv1 = upconv(iconv2,  16, 3, 2) #H
        concat1 = tf.concat([upconv1, udisp2], 3)
        iconv1  = conv(concat1,   16, 3, 1)
        self.disp1 = self.get_disp(iconv1)

tt1:
在这里插入图片描述

tt2: 参考 : 理解deconvolution(反卷积、转置卷积)概念原理和计算公式、up-sampling(上采样)的几种方式、dilated convolution(空洞卷积)的原理理解和公式计算

deconv和up-sampling是FCN图像分割网络中用到的,两个扩大feature map尺寸的重要操作。

这里的扩大,就是我们通信工程里面的,上采样,把原来低频的信号,插值了, 变成更加高频的信号。

有的人 将deconv反卷积称作转置卷积,我们暂且先认为它俩的概念一致

deconv 的动画解释:

请添加图片描述

(deconv: 把不丰富的图像,变得丰富,把小尺寸的 图片,变为 大尺寸的)

conv 就是 deconv 的反向:是把大尺寸的 图片,变为 小尺寸的; 是在做特征提取;

tt3:

arg_scope 函数的使用

tensorflow.contrib.slim

其主要目的是来做所谓的“代码瘦身”。

在这里插入图片描述

  • 消除原生tensorflow里面很多重复的模板性的代码,
  • 让代码更紧凑,更具备可读性。
  • 提供了很多计算机视觉方面的著名模型(VGG, AlexNet等)
  • 我们不仅可以直接使用,甚至能以各种方式进行扩展

参考这里

tensorflow.contrib这个库:此目录中的任何代码未经官方支持,可能会随时更改或删除。每个目录下都有指定的所有者。它旨在包含额外功能和贡献,最终会合并到核心TensorFlow中,但其接口可能仍然会发生变化,或者需要进行一些测试,看是否可以获得更广泛的接受。所以slim依然不属于原生tensorflow。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值