基于深度学习的MVS学习笔记(05.04-05.07)

1. MVS方法与分类

1.1 问题界定:多目和单目双目

  • 单目深度估计:拟合一个函数将图像【RGB输入】映射到深度图【浮点输出】
  • 双目深度估计:双目回归视差,可以进一步求像素距离相机光心的深度
  • 多视点三维重建
    • 单目只能找到“相对的”相对关系
    • 双目理论上可以获取深度,但不同视角下深度可能不一致
    • 多目可以综合考虑,交叉验证

在特征提取上可以参考单目方法,在特征匹配和聚合上可以参考双目方法

1.2 MVS重建方法分类

方法缺点
直接点云重建 point cloud based一般采用点云传播的方式逐步让模型变得稠密难以并行化,重建时间长
基于体素的方法 volumetric based将3D空间划分为体素,在全局坐标系下判断每个体素的占用,能很好的通过正则化并行化。一般采用divide-and-conquer或八叉树等进行高分辨率重建由于内存消耗,一般只能处理小分辨率的场景
基于深度图融合 depth map fusion based将MVS问题解耦为逐视点的深度估计+最终融合所有视点图得到3D模型对于大基线角度和遮挡区域由于几何一致性会导致较差的质量

大基线角度:拍摄角度变换太大导致两张图差别很大

2. MVS流程

2.1 前序步骤:SfM

SfM 从运动中恢复结构【从图片中恢复/得到稀疏的点云+相机的参数】

2.2 核心问题建模:平面扫描算法

Plane Sweeping平面扫描【得到深度图】

  • 将空间划分成不同的深度假设平面,选择最好的深度假设平面 -> 恢复丢失的深度

  • 在物体表面的点,不同相机看到的应该是一样的(在物体上) -> 某种特征&某种度量

  • 由于SfM求得了相机参数,因此可以相互投影(Homograpy) -> 深度统一

2.3 后续步骤:深度图滤波与融合

已经估计出深度图,进行滤波和融合

像素点P,像素点P对应的深度D§,将参考视角下的P投影到源视角得到P’ -D(P‘),投影到很多源视角下

  • P和P‘距离比较进【像素点】
  • D§和D(P‘)距离比较近【深度图】
  • 至少在N个视点上满足,则认可这个点

这就是几何一致性滤波

另外常见的光度一致性滤波

得到过滤后的深度图就可以进行融合,目前关于融合方面的工作比较成熟

3. 基于深度学习的MVS方法

3.1 数据集介绍

DTU:用于训练和测试

针对MVS专门拍摄处理的高精度室内物体数据集,利用可调节照明的ABB机械臂进行多视点拍摄

  • 由124个不同场景组成
  • 每个物体共拍摄49个不同的视角
  • 每个视角共有7种不同的亮度
  • 每张图像分辨率为1600x1200

Tanks and Temples:用于泛化测试

大型室外场景数据集

  • 光照变化大
  • GT使用工业激光扫描仪获得
  • 场景存在大规模光照变化
  • 不能进行训练

BlendedMVS:用于finetune

  • 由113个场景组成
  • 覆盖小尺度和大尺度场景
  • 高精度合成数据

ETH3D:用于大规模重建

  • 包含25个高分辨率场景和10个低分辨率场景
  • 视点数量和分辨率非常庞大
  • 存在很多大面积弱纹理和遮挡区域
  • 一般作为传统方法的benchmark

3.2 评估指标介绍

准确率

召回率/完整性

3.3 MVSNet系列论文列表

代码仓库

https://github.com/waisvid/Awesome-MVS

基于深度学习:https://github.com/XYZ-qiyh/Awesome-Learning-MVS

4. 代码中的数据维度【以MVSNet处理为例】

  • B:batch_size
    • 在研究数据维度的时候可以直接将这个维度去掉
  • C:图像特征维度
    • 最开始是3-channels,后来通过特征提取网络变成32维
  • D/Ndepth:深度假设维度
    • 这里是192个不同的深度假设
  • H:图像高度
    • 原始是640,经过特征提取网络下采样了四倍,变成160
  • W:图像宽度
    • 同上,512-》128

MVSNet源码解析

train.py中最重要的fun就是train_sample

def train_sample(sample, detailed_summary=False):
    model.train()
    optimizer.zero_grad()

    sample_cuda = tocuda(sample)
    depth_gt = sample_cuda["depth"] # 深度图GT
    """
    depth_visual_00xx.png:还有49张深度图的png版本被用作mask
    二值图,值为1的像素是深度可靠点,后续训练只计算这些点的loss
    """
    mask = sample_cuda["mask"] # 指出哪些地方不用计算loss

    outputs = model(sample_cuda["imgs"], sample_cuda["proj_matrices"], sample_cuda["depth_values"])
    depth_est = outputs["depth"] # MVSNet得到的深度估计图

    loss = model_loss(depth_est, depth_gt, mask) # 在mask控制下计算估计深度图和GT的loss
    loss.backward()
    optimizer.step()

    scalar_outputs = {"loss": loss}
    image_outputs = {"depth_est": visualize_depth(depth_est * mask),  # 深度图估计
                     "depth_gt": sample["depth"],
                     "ref_img": sample["imgs"][:, 0],
                     "mask": sample["mask"]}
    
    if detailed_summary:
        image_outputs["errormap"] = (depth_est - depth_gt).abs() * mask
        # 更关注2mm和4mm的误差
        scalar_outputs["abs_depth_error"] = AbsDepthError_metrics(depth_est, depth_gt, mask > 0.5)
        scalar_outputs["thres2mm_error"] = Thres_metrics(depth_est, depth_gt, mask > 0.5, 2)
        scalar_outputs["thres4mm_error"] = Thres_metrics(depth_est, depth_gt, mask > 0.5, 4)
        scalar_outputs["thres8mm_error"] = Thres_metrics(depth_est, depth_gt, mask > 0.5, 8)

    return tensor2float(loss), tensor2float(scalar_outputs), image_outputs
class MVSNet(nn.Module):
    def __init__(self, refine=True):
        super(MVSNet, self).__init__()
        self.refine = refine

        self.feature = FeatureNet()
        self.cost_regularization = CostRegNet()
        if self.refine:
            self.refine_network = RefineNet()

    def forward(self, imgs, proj_matrices, depth_values):
        imgs = torch.unbind(imgs, 1)
        proj_matrices = torch.unbind(proj_matrices, 1)
        assert len(imgs) == len(proj_matrices), "Different number of images and projection matrices"
        img_height, img_width = imgs[0].shape[2], imgs[0].shape[3]
        num_depth = depth_values.shape[1]
        num_views = len(imgs)

        # step 1. feature extraction
        # in: images; out: 32-channel feature maps
        features = [self.feature(img) for img in imgs] # 会跑3次, 1张ref,两张src
        ref_feature, src_features = features[0], features[1:] # 每个特征图都是 [B, 32, H/4, W/4]
        ref_proj, src_projs = proj_matrices[0], proj_matrices[1:]

        # step 2. differentiable homograph, build cost volume
        # 把上面三个特征都投影到ref视点的锥体上,同时做一个方差聚合
        ref_volume = ref_feature.unsqueeze(2).repeat(1, 1, num_depth, 1, 1) # [B, 32, 192,H/4, W/4]
        volume_sum = ref_volume # 便于后面计算平均
        volume_sq_sum = ref_volume ** 2 # 便于后面计算方差
        del ref_volume
        for src_fea, src_proj in zip(src_features, src_projs):
            # warpped features
            warped_volume = homo_warping(src_fea, src_proj, ref_proj, depth_values)
            if self.training:
                volume_sum = volume_sum + warped_volume
                volume_sq_sum = volume_sq_sum + warped_volume ** 2
            else: # 测试模式【分辨率率很大,要节省内存】
                # TODO: this is only a temporal solution to save memory, better way?
                volume_sum += warped_volume
                volume_sq_sum += warped_volume.pow_(2)  # the memory of warped_volume has been modified
            del warped_volume

        # aggregate multiple feature volumes by variance 对应原文公式(2),计算方差
        volume_variance = volume_sq_sum.div_(num_views).sub_(volume_sum.div_(num_views).pow_(2)) # [B, 32, 192, H/4, W/4]

        # step 3. cost volume regularization
        cost_reg = self.cost_regularization(volume_variance) # [B, 1, 192, H/4, W/4]
        # cost_reg = F.upsample(cost_reg, [num_depth * 4, img_height, img_width], mode='trilinear')
        cost_reg = cost_reg.squeeze(1) # [B, 192, H/4, W/4]
        prob_volume = F.softmax(cost_reg, dim=1) # [B, 192, H/4, W/4]
        depth = depth_regression(prob_volume, depth_values=depth_values) # [B, H/4, W/4] 加权平均选择最优的深度

        with torch.no_grad():
            # photometric confidence-从概率体中获得一个置信图,只用来做滤波
            prob_volume_sum4 = 4 * F.avg_pool3d(F.pad(prob_volume.unsqueeze(1), pad=(0, 0, 0, 0, 1, 2)), (4, 1, 1), stride=1, padding=0).squeeze(1) # 和周围4个加一下得到一个聚合概率值
            depth_index = depth_regression(prob_volume, depth_values=torch.arange(num_depth, device=prob_volume.device, dtype=torch.float)).long()
            photometric_confidence = torch.gather(prob_volume_sum4, 1, depth_index.unsqueeze(1)).squeeze(1)

        # step 4. depth map refinement
        if not self.refine:
            return {"depth": depth, "photometric_confidence": photometric_confidence}
        else:
            refined_depth = self.refine_network(torch.cat((imgs[0], depth), 1))
            return {"depth": depth, "refined_depth": refined_depth, "photometric_confidence": photometric_confidence}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/605916.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【AI+音视频总结】如何在几分钟内用智能工具摘取音视频精华?揭秘下一代学习和内容创作神器!

今天无意发现一个网站,可以一步到位完成AI音视频总结。 我之前对于音视频总结的步骤还是借助 工具下载 剪映来完成的。详情可以参考之前写的一篇文章 【AI应用】模仿爆款视频二次创作短视频操作步骤 。 这里介绍的网站是 BibiGPT 。 BibiGPT AI 音视频助理 - 它是…

构建第一个ArkTS应用之@AppStorage:应用全局的UI状态存储

AppStorage是应用全局的UI状态存储,是和应用的进程绑定的,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。 和AppStorage不同的是,LocalStorage是页面级的,通常应用于页面内的数据共享。而AppStora…

VMare Workstation安装ubuntu虚拟机异常问题处理

安装方法 ubuntu官网下载插件 异常处理 开启时报错"unable to proceed without a log file" 遇到此问题的都有一个共同点,工作目录路径上都带了数字,比如"Ubuntu 64位 01",解决方法为: 选中"Ubuntu 64位…

可视化大屏的应用:电子政务领域的巨大应用价值

可视化大屏在电子政务领域的应用价值主要体现在以下几个方面: 数据监控与分析 可视化大屏可以将政务数据以图表、地图等形式展示在大屏上,帮助政府部门实时监控和分析各项指标和数据变化。例如,可以实时显示人口统计、经济指标、环境监测等…

利用“AnaTraf“网络流量分析仪轻松诊断和优化网络

网络性能监测和诊断(NPMD)是网络管理和优化的重要环节,准确快速地定位和排除网络故障对于保障业务正常运转至关重要。作为一款专业的网络流量分析设备,AnaTraf网络流量分析仪凭借其强大的流量分析和故障诊断功能,为网络管理者提供了一个高效的网络优化解决方案。 全面掌握网络…

如何将pdf文件换成3d模型?---模大狮模型网

PDF文件是一种广泛用于文档传输和共享的格式,但在某些情况下,我们可能希望将其中的内容转换为更具交互性和视觉效果的3D模型。本文将介绍如何将PDF文件转换为3D模型,为您展示实现这一想象的步骤。 选择合适的PDF文件: 首先&#…

利用AnaTraf网络流量分析仪轻松解决网络故障问题

网络故障是每个企业都必须面对的头痛问题。如何快速定位并解决网络问题,不仅能提高员工工作效率,也能减少因网络问题而带来的经济损失。 AnaTraf网络流量分析仪就是为解决这一问题而问世的一款高性能网络诊断工具。它能够对网络流量进行全面的实时监控和分析,帮助网络管理员快…

软考中级之数据库系统工程师笔记总结(六)多媒体基础

作者:Maynor 博客之星大数据领域Top1,GitHub项目awesome-chatgpt-project作者, 大厂程序员, 全网技术矩阵粉丝7w 公众号:Maynor996📢博客主页:https://manor.blog.csdn.net 📢欢迎点赞 👍 收藏 ⭐留言 &am…

请求响应里面的日期参数

日期参数 需要在控制类使用DateTimeFormat注解 package com.ming.controller; ​ ​ import org.springframework.format.annotation.DateTimeFormat; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.Rest…

1756jsp农产品销售管理系统Myeclipse开发mysql数据库C2C模式java编程计算机网页项目沙箱支付

一、源码特点 java 农产品销售管理系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统采用web模式,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0…

在做题中学习(53): 寻找旋转数组中的最小值

153. 寻找旋转排序数组中的最小值 - 力扣(LeetCode) 解法:O(logn)->很可能就是二分查找 思路:再看看题目要求,可以画出旋转之后数组中元素的大小关系: 首先,数组是具有二段性的(适配二分查…

8.1 AWS创建用户池(Amazon Cognito)和用户

AWS创建用户池(Amazon Cognito)和用户 目录一、Amazon Cognito1. 创建用户池2. 添加用户 目录 一、Amazon Cognito Amazon Cognito: https://aws.amazon.com/cognito/ Amazon Cognito 是亚马逊提供的一种身份验证、授权和用户管理服务。它为开发人员提供…

韩顺平0基础学Java——第6天

p87-p109 运算符(第四章) 四种进制 二进制用0b或0B开头 十进制略 八进制用0开头 十六进制0x或0X开头,其中的A—F不区分大小写 10转2:将这个数不断除以2,直到商为0,然后把每步得到的余数倒过来&#…

数据结构--链表进阶面试题

在链表题目开始之前我们来复习一道数组元素的逆序问题&#xff1a; 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 提示&#xff1a; 1 < nums.length < 10^5-2^31 < nums[i] < 2^31 - 10 < k < 10^5 思…

AlphaFold3(AF3)简单介绍:预测各种生物分子结构和它们之间相互作用的深度学习模型

参考: 文章地址: https://www.nature.com/articles/s41586-024-07487-w https://blog.google/technology/ai/google-deepmind-isomorphic-alphafold-3-ai-model/ AlphaFold3体验官网: https://golgi.sandbox.google.com/ 《Accurate structure prediction of biomolecula…

分享一个php常驻内存多进程任务的扩展

前言 最近在摸鱼的时候发现一个PHP常驻内存多进程任务扩展包&#xff1a;EasyTask: PHP常驻内存多进程任务管理器&#xff0c;支持定时任务(PHP resident memory multi-process task manager, supports timing tasks) (gitee.com)&#xff0c;支持php使用多线程处理任务。之前…

文心一言 VS 讯飞星火 VS chatgpt (252)-- 算法导论18.2 5题

五、因为叶结点无需指向孩子结点的指针&#xff0c;那么对同样大小的磁盘页面&#xff0c;可选用一个与内部结点不同的(更大的) t 值。请说明如何修改 B 树的创建和插人过程来处理这个变化。如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; 当我们在B树&#xff…

Kafk设计篇01(设计动机+持久化)

背景 本篇文章基于最新版本&#xff1a;kafka 3.7&#xff0c;其他版本的设计&#xff0c;请参考官网&#xff1a; https://kafka.apache.org/documentation/设计动机 任何组件都有它存在的必要&#xff0c;必然是要解决某一类问题的。我们来看看kafka设计的初衷如何。 kaf…

Python---Numpy万字总结(1)

NumPy的应用&#xff08;1&#xff09; Numpy 是一个开源的 Python 科学计算库&#xff0c;用于快速处理任意维度的数组。Numpy 支持常见的数组和矩阵操作&#xff0c;对于同样的数值计算任务&#xff0c;使用 NumPy 代码简洁&#xff0c;在性能上也远远优于原生 Python&#…

温度表程序里的公式推算

今天要改个温度表的程序&#xff0c;但是好几年没搞过了。所以程序里面的各种数字怎么算出来的都忘记了。花了半天才想起来&#xff0c;所以记录在这里&#xff0c;下次再忘记了就来翻一下。。 下次应该看到这个能想起来的把。
最新文章