【论文简读】DIV-Loss

很久没有跟踪无监督MVS的工作了,今天快速过一篇ECCV2024 Oral的文章,作者都来自UCSB。这也是我第一次知道这个学校也有组在做MVS。

项目地址:Github

文章目录

  • [1 Introduction](#1 Introduction)
  • [2 Related Work](#2 Related Work)
  • [3 Methods](#3 Methods)
    • [3.1 Preliminaries](#3.1 Preliminaries)
    • [3.2 Depth-Smoothness Loss](#3.2 Depth-Smoothness Loss)
    • [3.3 Image-Synthesis Loss](#3.3 Image-Synthesis Loss)
    • [3.4 Supervision View Sampling](#3.4 Supervision View Sampling)
  • [4 Experiments](#4 Experiments)
  • [5 核心代码](#5 核心代码)

1 Introduction

论文的主要创新点集中在改进无监督 MVS 的核心损失函数,提出了 DIV Loss,包括以下三个关键部分:

  • 提出了一个新的深度平滑loss,使用Clamped 2nd-Order Depth Smoothness
  • 提出了一个learning-based监督,通过合成图像来做,提升与视角相关的效果
  • 除了使用本来的source views之外,还使用更多的view来做监督,以增强网络预测未见视角的能力

介绍了有监督和无监督的MVS,并且多介绍了深度平滑的一些工作,为后面展开说自己的方法做铺垫。

3 Methods

3.1 Preliminaries

pipeline如下图所示:

3.2 Depth-Smoothness Loss

如图2所示,传统无监督MVS的平滑损失使用一阶梯度,这样的损失鼓励locally-constant depth,容易导致楼梯效应(stair-stepping),在物体边界就深度非常不准,造成artifacts。于是,部分工作使用二阶梯度,来鼓励locally-smooth depth,这样虽然能缓解楼梯效应,但这样会错误地跨物体边界平滑,导致深度边界模糊,如图4所示。

作者发现,二阶梯度光滑性是有用的,但不应在边界区域过度 penalize。因此,他们提出梯度截断(Clamping),即在计算损失时将二阶梯度的绝对值限制在一个上限。这样的话,在平滑区域,损失与传统二阶平滑一致,就能保持平滑表面;在物体边界,二阶梯度通常很大,但被 clamp 限制,就不会被过度penalize了,并且,允许出现清晰的深度不连续性,可以消除深度渗透问题。

本文创新点:提出 "二阶梯度+梯度截断"。

  • 对二阶梯度进行截断(clamp),允许在物体边界处出现锐利的深度不连续。
  • 在平滑区域仍能保持光滑性,显著减少边界artifacts。
  • 效果:显著改善物体边界的深度预测质量。

3.3 Image-Synthesis Loss

传统无监督MVS使用基于warp的photometric loss,并用min-K策略过滤遮挡与高误差像素。

本文创新点:引入一个小 CNN 网络。

  • 将 warp 后的多视角图像作为输入,预测每个像素的权重。
  • 将加权融合后的结果作为"合成参考图像"进行 photometric supervision。
  • 同时结合显式的遮挡 mask(shadow mapping)。
  • 优点:更好地处理视角相关效应(如高光、反射);避免手工设计启发式规则。

3.4 Supervision View Sampling

以往方法使用的监督视图与MVS输入视图完全一致。

本文创新点:DIV Loss 额外采样一些非输入视图作为监督信号。

  • 挑战网络去预测能在未见视角下仍一致的深度。
  • 提高模型泛化能力与对缺失信息的鲁棒性。
  • 几乎无额外计算成本。

4 Experiments

目前来说纯无监督MVS这个是SOTA,从实验表格上看这个截断loss和策略上的trick在其他MVS pipeline也可以用上。

5 核心代码

核心创新点,也就是loss中深度平滑正则项,对二阶梯度的截断,实现很简单。

python 复制代码
def depth_smoothness_2nd_order(depth, img, lambda_wt=1.0, clip=2.0):
    """Computes image-aware depth smoothness loss using relaxed 2nd-order formulation."""
    # 对深度图计算一阶梯度,append_zeros=True表示在图像边界补零,避免尺寸不一致
    depth_dx, depth_dy = gradient(depth, append_zeros=True)
    # 对一阶梯度再求梯度,得到二阶梯度
    depth_dxdx, depth_dxdy = gradient(depth_dx, append_zeros=True)
    depth_dydx, depth_dydy = gradient(depth_dy, append_zeros=True)

    # enormous 2nd order gradients correspond to depth discontinuities
    # 将所有二阶梯度截断到[-clip, clip],避免边界处的大梯度被过度penalize,从而允许物体边界出现锐利的深度不连续
    depth_dxdx = torch.clip(depth_dxdx, -clip, clip)
    depth_dxdy = torch.clip(depth_dxdy, -clip, clip)
    depth_dydx = torch.clip(depth_dydx, -clip, clip)
    depth_dydy = torch.clip(depth_dydy, -clip, clip)

    # 对图像计算一阶梯度
    image_dx, image_dy = gradient(img, append_zeros=True)

    # get weight for gradient penalty
    # 在图像的边缘处,梯度大,权重变小,相当于放宽深度平滑约束(允许深度跳变)
    # 在图像平坦区域,梯度小,权重接近1,相当于强化平滑约束
    weights_x = torch.exp(-(lambda_wt * torch.sum(torch.abs(image_dx), 3, keepdim=True)))
    weights_y = torch.exp(-(lambda_wt * torch.sum(torch.abs(image_dy), 3, keepdim=True)))

    # 对 x、y 方向分别计算平滑损失,每个方向同时考虑同方向和交叉方向的二阶导数(平均后求和),最终返回两个方向的加权平均
    smoothness_x = weights_x * (torch.abs(depth_dxdx) + torch.abs(depth_dydx)) / 2.
    smoothness_y = weights_y * (torch.abs(depth_dydy) + torch.abs(depth_dxdy)) / 2.
    return torch.mean(smoothness_x) + torch.mean(smoothness_y)

这个正则是一种无监督的几何先验,解决了"深度要合理"的问题,允许物体边界处的锐利跳变。

相关推荐
聚客AI25 分钟前
⭐超越CNN与RNN:为什么Transformer是AI发展的必然选择?
人工智能·llm·掘金·日新计划
快手技术1 小时前
可灵AI数字人来了!快手重磅发布Kling-Avatar,面向多模态指令理解与控制的数字人长视频生成新范式
人工智能
算家计算1 小时前
PDF解析神器——MinerU本地部署教程,一键去除页眉页脚,精准提取公式表格,支持84种语言,让文档转换更简单!
人工智能·开源
逛逛GitHub1 小时前
面壁「小钢炮」最新开源!0.5B 的声音克隆神器。
人工智能·github
后端小肥肠2 小时前
Coze 一键生成 AI 星座漫画,从 0 到 1 拿捏 10w + 流量!,小白可学
人工智能·aigc·coze
canonical_entropy3 小时前
AI的集体反思:我们为什么未能预见到"可逆计算"的演进方向?
人工智能·低代码·aigc
mortimer4 小时前
Python 文件上传:一个简单却易犯的错误及解决方案
人工智能·python
IT_陈寒5 小时前
Vue3性能优化实战:这5个技巧让我的应用加载速度提升了70%
前端·人工智能·后端
机器之心5 小时前
英伟达50亿美元入股英特尔,将发布CPU+GPU合体芯片,大结局来了?
人工智能·openai