【MLP-BEV(7)】深度的计算。针孔相机和鱼眼相机对于深度depth的采样一个是均匀采样,一个是最大深度均匀采样

news2024/12/26 19:57:44

文章目录

  • 1.1 问题提出
    • 1.1 看看DD3D 的深度是怎么处理的
      • 给出代码示例
    • 1.2 我们看看BEVDepth的代码

1.1 问题提出

针孔相机和鱼眼相机的投影模型和畸变模型不一样,如果对鱼眼的模型不太了解可以到我的这篇博客【鱼眼镜头11】Kannala-Brandt模型和Scaramuzza多项式模型区别,哪个更好?,以及这个系列看看。

真空相机可以对于深度depth的采样一个是均匀采样,鱼眼来说,一个是最大深度均匀采样合适。

1.1 看看DD3D 的深度是怎么处理的

在3d head 中输出了深度,看这个代码

box3d_quat, box3d_ctr, box3d_depth, box3d_size, box3d_conf, dense_depth = self.fcos3d_head(features)

特征x经过 box3d_tower 卷积层后输出

box3d_tower_out = self.box3d_tower(features)
depth = self.box3d_depth[_l](box3d_tower_out)

而这个box3d_tower就是一群3x3卷积

box3d_tower.append(
                Conv2d(
                    in_channels,
                    in_channels,
                    kernel_size=3,
                    stride=1,
                    padding=1,
                    bias=norm_layer is None,
                    norm=norm_layer,
                    activation=F.relu
                )
            )

得到后得到深度

        pixel_size = torch.norm(torch.stack([inv_intrinsics[:, 0, 0], inv_intrinsics[:, 1, 1]], dim=-1), dim=-1)
        depth = depth / (pixel_size * scale_depth_by_focal_lengths_factor)

与相机的内参(intrinsics)和深度图(depth map)的处理有关。
这两行代码的目的是根据相机的焦距和某个比例因子来调整深度图的值。这在计算机视觉和3D重建等任务中是很常见的操作。

  • inv_intrinsics: 这应该是一个表示相机内参逆矩阵的Tensor。在相机标定中,内参矩阵通常是一个3x3的矩阵,包含了焦距(fx, fy)、主点(cx, cy)和可能的扭曲因子等。但是在这里,我们只关心对角线元素,即焦距的倒数(假设fx和fy已经被取倒数)。
  • torch.stack([inv_intrinsics[:, 0, 0], inv_intrinsics[:, 1, 1]], dim=-1): 这将逆内参矩阵的第一行第一列和第二行第二列的元素(即fx和fy的倒数)沿着最后一个维度(dim=-1)堆叠成一个新的Tensor。结果是一个形状为[batch_size, 2]的Tensor,其中batch_sizeinv_intrinsics的第一个维度的大小。
  • torch.norm(..., dim=-1): 这计算了沿着最后一个维度(dim=-1)的范数。但是,由于我们堆叠的是两个值(即两个焦距的倒数),实际上计算的是这两个值的L2范数,也就是它们的平方根之和(但在这个特殊情况下,由于只有两个正数,L2范数就是它们的几何平均值)。但是,因为这里两个数都是正数并且只是简单的堆叠,所以实际上torch.norm在这里计算的是这两个值的平方根的和,这与直接取它们的平均值(或者只是取它们的和,如果后续操作是除法)在效果上可能差别不大。但几何平均值或平方根的和可能用于平滑或归一化目的。
  • pixel_size: 最终得到的Tensor包含了每个图像或图像批次的“像素大小”的某种度量,这个度量是基于焦距的倒数来计算的。
  • depth: 这是一个表示深度图的Tensor,其中每个值可能代表图像中对应像素的真实世界深度(或某种与深度相关的量度)。
  • pixel_size * scale_depth_by_focal_lengths_factor: 这部分计算了每个像素的“大小”与某个比例因子scale_depth_by_focal_lengths_factor的乘积。这个比例因子可能是用于根据焦距来缩放或调整深度值的。
  • depth / ...: 最后,原始的深度图被这个乘积除以,得到一个新的深度图,其中每个像素的深度值都根据焦距和比例因子进行了调整。这种调整可能是为了将深度图从某种原始度量(如像素单位的倒数)转换为更物理的度量(如米或厘米),或者为了校正由于相机内参引起的某种偏差。

给出代码示例

首先,我们需要确保inv_intrinsics是一个形状为[batch_size, 3, 3]的Tensor,其中包含了逆相机内参矩阵的集合,每个矩阵的(0, 0)(1, 1)位置是焦距的倒数(即1/fx1/fy)。同时,depth应该是一个形状为[batch_size, ...]的Tensor,其中包含了每个像素的深度值。

以下是代码示例,说明了如何计算pixel_size并更新depth

import torch

# 假设 inv_intrinsics 是一个形状为 [batch_size, 3, 3] 的 Tensor
# 假设 depth 是一个形状为 [batch_size, ...] 的 Tensor
# 假设 scale_depth_by_focal_lengths_factor 是一个标量或者与 depth 形状相同的 Tensor

# 示例数据
batch_size = 4  # 假设批次大小为 4
inv_intrinsics = torch.randn(batch_size, 3, 3)  # 随机生成逆内参矩阵
depth = torch.randn(batch_size, 10, 10)  # 随机生成深度图,假设每个样本的深度图大小为 10x10
scale_depth_by_focal_lengths_factor = 0.5  # 假设的比例因子

# 计算 pixel_size
# 注意:我们只关心逆内参矩阵的对角线元素,即焦距的倒数
pixel_size = torch.sqrt(inv_intrinsics[:, 0, 0] ** 2 + inv_intrinsics[:, 1, 1] ** 2)
# 或者,如果你想使用 torch.norm 来计算两个元素的 L2 范数(几何平均值),但这里更简单的方法是直接相加然后开方
# pixel_size = torch.norm(torch.stack([inv_intrinsics[:, 0, 0], inv_intrinsics[:, 1, 1]], dim=-1), dim=-1)

# 更新 depth
depth = depth / (pixel_size.unsqueeze(1).unsqueeze(1) * scale_depth_by_focal_lengths_factor)
# 注意:我们需要使用 unsqueeze 来扩展 pixel_size 的维度,以便它可以与 depth 进行广播(broadcast)

# 此时,depth 已经根据 pixel_size 和 scale_depth_by_focal_lengths_factor 进行了更新

在这个示例中,我使用了torch.sqrt来直接计算两个焦距倒数的平方和的平方根,这是更简单且等价于使用torch.norm计算L2范数的方法。同时,我使用了unsqueeze来扩展pixel_size的维度,以便它可以与depth进行广播操作。这确保了当我们将pixel_sizedepth相除时,广播规则能够正确地将pixel_size扩展到与depth相同的形状。

1.2 我们看看BEVDepth的代码

    def _forward_single_sweep(...):
        # 提取环视图片特征
        # img_feats:[1, 1, 6, 512, 16, 44]
        img_feats = self.get_cam_feats(sweep_imgs)
        source_features = img_feats[:, 0, ...]
        
        # 提取Depth以及context
        depth_feature = self._forward_depth_net(...)
        # 预测的距离分布 depth:[6, 112, 16, 44]
        depth = depth_feature[:, :self.depth_channels].softmax(1)
        # 对应论文中的 Context Feature * Depth Distribution 操作
        img_feat_with_depth = ... # 

depth 是采用depth = depth_feature[:, :self.depth_channels].softmax(1) 均匀采样,商汤采样的的是最大深度均匀采样

采样策略:

最大深度均匀采样主要关注最大深度范围内的均匀性,而不太关心近处或中间深度层次的细节。
均匀深度分布采样则在整个深度范围内追求均匀性,确保每个深度层次都得到同等的关注。

数据分布:

最大深度均匀采样可能导致近处或中间深度层次的点或像素被过度采样,而远处深度层次的点或像素被采样不足。
均匀深度分布采样则在整个深度范围内保持相对均匀的数据分布。

适用场景:

最大深度均匀采样适用于那些主要关注远处目标或障碍物检测的应用,因为远处目标往往对任务结果有更大影响。
均匀深度分布采样适用于需要全面考虑场景深度的应用,如三维重建或增强现实。

鱼眼相机镜头对光线有折射作用,以此获得更大的可视范围,越靠近边缘区域,折射率越大,生成的图片畸变程度越大。

由于畸变,使用均匀的深度分布来生成的点云大部分位于感兴趣范围以外。
在这里插入图片描述

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

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

相关文章

go语言day4 引入第三方依赖 整型和字符串转换 进制间转换 指针类型 浮点数类型 字符串类型

Golang依赖下载安装失败解决方法_安装go依赖超时怎么解决-CSDN博客 go安装依赖包(go get, go module)_go 安装依赖-CSDN博客 目录 go语言项目中如何使用第三方依赖:(前两步可以忽略) 一、安装git,安装程序…

vue启动时的错误

解决办法一:在vue.config.js中直接添加一行代码 lintOnSave:false 关闭该项目重新运行就可启动 解决办法二: 修改组件名称

步步精科技诚邀您参加2024慕尼黑上海电子展

尊敬的客户: 我们诚挚地邀请您参加即将于2024年7月8日至7月10日在上海新国际博览中心举办的2024慕尼黑上海电子展(electronica China)。此次展会汇聚了国内外优秀企业,展示从元器件到系统集成方案的完整产品链,为各行…

点云处理实战 点云平面拟合

目录 一、什么是平拟合 二、拟合步骤 三、数学原理 1、平面拟合 2、PCA过程 四、代码 一、什么是平拟合 平面拟合是指在三维空间中找到一个平面,使其尽可能接近给定的点云。最小二乘法是一种常用的拟合方法,通过最小化误差平方和来找到最优的拟合平面。 二、拟合步骤…

极验行为式验证码适配HarmonyOS 鸿蒙SDK下载

现阶段,越来越多的开发者正在积极加入鸿蒙生态系统。随着更多开发者的参与,早在去年9月,极验就成为首批拥有鸿蒙NEXT内测版本和手机系统测试机会的验证码供应商。 为了提高各开发者及企业客户集成鸿蒙版本行为验4.0的效率,方便大家…

放大招了|十亿参数大模型LLMs运行功耗仅需13W,内存使用量减少90%!

矩阵乘法(MatMul)历来是大型语言模型(LLMs)总体计算成本的主导因素,尤其在模型向更大维度嵌入和上下文长度发展时,这一成本呈指数级增长。 近期有一篇刚刚发表的论文中提出的方法完全去除了矩阵乘法操作&am…

SS8870T-3.6A 扫地机和滚刷电机的大电流电机驱动

扫地机器人已经成为现代家庭清洁的必备工具,而其中的关键部件——电机,对于其性能和用户体验起着至关重要的作用。为了确保扫地机器人的高效清洁和稳定运行,至少需要使用7个直流电机,包括行走轮、滚轮、边刷和吸尘等功能的驱动。 …

2024/5/9【贪心5/5】--代码随想录算法训练营day36|56. 合并区间、738.单调递增的数字、968.监控二叉树 (可跳过)

56. 合并区间 力扣链接 class Solution:def merge(self, intervals):result []if len(intervals) 0:return result # 区间集合为空直接返回intervals.sort(keylambda x: x[0]) # 按照区间的左边界进行排序result.append(intervals[0]) # 第一个区间可以直接放入结果集中…

专业软件测试公司分享:安全测评对于软件产品的重要性

在互联网普及的今天,随着各类软件的大规模使用,安全问题也变得愈发突出。因此,对软件进行全面的安全测评,不仅可以有效保障用户的信息安全,还能提升软件产品的信任度和市场竞争力。 安全测评对于软件产品的重要性就如…

SSL证书部署的安装环境

一、SSL证书常见的几种服务器环境 SSL证书可以安装部署在多种服务器环境中,以实现网站的HTTPS安全加密通信。正常常见的几种服务器主要分为Apache服务器、Nginx服务器、IIS服务器、Tomcat服务器。 1、Apache服务器: Apache是广泛使用的Web服务器软件。…

【C++】STL-stack_queue

目录 1、stack和queue的使用 1.1 最小栈 1.2 栈的弹出和压入序列 1.3 二叉树的层序遍历 2、stack和queue的模拟实现 2.1 适配器 2.2 deque 2.2.1 deque的成员变量 2.2.2 deque的迭代器 2.2.3 deque尾插元素 2.2.4 deque头插元素 2.2.5 下标访问 2.2.6 deque的不足 …

Vite: Esbuild的使用与其插件开发

概述 作为 Vite 的双引擎之一,Esbuild 在很多关键的构建阶段(如 依赖预编译 、 TS 语法转译 、 代码压缩 ) 让 Vite 获得了相当优异的性能,是 Vite 高性能的得力助手无论是在 Vite 的配置项还是源码实现中,都包含了不少 Esbuild 本身的基本概…

postGreSQL关系数据库介绍

什么是postGreSQL关系数据库? PostgreSQL 是一个强大的、开源的对象关系型数据库管理系统(ORDBMS)。它基于POSTQUEL查询语言的继承,提供了对SQL标准的广泛支持,并扩展了许多高级功能,如事务处理、多版本并…

被年轻人整不会的1688,终于开始反击了!

“我可以买贵的,但我不能买贵了。”成为年轻人新晋购物哲学。 最近,在豆瓣、小红书等社交媒体上出现了一种独特的消费趋势。在这些平台被种草之后,越来越多对价格敏感、注重性价比的年轻人开始挖宝“大牌平替”。他们涌入阿里巴巴旗下以批发…

配置Nginx二级域名

一、环境 (一)配置 1.服务器 linux CentOS 2.反向代理 Nginx 3.开放端口 云服务器开放端口80和443 二、域名备案 (一)腾讯云 1.腾讯云域名备案流程 备注:一级域名备案后,二级域名可以不用再备案&a…

第一个Flask程序

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 一切准备就绪,现在我们开始编写第一个Flask程序,由于是第一个Flask程序,当然要从最简单的“Hello World&#xff…

Qt Object:智能即时聊天室项目

目录 1.项目介绍 2.设计思路 3.Pro文件配置 4.项目演示 5.项目开源 项目介绍 智能即时聊天室系统(AIChatProject)是一个高效、灵活的即时通讯解决方案。它融合了百度的开源大型语言模型——文心一言,通过API接口实现深度集成。系统专为聊天和…

深入理解RLHF技术

在《LLM对齐“3H原则”》这篇文章中,我们介绍了LLM与人类对齐的“3H”原则,但是这些对齐标准主要是基于人类认知进行设计的,具有一定的主观性。因此,直接通过优化目标来建模这些对齐标准较为困难。本文将介绍基于人类反馈的强化学…

JavaScript的单线程与任务队列

目录 一、JavaScript为什么设计为单线程? 二、任务队列 👋🏻 扩展:异步队列里的宏任务与微任务 一、JavaScript为什么设计为单线程? JavaScript语言的一大特点就是单线程,换言之就是同一个时间只能做一…

三元和磷酸铁锂电池有什么区别?

现在的电动车大多都会使用到锂电池,在常见的锂电池分为两种,一种是三元锂电池另外一种是磷酸铁锂电池,面对这两种锂电池时,它们到底有什么不同? 1、材料不同 这两种锂电池的不同之处便是材料不同,磷酸铁锂…