基于深度学习的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"] # 指出哪些地方不用计算lossoutputs = 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的lossloss.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 = refineself.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 mapsfeatures = [self.feature(img) for img in imgs] # 会跑3次, 1张ref,两张srcref_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_volumefor src_fea, src_proj in zip(src_features, src_projs):# warpped featureswarped_volume = homo_warping(src_fea, src_proj, ref_proj, depth_values)if self.training:volume_sum = volume_sum + warped_volumevolume_sq_sum = volume_sq_sum + warped_volume ** 2else: # 测试模式【分辨率率很大,要节省内存】# TODO: this is only a temporal solution to save memory, better way?volume_sum += warped_volumevolume_sq_sum += warped_volume.pow_(2)  # the memory of warped_volume has been modifieddel 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 regularizationcost_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 refinementif 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.mzph.cn/bicheng/8889.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

详解基于 RAG 的 txt2sql 全过程

前文 本文使用通义千问大模型和 ChromaDB 向量数据库来实现一个完整的 text2sql 的项目,并基于实际的业务进行效果的展示。 准备 在进行项目之前需要准备下面主要的内容: python 环境通义千问 qwen-max 模型的 api-keyChromaDB 向量数据库acge_text_…

Linux-笔记 uboot修改设备树

1. FDT介绍 扁平设备树(Flattened Device Tree,FDT),也叫平坦设备树,是设备树的一种二进制表示形式,提高了在嵌入式系统中的传输和解析效率; 2. 在U-Boot中使用FDT 2.1. 进入U-Boot 开发板上…

OpenCV 入门(四)—— 车牌号识别

OpenCV 入门系列: OpenCV 入门(一)—— OpenCV 基础 OpenCV 入门(二)—— 车牌定位 OpenCV 入门(三)—— 车牌筛选 OpenCV 入门(四)—— 车牌号识别 OpenCV 入门&#xf…

【论文阅读】VMamba: Visual State Space Model

VMamba:视觉状态空间模型 code:https://github.com/MzeroMiko/VMamba Background ​ CNN拥有线性复杂度因而可以处理高分辨率的图像,而ViT在拟合能力方面超过了CNN,但ViT是二次复杂度,在处理高分辨率图像时计算开销较大。ViT通过…

Wappalyzer指纹识别下载安装使用教程,图文教程(超详细)

「作者简介」:2022年北京冬奥会网络安全中国代表队,CSDN Top100,就职奇安信多年,以实战工作为基础对安全知识体系进行总结与归纳,著作适用于快速入门的 《网络安全自学教程》,内容涵盖系统安全、信息收集等…

Windows平台通过MobaXterm远程登录安装在VMware上的Linux系统(CentOS)

MobaXterm是一个功能强大的远程计算工具,它提供了一个综合的远程终端和图形化的X11服务器。MobaXterm旨在简化远程计算任务,提供了许多有用的功能,使远程访问和管理远程服务器变得更加方便,它提供了一个强大的终端模拟器&#xff…

C语言进程A调用进程B中定义的函数

我想要实现2个独立的进程,A持续运行,B随时运行,B的函数通过A中得条件触发。 因为B中的函数触发后,还会执行B中的其他相关函数,所以单独的把B的触发函数写成动态链接库在A中调用是不行的。B是一个独立的逻辑&#xff0…

钉钉开放平台创建企业内部H5微应用或者小程序

前言: 在当今企业数字化转型的浪潮中,创建企业内部H5微应用或小程序已成为提升工作效率和促进内部沟通的重要举措。发话不多说本文将介绍如何利用钉钉平台快速创建这些应用,让企业内部的工作更加便捷高效。 步骤 1.在浏览器打开链接…

【解决】Android APK文件安装时 已包含数字签名相同APP问题

引言 在开发Android程序过程中,编译好的APK文件,安装至Android手机时,有时会报 包含数字签名相同的APP 然后无法安装的问题,这可能是之前安装过同签名的APP,但是如果不知道哪个是,无法有效卸载,…

ESD静电问题 | 更换接口芯片

【转发微信公众号:EMC容冠电磁】

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

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

用得助全媒体呼叫中心,让AI落到实处帮品牌做营销

怎么让人工智能落到实处的帮助到我们?我们今天来讲讲中关村科金得助全媒体呼叫中心是怎么让AI帮品牌。 这次聊的案例是知名的护肤品牌,该品牌在中国功能性护肤品市场占有率达到20.5%,这么高的市场占有率客户的咨询量也是非常庞大的&#xff0…

C++ 继承篇

面向对象语言的三大特性:封装,继承和多态 根据目前学到的知识,对于封装的理解,大致有两层: 将数据和方法封装,不想让外面看到用private/protected修饰,想让外面看到用public修饰类型的行为不满…

elasticsearch文档读写原理大致分析一下

文档写简介 客户端通过hash选择一个node发送请求,专业术语叫做协调节点 协调节点会对document进行路由,将请求转发给对应的primary shard primary shard在处理完数据后,会将document 同步到所有replica shard 协调节点将处理结果返回给…

[嵌入式系统-71]:RT-Thread-组件:日志管理系统ulog,让运行过程可追溯

目录 ulog 日志 1. ulog 简介 ulog 架构 配置选项 日志级别 日志标签 2. 日志初始化 初始化 去初始化 3. 日志输出 API 4. 日志使用示例 使用示例 在中断 ISR 中使用 同步模式(Synchronous Mode) 异步模式(Asynchronous Mode&…

【视频/图像数据格式】基本视频/图像数据格式

基本视频/图像数据格式 1.概述2.视频图像数据格式2.1 yuv420p2.2 yuv422p2.3 yuv444p2.4 RGB格式2.5 BMP格式 3.格式转换3.1 RGB24转换为YUV420P 4.视频图像评价指标4.1 MSE4.2 PSNR 参考: 雷霄骅博士博客: http://t.csdnimg.cn/kl2jLhttp://t.csdnimg.…

蓝桥杯EDA客观题

目录 前言 一、PCB类知识点和题目分析 1.电阻 2.电容 3.封装类 4.单位转换类 5.电路板结构类 6.PCB绘制规则 7.立创软件 8.PCB硬件 线性电源和开关电源 二、数电知识点和题目分析 1.门电路 2.逻辑代数 3.组合逻辑电路 4.触发器 5.时序逻辑电路 6.其他 三、模…

vue3+ts之el-tooltip换行显示内容

<el-tooltip placement"top-end"><div slot"content" class"tips"><el-button type"primary" click"exportData">导出</el-button></div><template #content><span class"cont…

【项目实战】使用Yolov8 + tesseract 实现身份证信息解析(OCR) + 输入可为图片或者pdf + 完整代码 + 整体方案 + 全网首发

本项目可用于实验,毕业设计参考等。整体效果如下所示: 说明:图片来源于网络,如有侵权,请联系作者删除。 目录 一 数据集制作

C语言--带环链表问题

继续学习 一、判断链表是否带环 141. 环形链表 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a;用快慢指针&#xff0c;快指针走两步&#xff0c;慢指针走一步&#xff0c;当慢指针走一半快指针进到环里 当慢指针进环&#xff0c;快指针已经在环中转了一会儿了 | |…