论文阅读笔记:Depth Pro: Sharp Monocular Metric Depth in Less Than a Second

论文阅读笔记:Depth Pro: Sharp Monocular Metric Depth in Less Than a Second

  • [1 背景](#1 背景)
    • [1.1 动机](#1.1 动机)
    • [1.2 提出的方法](#1.2 提出的方法)
  • [2 创新点](#2 创新点)
  • [3 方法](#3 方法)
  • [4 模块](#4 模块)
    • [4.1 训练目标](#4.1 训练目标)
    • [4.2 课程训练](#4.2 课程训练)
  • [4.3 边缘评价指标](#4.3 边缘评价指标)
    • [4.4 焦距估计](#4.4 焦距估计)
  • [5 效果](#5 效果)
    • [5.1 和SOTA方法的对比](#5.1 和SOTA方法的对比)

论文:https://arxiv.org/abs/2410.02073

代码:https://github.com/apple/ml-depth-pro

1 背景

1.1 动机

单幅图像新视图合成的应用暗含了许多单目深度估计待解决的问题。

首先单目深度估计应该零样本地在任何图像上工作,不局限于特定的域,理想的在零样本下生成深度估计图。为了最广泛的"野外"适用性,该方法应该产生绝对尺度,即使没有提供相机内参。这样就可以实现试图合成场景,如从63毫米外合成该场景的视图。

其次,单目深度估计器应该在高分辨率下操作,并产生与图像细节紧密相关的细粒度深度图,如头发,皮毛等。生成精确跟踪细节的锐利深度图的一个好处是消除了"飞行像素",这在视图合成中会降低图像质量。

第三,需要交互式应用场景,深度估计器应该在低延迟下运行,在不到1秒的时间内处理一张高分辨率图像,以支持交互式视图合成的按需查询。

1.2 提出的方法

在这项工作中,作者提出了一个满足以上所有需求的零样本单目估计基础模型,Depth Pro,在不需要相机内参等数据的情况下,在任意"野外"图像上生成具有绝对尺度的高分辨率深度估计图。在V100 GPU上以0.3秒的速度产生2.25M像素深度图。图1给出了一些具有代表性的结果。Depth Pro在锐利地描绘物体边界方面显著由于之前的所有工作,包括如头发,皮毛和植被等细微结构。

如图2所示,Depth Pro提供了无与伦比的边界追踪,在边界召回中超过了之前所有的工作,相比于目前最先进的边界精读,Depth Pro速度快了1~2个数量级,边界精读更高,提供了具有绝对尺度的深度估计图。

2 创新点

  • 设计了一种高效的基于多尺度的ViT框架,用于捕获全局图像上下文,同时在高分辨率下也能预测出精细的结构。

  • 提出了一套新的度量标准,可以利用高精度的抠图数据集来量化在评估单目深度图中边界跟踪的准确性。

  • 设计了一组损失函数和训练方法,以促进锐利深度估计,同时在集提供了粗略的和不准确的边界监督的真实世界数据集上,以及提供了精确的像素级GT但是真实性有限的合成数据集上训练。

  • 从单幅图像中实现了零样本焦距估计,其性能显著优于现有技术。

3 方法

核心思想是将普通的ViT编码器应用在多个尺度提取的块上,并将块预测融合到一个端到端的可训练模型中的单个高分辨率密集预测中。架构如图3所示。

为了预测深度,作者使用了两个ViT编码器,一个块编码器和一个图像编码器。

  • 块编码器应用于多个尺度下提取的块。从直接上将,这可能允许学习的表示是尺度不变的,因为权重是跨尺度共享的。

  • 图像编码器将块预测锚定在全局上下文中。他应用于整个输入图像, 下采样到所选择的编码器主干的基本输入分辨率(本文是384×384)。

整个网络的固定分辨率为 1536×1536,他被选定为 ViT 的 384×384 的倍数。这就保证了足够大的感受野和对任意图像的恒定运行时间,同时防止了超出显存问题。

降采样到 1536×1536,768×768 和 384 ×384 后,输入图像被分割成大小为 384×384 的块,为了避免接缝,对于最精细的两个尺度,作者分割时采用重叠划分的方式。在每个尺度下,块被输入到块编码器中,为每个块(图3中的特征3-5)产生一个 24 ×24 大小的特征张量,在最精细的尺度上作者进一步提取中间特征(图3中的特征1和2)以捕获更细粒度的细节。

这里感觉原文说的不是很清楚,可以看代码 https://github.com/apple/ml-depth-pro/blob/main/src/depth_pro/network/encoder.py#L247

代码中的 x_latent0_featuresx_latent1_featuresx0_features x1_features x3_features 分别表示图 3 中的 feature 1-5。

python 复制代码
  # Step 0: create a 3-level image pyramid.
  x0, x1, x2 = self._create_pyramid(x)
  # Step 1: split to create batched overlapped mini-images at the backbone (BeiT/ViT/Dino) resolution.
  # 5x5 @ 384x384 at the highest resolution (1536x1536).
  x0_patches = self.split(x0, overlap_ratio=0.25)
  # 3x3 @ 384x384 at the middle resolution (768x768).
  x1_patches = self.split(x1, overlap_ratio=0.5)
  # 1x1 # 384x384 at the lowest resolution (384x384).
  x2_patches = x2
  
  # Concatenate all the sliding window patches and form a batch of size (35=5x5+3x3+1x1).
  x_pyramid_patches = torch.cat(
  		(x0_patches, x1_patches, x2_patches),
  		dim=0,
  )
  # Step 2: Run the backbone (BeiT) model and get the result of large batch size.
  x_pyramid_encodings = self.patch_encoder(x_pyramid_patches)
  x_pyramid_encodings = self.reshape_feature(
		x_pyramid_encodings, self.out_size, self.out_size
  )
  # Step 3: merging.
  # Merge highres latent encoding.
  x_latent0_encodings = self.reshape_feature(
  		self.backbone_highres_hook0,   # 中间特征
  		self.out_size,
  		self.out_size,
  )
  x_latent0_features = self.merge(
  		x_latent0_encodings[: batch_size * 5 * 5], batch_size=batch_size, padding=3
  )
  
   x_latent1_encodings = self.reshape_feature(
  		self.backbone_highres_hook1,   # 中间特征
  		self.out_size,
  		self.out_size,
  )
  x_latent1_features = self.merge(
  		x_latent1_encodings[: batch_size * 5 * 5], batch_size=batch_size, padding=3
  )
  # Split the 35 batch size from pyramid encoding back into 5x5+3x3+1x1.
  x0_encodings, x1_encodings, x2_encodings = torch.split(
  		x_pyramid_encodings,
  		[len(x0_patches), len(x1_patches), len(x2_patches)],
  		dim=0,
  )
  
  # 96x96 feature maps by merging 5x5 @ 24x24 patches with overlaps.
  x0_features = self.merge(x0_encodings, batch_size=batch_size, padding=3)
  
  # 48x84 feature maps by merging 3x3 @ 24x24 patches with overlaps.
  x1_features = self.merge(x1_encodings, batch_size=batch_size, padding=6)
  
  # 24x24 feature maps.
  x2_features = x2_encodings

过了Patch编码器后,共 (5×5×2) + (5×5+3×3+1) 个patch。

  • 5×5×2 表示,作者用最精细的1536分辨率上拆分的 5×5 的块用编码器编码时,保留了中间 2 层的特征,并将其输出,按重叠划分的逆过程又合并回去

  • 5×5+3×3+1表示,各个尺度下的特征经过编码后,最后一层输出的特征,然后再合并回去

除了跨尺度共享表示外,编码器网络的基于patch的应用支持并行化,因为patch可以独立处理。计算效率的另一个来源是,与将ViT扩展到更高分辨率相比,基于patch处理的计算复杂度更低。因为多头注意力计算复杂度是输入像素数量的二次方,因此在图像维度上呈4次方关系。

4 模块

4.1 训练目标

对于每一个输入图像 I I I,网络 f f f 预测一个标准的逆深度图像 C = f ( I ) C=f(I) C=f(I)。为了获得稠密的深度估计图 D m D_m Dm ,作者用水平视角来缩放,并用焦距 f p x f_{px} fpx 和 宽度 w w w 来表示: D m = f p x w C D_m = \frac{f_{px}}{wC} Dm=wCfpx。

出自论文《Metric3D: Towards zero-shot metric 3D prediction from a single image》

作者使用多个目标进行训练,所有这些目标都是基于典型的逆深度,因为这将优先考虑靠近相机的区域,而不是更远的区域或者整个场景、设 c ^ \hat{c} c^ 为GT,对于所有度量数据集,计算每个像素 i i i 的平均绝对误差,对于真实世界数据集,每张图中丢弃误差top 20%的像素:

误差top20%的像素一般是比较远的像素。

对于所有非度量数据集(即没有可靠的相机内参或尺度不一致),在计算损失之前,先通过与中位数的平均绝对误差来归一化预测和GT。

出自论文《Towards robust monocular depth estimation: Mixing datasets for zero-shot cross-dataset transfer》

归一化来规避绝对尺度不准的问题,变成相对尺度

作者进一步计算多尺度下逆深度图的一阶导数和二阶导数的误差,令 KaTeX parse error: Undefined control sequence: \* at position 3: ▽_\̲*̲ 表示空间导数算子,如scharr(S) 或 laplace(L), p p p 表示误差范数,M尺度上的多尺度导数损失定义为:

其中尺度 j j j 是通过模糊和下采样逆深度图来计算得到的,每个尺度的因子为2,为了简写,定义平均梯度误差 L M A G E = L S , 1 , 6 L_{MAGE}=L_{S,1,6} LMAGE=LS,1,6,平均绝对拉普拉斯误差 L M A L E = L L , 1 , 6 L_{MALE}=L_{L,1,6} LMALE=LL,1,6,均方梯度误差 L M S G E = L S , 2 , 6 L_{MSGE}=L_{S,2,6} LMSGE=LS,2,6。

4.2 课程训练

课程训练旨在通过逐步引入越来越难的样本或任务,帮助模型逐渐学习到复杂的模式和规律。提出课程训练的动机如下:

  • 在真实数据和合成数据的大量混合数据集上训练提高了零样本的泛化能力。

  • 人工合成的数据集能够提供精确的像素级GT,而真实世界的训练集往往包含缺失、不匹配的深度和物体边界上的错误估计。

  • 预测会随着训练过程越来越好。

基于这些观察,作者设计了一个二阶段的训练课程。第一阶段,我们的学习目标是学习鲁棒的特征,使网络能够跨领域泛化。为此,作者在所有已标记的训练集的混合上进行训练,在度量数据集上最小化 L M A E L_{MAE} LMAE,在非度量数据集上最小化 L M A E L_{MAE} LMAE 的归一化版本。 L M A E L_{MAE} LMAE 因其在处理损坏的真实世界GT时的鲁棒性而被选择,为了使网络预测朝向锐利地边界,作者也对预测到的梯度进行监督。然而这会阻碍优化,减缓收敛。作者发现仅应用于合成数据的尺度和平移不变梯度损失效果会更好。

第二阶段的训练旨在锐化边界并揭示预测深度图中的细节。为了尽量减少不准确的GT的影响,现阶段只在高质量的像素级GT的合成数据上训练(虽然这点到了在合成数据上先训练,然后在真实数据上微调的普遍做法)。具体来说,再次最小化 L M A E L_{MAE} LMAE 的同时,在 L M A G E L_{MAGE} LMAGE, L M A L E L_{MALE} LMALE 和 L M S G E L_{MSGE} LMSGE 的一阶和二阶导数上选择损失进行补充。

4.3 边缘评价指标

新视图合成等应用需要深度图与物体边界保持一致。不对齐活模糊的边界会使得物体出现扭曲或分裂。常见的单目深度估计很少考虑边界清晰度,这可能是因为缺乏多样的和真实的,且具备像素级别GT的数据集。为了解决这个问题,作者专门提出了一套用于深度深度边界的指标。作者利用现有的高质量的抠图,显著性检测或分割任务的标注作为深度深度边界的基础真值,将这些任务的标注视为二值化图,定义了对象与其环境之间的前后背景关系。这种关系在任何情况下都可能不成立,尤其是对于分割掩码,作者通过人工检查很容易的丢弃了这种有问题的案例。为了保证关系成立,作者只考虑二值化图中边缘周围的像素。

作者使用相邻像素的成对深度比来定义前后背景关系。令 i , j i,j i,j 为向量的两个像素的位置,定义一个由深度图 d d d 导出的遮挡轮廓 c d c_d cd 为 c d ( i , j ) = [ d j d i > ( 1 + t 100 ) ] c_d(i,j)=[\frac{d_j}{d_i}>(1+\frac{t}{100})] cd(i,j)=[didj>(1+100t)] ,其中 [ ⋅ ] [·] [⋅]表示满足条件为1,不满足条件为0。直观地说,如果像素 i i i 和 j j j 对应的深度相差超过了 t t t%,这表明像素 i i i 和 j j j 之间存在轮廓遮挡,对于所有的相邻像素对,可以计算精确率 P P P 和召回率 R R R 为:

在本文实验中,根据 P P P 和 R R R 再计算了 F 1 F1 F1。为了考虑多个相对深度比,作者对 F 1 F1 F1 进行了加权,阈值从 t m i n = 5 t_{min}=5 tmin=5 到 t m a x = 25 t_{max}=25 tmax=25,对高阈值具有更强的权重。这种度量方式不需要任何手动标注,而是简单的通过合成数据来获得像素级GT。

类似地,我们也可以从二进制标签图中识别遮挡轮廓,这些标签图可以从真实世界的分割、显著性检测和抠图数据集中获得。给定图像上的二值掩膜 b b b,定义像素 i , j i,j i,j 之间存在遮挡轮廓 c b c_b cb 为 c b ( i , j ) = b ( i ) ∧ ¬ b ( j ) c_b(i,j)=b(i)∧¬b(j) cb(i,j)=b(i)∧¬b(j)。利用这个定义,通过替换公式(3)中深度图的遮挡轮廓来计算召回。由于二值图通常标记整个物体,我们无法获得与物体轮廓不对齐的真实遮挡轮廓。因此,只能计算召回率,而不能计算精确率。

比如某个对象表面的深度变化明显,但通过二值图只能获得其边缘的轮廓。

4.4 焦距估计

为了处理可能存在源数据不准确或丢失的图像,在网络中添加了一个焦距估计头。一个小的卷积头从深度估计网络中提取冻结的特征和从单独的ViT图像编码器中提取的特征来预测水平角度视图的焦距。使用 L 2 L_2 L2 损失作为训练损失。深度估计训练完成后,再对焦距头和ViT编码器进行训练。分离焦距训练的好处是:避免了深度和焦距训练目标平衡的必要性,还允许在不同数据集上训练焦距头。

5 效果

5.1 和SOTA方法的对比

和SOTA方法对比深度准确率。

和SOTA方法对比边缘准确率。

和SOTA方法对比焦距估计。

用于单目新视图合成的效果。

相关推荐
HPC_fac130520678162 小时前
以科学计算为切入点:剖析英伟达服务器过热难题
服务器·人工智能·深度学习·机器学习·计算机视觉·数据挖掘·gpu算力
小陈phd4 小时前
OpenCV从入门到精通实战(九)——基于dlib的疲劳监测 ear计算
人工智能·opencv·计算机视觉
冰帝海岸5 小时前
01-spring security认证笔记
java·笔记·spring
小二·6 小时前
java基础面试题笔记(基础篇)
java·笔记·python
wusong9999 小时前
mongoDB回顾笔记(一)
数据库·笔记·mongodb
猫爪笔记9 小时前
前端:HTML (学习笔记)【1】
前端·笔记·学习·html
Resurgence039 小时前
【计组笔记】习题
笔记
如若1239 小时前
主要用于图像的颜色提取、替换以及区域修改
人工智能·opencv·计算机视觉
pq113_69 小时前
ftdi_sio应用学习笔记 3 - GPIO
笔记·学习·ftdi_sio
爱米的前端小笔记10 小时前
前端八股自学笔记分享—页面布局(二)
前端·笔记·学习·面试·求职招聘