【论文阅读】PETRv2: A Unified Framework for 3D Perception from Multi-Camera Images

news2024/11/14 2:55:57

在这里插入图片描述

Q: 论文如何解决这个问题?

A: 论文通过提出PETRv2框架来解决多相机图像的3D感知问题,具体方法包括以下几个关键点:

时间建模(Temporal Modeling):

  • 通过3D坐标对齐(3D Coordinates Alignment)实现不同帧之间的时间对齐,将上一帧的3D坐标转换到当前帧的坐标系中,以增强目标定位和速度估计。
    多任务学习(Multi-task Learning):

引入任务特定的查询(task-specific queries),

  • 例如车道检测的3D锚定车道和BEV分割的seg查询,这些查询在不同的空间中初始化,并与transformer解码器中的多视图图像特征进行交互。
    特征引导的位置编码器(Feature-guided Position Encoder, FPE):

改进原有的3D位置嵌入(3D PE)

  • 通过FPE使3D PE依赖于输入图像数据,利用2D图像特征提供的信息(如深度)来指导查询学习。
    鲁棒性分析(Robustness Analysis):

对PETRv2进行详细的鲁棒性分析

  • 考虑了包括相机外参噪声、相机缺失和时间延迟等多种噪声情况,以评估和提高系统在现实世界条件下的性能和可靠性。

结构图

在这里插入图片描述

  1. 2D backbone(例如 ResNet-50),3D 坐标是从相机截锥空间生成的,考虑到自我运动,首先通过姿态变换将前一帧t−1的三维坐标转化为当前帧t的坐标系。
  2. 将相邻帧的2D特征和3D坐标分别连接在一起,输入到特征引导位置编码器(FPE)。之后,使用 FPE 为变压器解码器生成键和值组件.
  3. 特定于任务的查询,包括从不同空间初始化的检测查询(det 查询)和分割查询(seg 查询)(lane 查询)被馈送到变压器解码器并与多视图图像特征交互。
  4. 更新后的查询被输入到特定于任务的头部以进行最终预测

Q: 论文如何解决这个问题?

A: 论文通过提出PETRv2框架来解决多相机图像的3D感知问题,具体方法包括以下几个关键点:

时间建模(Temporal Modeling):

通过3D坐标对齐(3D Coordinates Alignment)实现不同帧之间的时间对齐,将上一帧的3D坐标转换到当前帧的坐标系中,以增强目标定位和速度估计。

在这里插入图片描述

P 3 d t = T t − 1 t P 3 d t − 1 \bm{P^t_{3d}} = \bm{T^t_{t-1}}\bm{P^{t-1}_{3d}} P3dt=Tt1tP3dt1

多任务学习(Multi-task Learning):

引入任务特定的查询(task-specific queries),例如车道检测的3D锚定车道和BEV分割的seg查询,这些查询在不同的空间中初始化,并与transformer解码器中的多视图图像特征进行交互。

3D object detection
在这里插入图片描述
Det Queries: 3D Anchor Points (~1500)+ MLP

Segmentation
在这里插入图片描述
Seg Queries:

  • 我们引入了用于 BEV 分割的 seg 查询,每个 seg 查询对应于一个特定的Patch(例如,BEV map ( 25 × 25 像素)。
  • seg 查询在 BEV 空间中使用固定的锚点进行初始化,类似于 PETR 中检测查询 (det 查询) 的生成。然后使用具有两个线性层的简单 MLP 将这些锚点投影到 seg Queries。

特征引导的位置编码器(Feature-guided Position Encoder, FPE):

改进原有的3D位置嵌入(3D PE),通过FPE使3D PE依赖于输入图像数据,利用2D图像特征提供的信息(如深度)来指导查询学习。
在这里插入图片描述

P E i 3 d ( t ) = ξ ( F i ( t ) ) ∗ ψ ( P l ( t ) i ( t ) ) \bm{{PE}^{3d}_i (t)} = \xi(\bm{F_i(t)}) * \psi(\bm{P_{l(t)}^i (t)}) PEi3d(t)=ξ(Fi(t))ψ(Pl(t)i(t))
ξ : MLP + sigmoid function
ψ(.):一个简单的多层感知(MLP)
key: 2D feature + 3D PE
value: 2D Feature

def position_embeding(self, img_feats, img_metas, masks=None):
    eps = 1e-5  # 用于避免除零错误的极小值
    
    # 获取填充后的图片高度和宽度 (pad_h, pad_w),以及其它相关信息
    pad_h, pad_w, _ = img_metas[0]['pad_shape'][0]
    
    # 获取特征图的形状信息:B(批次大小),N(图像数量),C(通道数),H(高度),W(宽度)
    B, N, C, H, W = img_feats[self.position_level].shape
    
    # 计算每个像素点在填充后图像中的实际高度坐标和宽度坐标
    coords_h = torch.arange(H, device=img_feats[0].device).float() * pad_h / H
    coords_w = torch.arange(W, device=img_feats[0].device).float() * pad_w / W

    if self.LID:
        # 如果使用 LID 方法计算深度坐标
        index = torch.arange(start=0, end=self.depth_num, step=1, device=img_feats[0].device).float()
        index_1 = index + 1
        bin_size = (self.position_range[3] - self.depth_start) / (self.depth_num * (1 + self.depth_num))
        coords_d = self.depth_start + bin_size * index * index_1
    else:
        # 否则,直接计算深度坐标
        index = torch.arange(start=0, end=self.depth_num, step=1, device=img_feats[0].device).float()
        bin_size = (self.position_range[3] - self.depth_start) / self.depth_num
        coords_d = self.depth_start + bin_size * index

    # 获取深度坐标的数量 D
    D = coords_d.shape[0]
    
    # 生成坐标网格,并将其维度排列为 W, H, D, 3
    coords = torch.stack(torch.meshgrid([coords_w, coords_h, coords_d])).permute(1, 2, 3, 0)
    
    # 添加第四维坐标(均为1),形成 W, H, D, 4
    coords = torch.cat((coords, torch.ones_like(coords[..., :1])), -1)
    
    # 计算 x 和 y 坐标的变换,确保 z 坐标不为零
    coords[..., :2] = coords[..., :2] * torch.maximum(coords[..., 2:3], torch.ones_like(coords[..., 2:3])*eps)

    # 生成 img2lidar 矩阵列表
    img2lidars = []
    for img_meta in img_metas:
        img2lidar = []
        for i in range(len(img_meta['lidar2img'])):
            # 计算每个 lidar2img 矩阵的逆矩阵
            img2lidar.append(np.linalg.inv(img_meta['lidar2img'][i]))
        img2lidars.append(np.asarray(img2lidar))
    
    # 将 img2lidar 列表转换为 numpy 数组
    img2lidars = np.asarray(img2lidars)
    
    # 将 numpy 数组转换为 tensor,形状为 (B, N, 4, 4)
    img2lidars = coords.new_tensor(img2lidars)

    # 调整 coords 和 img2lidars 的维度,并进行重复操作
    coords = coords.view(1, 1, W, H, D, 4, 1).repeat(B, N, 1, 1, 1, 1, 1)
    img2lidars = img2lidars.view(B, N, 1, 1, 1, 4, 4).repeat(1, 1, W, H, D, 1, 1)
    
    # 计算3D坐标,将坐标从齐次坐标变换到3D坐标
    coords3d = torch.matmul(img2lidars, coords).squeeze(-1)[..., :3]
    
    # 对3D坐标进行归一化
    coords3d[..., 0:1] = (coords3d[..., 0:1] - self.position_range[0]) / (self.position_range[3] - self.position_range[0])
    coords3d[..., 1:2] = (coords3d[..., 1:2] - self.position_range[1]) / (self.position_range[4] - self.position_range[1])
    coords3d[..., 2:3] = (coords3d[..., 2:3] - self.position_range[2]) / (self.position_range[5] - self.position_range[2])

    # 创建掩码,检查是否有坐标超出范围
    coords_mask = (coords3d > 1.0) | (coords3d < 0.0)
    
    # 计算掩码,若超过一半的深度坐标超出范围,则设置掩码
    coords_mask = coords_mask.flatten(-2).sum(-1) > (D * 0.5)
    
    # 合并输入掩码和计算的坐标掩码
    coords_mask = masks | coords_mask.permute(0, 1, 3, 2)
    
    # 调整 coords3d 的维度
    coords3d = coords3d.permute(0, 1, 4, 5, 3, 2).contiguous().view(B*N, -1, H, W)
    
    # 计算逆sigmoid
    coords3d = inverse_sigmoid(coords3d)
    
    # 计算位置嵌入
    coords_position_embeding = self.position_encoder(coords3d)
    
    # 返回位置嵌入和掩码
    return coords_position_embeding.view(B, N, self.embed_dims, H, W), coords_mask

鲁棒性分析(Robustness Analysis):

对PETRv2进行详细的鲁棒性分析,考虑了包括相机外参噪声、相机缺失和时间延迟等多种噪声情况,以评估和提高系统在现实世界条件下的性能和可靠性。
在这里插入图片描述
外参误差:外参误差在现实中很常见,例如汽车碰撞引起的相机抖动或环境力的相机偏移
Rmax = M表示三个轴的最大角度为M。
在这里插入图片描述

相机丢失:当一台相机发生故障或被遮挡时,就会发生相机图像未命中。
在这里插入图片描述

相机时间延迟:由于相机曝光时间,相机时间延迟也是一个挑战,尤其是在夜间。

T ≈ 0.083s
在这里插入图片描述
3D object detection

在这里插入图片描述

BEV segmentation

在这里插入图片描述
3D lane detection

在这里插入图片描述

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

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

相关文章

AI应用开发前景与目标

前景与目标 什么是AIGC AIGC最基本的能力是生成内容&#xff0c;包括文本、图像、视频、代码、3D内容或者几种媒介类型转换组合 形成的“多模态内容”。生成算法、预训练模型、多模态等技术累积融合&#xff0c;以及深度模型方面的 技术创新&#xff0c;共同催生了AIGC的大爆…

一篇文章教你如何在Android上使用QPython高效编程

导语&#xff1a;你是否想在Android设备上体验Python编程的乐趣&#xff1f;QPython是一款强大的Python脚本引擎&#xff0c;让你在手机上也能轻松编写和运行Python代码。本文将带你了解QPython的使用方法&#xff0c;让你随时随地开启编程之旅&#xff01; 一、认识QPython Q…

File 34

package File;import java.awt.*; import java.io.File;public class file1 {public static void main(String[] args) {//创建FILE对象&#xff0c;指代某个具体的文件//路径分隔符File f1new File("C:/Users/SUI/Desktop/kaishi/nih.txt");// File f1new File(&quo…

推荐4款比转转大师还好用的专业数据恢复软件。

数据已经成为我们生活和工作中不可或缺的一部分&#xff1b;然而我们在很多的场景当中都会导致数据丢失&#xff1b;于是数据恢复工具便成了一些人的常用工具。很多人都知道转转大师数据恢复软件&#xff0c;但是也有其他的恢复软件也很好用。 1、福昕恢复 直通车&#xff1a;…

ArkTS通用属性

目录 一、尺寸设置 宽高&#xff0c;外边距&#xff0c;内边距&#xff0c;尺寸size layoutWeight constraintSize 二、位置设置 align direction position offset 使用Edge方式position,offset 三、布局约束 aspectRatio displayPriority 四、Flex布局 flexBas…

数字转罗马字符

import java.util.Scanner;/*** author gyf* ClassName Test* Date 2024/7/31 17:14* Version V1.0* Description : 方法一*/ public class Test {public static void main(String[] args) {Scanner scanner new Scanner(System.in);System.out.println("请输入一个字符串…

php类与对象

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文主要整理php类与对象相关的知识点 适合有编程基础的人观看 因为我这个也是整理第n语言&#xff0c;这些老套的概念就不再多啰嗦了。 直接整理相应的语法 感觉把php当第一语言学的人不太多了 快速理解类与对…

MyBatis的example.createCriteria()方法学习记录

目录 一、mapper的crud方法:1. insert方法insert(User user)insertSelective(User user) 2. select方法selectByPrimaryKey(id)selectByExample(example)selectCountByExample(example) 3. update方法updateByPrimaryKey(User user)updateByPrimaryKeySelective(User user)upda…

从零开始的MicroPython(六)ADC

上一篇&#xff1a;PWM 文章目录 ADC是什么ESP32的ADC代码 ADC是什么 ADC的英文全称是Analog / Digital Converter&#xff0c;是将模拟信号转换为数字信号的转换器&#xff0c;ADC是单片机读取传感器信号的常见方式。 我们日常生活中的信号&#xff0c;例如光照强度&#xf…

机器学习练手(三):基于决策树的iris 多分类和波士顿房价预测

总结&#xff1a;本文为和鲸python 可视化探索训练营资料整理而来&#xff0c;加入了自己的理解&#xff08;by GPT4o&#xff09; 原活动链接 原作者&#xff1a;vgbhfive&#xff0c;多年风控引擎研发及金融模型开发经验&#xff0c;现任某公司风控研发工程师&#xff0c;对…

python通过pyautogui自动给微信聊天窗口发消息

使用py脚本自动给聊天窗口发消息 1.突然的自我2.编写脚本玩一把i.先获取窗口位置ii.模拟聊天iii.疗效不错呢 1.突然的自我 突然想到pyautogui可以做那么事情&#xff0c; 那么是不是可以模拟聊天呢&#xff0c;如果结合现在的大模型chatGPT一边问然后得到结果一边自动和别人聊…

一文读懂新版Nacos的使用方式

文章目录 什么是 NacosNacos 架构Nacos 的本地启动 构建提供者 provider-nacos-8081搭建环境编写配置文件 application.yaml构建数据库编写业务实体类控制器类逻辑层与数据层接口 模块结构 构建消费者 consumer-nacos-8080搭建环境编写 yaml 文件配置编写业务编写配置类编写 Co…

Linux系统之NFS服务配置

准备工作 克隆两台linux&#xff0c;并更改其Mac地址&#xff0c;作为NFS客户端&#xff1b;将服务器更名为学号nfsserver&#xff0c;配置IP地址为192.168.学号.1 将客户端Client1更名为学号client1&#xff0c;配置IP地址为192.168.学号.2 将客户端Client2更名为学号clien…

达梦数据库一体机在宜昌市财政局上线了!

财政作为国家治理的基础和重要支柱&#xff0c;其数字化转型已成为构建现代财政制度的必由之路&#xff0c;引领着财政管理体系向更高效、更智能的方向迈进。 达梦数据全面助力财政信息化转型与智能化发展&#xff0c;采用 DAMEGN PAI I 系列数据库一体机&#xff0c;为宜昌市财…

python实现图像分割算法3

python实现区域增长算法 算法原理基本步骤数学模型Python实现详细解释优缺点应用领域区域增长算法是一种经典的图像分割技术,它的目标是将图像划分为多个互不重叠的区域。该算法通过迭代地合并与种子区域相似的邻域像素来实现分割。区域增长算法通常用于需要精确分割的场景,如…

css实现文字根据条件渐变

body 选择器 body { padding: 50vh 0; text-align: center; font-size: 6em; } padding: 50vh 0; 设置了body的上下内边距为视口高度的50%&#xff0c;左右内边距为0。text-align: center; 使得body内的文本内容居中显示。font-size: 6em; 设置了字体大小为当前字体尺寸的6倍…

Solana 自建节点搭建教程:手把手教你成为区块链网络的重要一员

区块链技术正在迅速改变世界&#xff0c;而Solana作为新一代高性能公链&#xff0c;以其出色的性能和低廉的交易费用吸引了众多开发者和用户。如果你想成为Solana生态系统的一部分&#xff0c;搭建自己的Solana节点是一个绝佳的选择。本教程将详细介绍如何一步步搭建Solana自建…

MyBatis 如何通过拦截器修改 SQL

目录 1. 实现Interceptor接口2. 注册配置文件 假如我们想实现多租户&#xff0c;或者在某些 SQL 后面自动拼接查询条件。在开发过程中大部分场景可能都是一个查询写一个 SQL 去处理&#xff0c;我们如果想修改最终 SQL 可以通过修改各个 mapper.xml 中的 SQL 来处理。 但实际过…

【C语言】结构体内存布局解析——字节对齐

&#x1f984;个人主页:小米里的大麦-CSDN博客 &#x1f38f;所属专栏:https://blog.csdn.net/huangcancan666/category_12718530.html &#x1f381;代码托管:黄灿灿 (huang-cancan-xbc) - Gitee.com ⚙️操作环境:Visual Studio 2022 目录 一、引言 二、什么是字节对齐&…

开源个性化自托管服务仪表板:Dashy

**Dashy&#xff1a;**一站式管理&#xff0c;个性化展现- 精选真开源&#xff0c;释放新价值。 概览 Dashy是一个创新的自托管仪表板解决方案&#xff0c;旨在为用户提供一个集中管理多个在线服务的平台。通过直观的界面设计&#xff0c;Dashy允许用户快速访问他们的自托管应…