《Self-Supervised Monocular Scene Flow Estimation》论文笔记
Posted m_buddy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《Self-Supervised Monocular Scene Flow Estimation》论文笔记相关的知识,希望对你有一定的参考价值。
参考代码:self-mono-sf
1. 概述
介绍:这篇文章介绍了一种自监督单目相机场景流和深度估计方法,单目场景流是需要在单目视频序列中估计出像素的3D空间移动信息,而且在没有标注的情况下完成该任务,因而其需要克服更多的困难。这篇文章的方法是在PWC-Net的基础上进行创新改进而来的,在预测过程中该方法中将3D场景流和深度估计任务组合起来,并在构建的cost-volume上进行解码预测。对于单目的视觉任务是会存在场景scale不准确、目标遮挡等情况的,对此文章引入了双目图像用于解决单目中存在的scale不准确问题,并通过光流映射采用启发式的遮挡掩膜提取机制解决遮挡的问题。在自监督的单目深度估计中一个比较头疼的问题便是场景中的运动物体,这篇文章将单目深度估计和3D场景流组合起来可看作是对该场景的一种解决思路(文章:Unsupervised Monocular Depth Learning in Dynamic Scenes也是一种类似的解决办法)。
在这篇文章中将单目深度估计与3D场景流组合起来进行预测,并将这两个任务互为补充构建约束表达用于监督。通过双目图像对、光流遮挡掩膜计算、3D空间点约束有效处理自监督过程中存在的问题(如scale问题),文章算法的预测效果见下图所示:
2. 方法设计
2.1 pipeline
文章方法的整体pipeline见下图所示:
文章的方法的主体架构是来自于双目匹配网络PWC-Net的,不同点是同时估计3D场景流和单目深度信息,并且其中的场景流不是估计的残差而是在每个level都估计完整场景流。另外一个不同点是采用自监督的形式进行约束,因而有了最下面的warp分支。
对于文章的方法为何要将scene flow和depth联合估计,以及共同使用一个解码器去预测,这里直接给出实测的性能比较以进行说明:
2.2 单目深度估计
在文章的任务中需要估计参考图像
I
t
I_t
It中像素点
p
=
(
p
x
,
p
y
)
p=(p_x,p_y)
p=(px,py)的3D坐标点
P
=
(
P
x
,
P
y
,
P
z
)
P=(P_x,P_y,P_z)
P=(Px,Py,Pz),和该3D点到目标图像
I
t
+
1
I_t+1
It+1对应像素3D点
P
′
=
(
P
x
′
,
P
y
′
,
P
z
′
)
P^'=(P^'_x,P^'_y,P^'_z)
P′=(Px′,Py′,Pz′)的场景流
s
=
(
s
x
,
s
y
,
s
z
)
s=(s_x,s_y,s_z)
s=(sx,sy,sz)。也就是下图中描绘的对应关系:
要准确估计场景流
s
=
(
s
x
,
s
y
,
s
z
)
s=(s_x,s_y,s_z)
s=(sx,sy,sz)就需要产生运动变化的3D点准确,但是在单目场景下深度是存在scale上的不确定性,也就是下图中展示的情况(一个3D点其对应的真实深度值是存在多个解的):
那么怎么去处理这个深度估计scale上的不确定性呢?一个有效的办法便是使用双目系统,在给定相机焦距
f
f
o
c
a
l
f_focal
ffocal,基线距离为
b
b
b,那么对应的深度就可以描述为:
d
^
=
f
f
o
c
a
l
⋅
b
d
\\hatd=\\fracf_focal\\cdot bd
d^=dffocal⋅b,这样就可以解决scale带来的不确定性问题。
PS: 这里需要注意的是上述提到的双目图像中参与深度估计与3D场景流估计的图像均为双目系统的左视图,右视图主要用于实现对scale的约束和生成遮挡掩膜。而且上述使用双目的过程是在训练的阶段(也就是在训练过程中右视图用于训练引导),而在测试阶段还是使用的单目视频序列进行预测。
对于这篇文章方法训练所需的数据是连续的双目视频帧 I t l , I t + 1 l , I t r , I t + 1 r \\I_t^l,I_t+1^l,I_t^r,I_t+1^r\\ Itl,It+1l,Itr,It+1r。在深度估计任务中会使用帧 I t l , I t + 1 l \\I_t^l,I_t+1^l\\ Itl,It+1l分别估计对应的视差图 d t l , d t + 1 l \\d_t^l,d_t+1^l\\ dtl,dt+1l,以及这两帧图像按照顺序排列不同得到的3D场景流 s f w l , s b w l \\s_fw^l,s_bw^l\\ sfwl,sbwl。
对于深度估计任务其采用约束是光度一致性,这一点与传统意义上的自监督单目深度估计类似。只不过这里光度一致性是建立在双目系统之上的,通过给定的双目相机标定参数和左视图估计出的视差
d
t
l
d_t^l
dtl将右视图
I
t
l
I_t^l
Itl(
t
+
1
t+1
t+1时刻同理,这里只讲
t
t
t时刻)变换到左视图得到左视图的重建结果
I
^
t
l
,
d
\\hatI_t^l,d
I^tl,d。那么就可以在这个重建视图和原视图上进行光度一致性约束:
ρ
(
a
,
b
)
=
α
1
−
S
S
I
M
(
a
,
b
)
2
+
(
1
−
α
)
∣
∣
a
−
b
∣
∣
1
\\rho(a,b)=\\alpha\\frac1-SSIM(a,b)2+(1-\\alpha)||a-b||_1
ρ(a,b)=α21−SSIM(a,b)+(1−α)∣∣a−b∣∣1
其中,
α
=
0.85
\\alpha=0.85
α=0.85。但是这里又一个问题需要去解决那就是遮挡的问题,在MonoDepth2中是通过选取最小光度重构误差方式进行处理。而这篇文章中采用的是估计右视图的视差
d
t
r
d_t^r
dtr,之后进行前向映射判断映射之后的值是否满足判定条件来判定是否为遮挡区域(因为遮挡区域映射不过去嘛),这样就可以得到遮挡掩膜
O
t
l
,
d
i
s
p
∈
0
,
1
O_t^l,disp\\in\\0,1\\
Otl,disp∈0,1(其中0代表未遮挡)。其实现代码可以参考该函数:
# losses.py#L85
def _adaptive_disocc_detection_disp(disp):
# # init
b, _, h, w, = disp.size()
mask = torch.ones(b, 1, h, w, dtype=disp.dtype, device=disp.device).float().requires_grad_(False)
flow = torch.zeros(b, 2, h, w, dtype=disp.dtype, device=disp.device).float().requires_grad_(False)
flow[:, 0:1, :, : ] = disp * w
flow = flow.transpose(1, 2).transpose(2, 3)
disocc = torch.clamp(forward_warp()(mask, flow), 0, 1)
disocc_map = (disocc > 0.5)
if disocc_map.float().sum() < (b * h * w / 2):
disocc_map = torch.ones(b, 1, h, w, dtype=torch.bool, device=disp.device).requires_grad_(False)
return disocc_map
那么对于光对一致性的约束添加了遮挡mask之后就可以描述为:
以上是关于《Self-Supervised Monocular Scene Flow Estimation》论文笔记的主要内容,如果未能解决你的问题,请参考以下文章
NTU 课程笔记:self-supervised learning
自监督学习(Self-Supervised Learning) 2018-2020年发展综述
自监督学习(Self-Supervised Learning) 2018-2020年发展综述
MoCo v3: An Empirical Study of Training Self-Supervised Vision Transformers
Instance Localization for Self-supervised Detection Pretraining 解读
Instance Localization for Self-supervised Detection Pretraining 解读