DETR3D的关键:feature_sampling(3D到2D的图像特征采样)

2023-05-16

流程:坐标转换->归一化坐标->grid_sample()方法->mask

坐标转换->归一化坐标->grid_sample()方法

# 特征采样部分, Input queries from different level. Each element has shape [bs, embed_dims, h, w] 也就是[4, bs, embed_dims, h, w]
# 特征采样部分, Input queries from different level. Each element has shape [bs, embed_dims, h, w] 也就是[4, bs, embed_dims, h, w]
def feature_sampling(mlvl_feats, reference_points, pc_range, img_metas):
    lidar2img = []
    # lidar2img:3D坐标以lidar为中心,求出3D点到img的转换关系也就是求出lidar到img的转换关系
    for img_meta in img_metas:
        lidar2img.append(img_meta['lidar2img'])
    lidar2img = np.asarray(lidar2img)
    # N = 6,referrence_points:[bs, num_query, 3]
    lidar2img = reference_points.new_tensor(lidar2img) # (B, N, 4, 4)
    reference_points = reference_points.clone()
    reference_points_3d = reference_points.clone()
    #  还原归一化后的[x,y,z]
    reference_points[..., 0:1] = reference_points[..., 0:1]*(pc_range[3] - pc_range[0]) + pc_range[0]
    reference_points[..., 1:2] = reference_points[..., 1:2]*(pc_range[4] - pc_range[1]) + pc_range[1]
    reference_points[..., 2:3] = reference_points[..., 2:3]*(pc_range[5] - pc_range[2]) + pc_range[2]
    # reference_points [bs, num_query, 3] -> [bs, num_query, 4]
    reference_points = torch.cat((reference_points, torch.ones_like(reference_points[..., :1])), -1)
    B, num_query = reference_points.size()[:2]
    # num_cam = 6
    num_cam = lidar2img.size(1)
    # from [b,1,num_query,4] to [b,num_cam,num_query, 4, 1],将相同的query投影到每个camera中,因为每个query对应的是lidar坐标系的三维点
    reference_points = reference_points.view(B, 1, num_query, 4).repeat(1, num_cam, 1, 1).unsqueeze(-1)
    # shape:[b, num_cam, num_query, 4, 4]
    lidar2img = lidar2img.view(B, num_cam, 1, 4, 4).repeat(1, 1, num_query, 1, 1)

    # project 3d -> 2d
    # shape:[b, num_cam, num_query, 4],计算得到每个三维点在每个相机的投影
    reference_points_cam = torch.matmul(lidar2img, reference_points).squeeze(-1)
    eps = 1e-5 # eps作为无穷小数
    mask = (reference_points_cam[..., 2:3] > eps)

    # 避免除以0的问题, reference_points_cam[..., 2:3]指的是深度,要获得z*[x,y,1,1] = cam_intrinsics[4x4] * [x,y,z,1] -> z*[x,y,1,1] / z -> [x,y,1,1]
    reference_points_cam = reference_points_cam[..., 0:2] / torch.maximum(
        reference_points_cam[..., 2:3], torch.ones_like(reference_points_cam[..., 2:3])*eps)
    # 归一化[0,1]
    reference_points_cam[..., 0] /= img_metas[0]['img_shape'][0][1]
    reference_points_cam[..., 1] /= img_metas[0]['img_shape'][0][0]

    # 确保reference在[-1, 1]之间,原来在[0,1]之间
    reference_points_cam = (reference_points_cam - 0.5) * 2

    # 对所有不在grid内的点,也就是投影在某个cam之外的点进行mask
    mask = (mask & (reference_points_cam[..., 0:1] > -1.0) 
                 & (reference_points_cam[..., 0:1] < 1.0) 
                 & (reference_points_cam[..., 1:2] > -1.0) 
                 & (reference_points_cam[..., 1:2] < 1.0))
    mask = mask.view(B, num_cam, 1, num_query, 1, 1).permute(0, 2, 3, 1, 4, 5) # [bs, 1, n_q, n_c, 1, 1]
    mask = torch.nan_to_num(mask)
    sampled_feats = []
    # 对四个特征层分别求出线性插值后的feature,其中N为num_query, [4, bs, embed_dims, h, w]
    for lvl, feat in enumerate(mlvl_feats):
        B, N, C, H, W = feat.size() # (num_key, bs, embed_dims)
        # N=num_cam
        feat = feat.view(B*N, C, H, W)
        # [b,num_cam,num_query,2] -> [b, num_cam, num_query, 1, 2]
        reference_points_cam_lvl = reference_points_cam.view(B*N, num_query, 1, 2)
        # F.grid_sample return:[b*n,c,num_query,1]每个query对应着一个grid采样(bilinear incorparation)后返回的值
        sampled_feat = F.grid_sample(feat, reference_points_cam_lvl)
        # b,c,n_q,n,1
        sampled_feat = sampled_feat.view(B, N, C, num_query, 1).permute(0, 2, 3, 1, 4)
        sampled_feats.append(sampled_feat)
    # [b,n,c,num_query,len(mlvl_feats)]
    sampled_feats = torch.stack(sampled_feats, -1)
    sampled_feats = sampled_feats.view(B, C, num_query, num_cam,  1, len(mlvl_feats)) 
    return reference_points_3d, sampled_feats, mask

mask

attention_weights = attention_weights.sigmoid() * mask
@ATTENTION.register_module()
class Detr3DCrossAtten(BaseModule):

    def __init__(self,
                 embed_dims=256,
                 num_heads=8,
                 num_levels=4,
                 num_points=5,
                 num_cams=6,
                 im2col_step=64,
                 pc_range=None,
                 dropout=0.1,
                 norm_cfg=None,
                 init_cfg=None,
                 batch_first=False):
        super(Detr3DCrossAtten, self).__init__(init_cfg)

    def forward(self,
                query,
                key,
                value,
                residual=None,
                query_pos=None,
                key_padding_mask=None,
                reference_points=None,
                spatial_shapes=None,
                level_start_index=None,
                **kwargs):
        # 输入的是query和reference points
        if key is None:
            key = query
        if value is None:
            value = key

        if residual is None:
            inp_residual = query
        if query_pos is not None:
            query = query + query_pos

        # change to (bs, num_query, embed_dims)
        query = query.permute(1, 0, 2)

        bs, num_query, _ = query.size()

        attention_weights = self.attention_weights(query).view(
            bs, 1, num_query, self.num_cams, self.num_points, self.num_levels)
        
        # shape:(B, N, C, H, W), [bs, num_query, 3]
        reference_points_3d, output, mask = feature_sampling(
            value, reference_points, self.pc_range, kwargs['img_metas'])
        output = torch.nan_to_num(output)
        mask = torch.nan_to_num(mask)

        # 对每个camera中投影在之外的点进行mask
        attention_weights = attention_weights.sigmoid() * mask
        output = output * attention_weights
        output = output.sum(-1).sum(-1).sum(-1) # sum后缩减三个维度:shape:[bs, c, num_query]
        output = output.permute(2, 0, 1) # [num_query, bs, c]
        
        output = self.output_proj(output) # (num_query, bs, embed_dims),将reference3d的dim转换到256
        # output作为fetch的feature,与经过encoder后的query、原始query直接相加作为refinement query
        pos_feat = self.position_encoder(inverse_sigmoid(reference_points_3d)).permute(1, 0, 2)

        return self.dropout(output) + inp_residual + pos_feat
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

DETR3D的关键:feature_sampling(3D到2D的图像特征采样) 的相关文章

  • 蚁群算法实现三维避障轨迹规划(Matlab)

    关于蚁群算法 其实大多数优化算法都是 试错 的过程 xff0c 不同的是如何利用在 试错 过程中得到的经验 蚁群算法在 试错 的过程中通过留下信息素对未来的试错过程加以提示 xff0c 从而保证一定的收敛性 代码分析 我写了一份matlab
  • CAN总线基础知识(2)——CAN的数据帧

    CAN总线基础知识 xff08 2 xff09 CAN结构上由7个段组成 xff08 仲裁段包括上篇说的can id 和 RTR xff09 xff0c 如图所示 其中根据仲裁段ID码长度的不同 xff0c 分为标准帧 xff08 CAN2
  • 一种通过printf打印的调试程序的方法

    我们在写代码的时候 xff0c 有时候需要调试程序的时候 xff0c 对于初学者 xff0c 可以通过简单的增加printf函数打印 xff0c 这样能够来跟踪程序的踪迹 xff0c 举个很简单的代码 xff1a include lt st
  • 详解Unity中的Nav Mesh新特性|导航寻路系统 (二)

    前言 第一篇我们简要概述了新版NavMesh的一些新增功能 xff0c 以及旧版的对比 本篇我们来讲一讲NavMeshSurface NavMeshLink这两个组件的参数以及如何应用 xff0c 接下来就进入正题吧 本系列提要 Unity
  • ROS安装包--rqt

    ROS安装包 rqt 安装命令刷新缓存 安装命令 sudo apt get install ros kinetic rqt sudo apt get install ros kinetic rqt common plugins sudo a
  • 【无标题】

    ROS自定义话题传输出现md5sum错误 问题描述 提前从一个程序中使用rosbag record命令对某一话题进行了录制 xff0c 之后用rostopic echo命令确定了录入了信息 但是给另一程序发布的时候 xff0c 终端报错 x
  • 关于CAN标准帧和扩展帧为什么分别占位是11bit和29bit

    关于CAN标准帧和扩展帧为什么分别占位是11bit和29bit 文章目录 关于CAN标准帧和扩展帧为什么分别占位是11bit和29bit前言一 关于标准帧二 关于扩展帧总结写在结尾 前言 之前一直没明白CAN标准帧和扩展帧为什么分别占位是1
  • 旭日x3派个人配置总结(ubuntu server + xrdp)

    旭日x3派基本设置 旭日x3派使用文档 首发 多方位玩转旭日x3派 XRDP 43 Xface4远程桌面设置 安装xrdp并解决闪退 黑屏问题 ROS2 Foxy配置 解决 Failed to connect to raw githubus
  • 思岚S2激光雷达1—初次连接

    1 去官网下载Robostudio xff0c 我这里是windows http www slamtec com robostudio 2 连接激光雷达 3 去官网下载SDK 4 在SDK文件夹里的tools里面找驱动下载驱动 5 电脑成功
  • ZED2双目相机1:标定

    一 下载及安装 xff08 1 xff09 按照下面这个链接 xff1a https blog csdn net TengYun zhang article details 123072847 下载完是这样的 xff1a xff08 2 x
  • ZED2双目相机2:畸变矫正

    1 运行ZED2相机 xff08 注意是在ZED WS工作空间里 xff09 xff08 1 xff09 关闭anconda xff08 如果有的话 xff09 xff1a conda deactivate span class token
  • 用android代码实现一个可以万能播放器

    要实现一个万能播放器需要使用多媒体库 xff0c 可以使用Android自带的MediaPlayer类以及ExoPlayer库 以下是一个简单的示例代码 xff1a 在XML布局文件中添加一个SurfaceView和几个按钮 xff1a s
  • 初出茅庐的小李第108篇博客二进制打印

    二进制打印介绍 C语言在格式化打印的时候有很多格式控制 xff0c 比如十进制打印用 d输出 xff0c 十六进制用 x输出 xff0c 八进制用 o格式输出 xff0c 但是当我们期望看一个数据的二进制的时候就必须借助计算器或者其他比较不
  • QGroundControl 自定义命令小工具的使用

    Custom Command Widgets 不用编译qgc的源码 xff0c 仅仅需要编写一个QML UIs文件这个小工具窗口可以被加载 xff0c 并且从重启之后仍然可以使用 xff0c 而且不受操作系统的限制主要有两个用途 xff11
  • HTTP请求方式GET和POST代码示例

    HTTP请求方式GET和POST代码示例 1 HTTP名词解释1 2 HTTP传输方式1 2 1GET名词解释1 2 1POST名词解释 1 3Http中Post 和Get代码实现 1 HTTP名词解释 HTTP大名叫做超文本传输协议 xf
  • Postman工具常见操作

    Postman常见操作 1 新建GET或POST请求 xff08 1 xff09 打开Postman xff0c 选择File gt New xff08 2 xff09 选择Request xff0c 进入 xff08 3 xff09 输入
  • Ubuntu18.04+ROS melodic 跑通VINS-MONO的一些踩坑记录

    VINS MONO的一些踩坑记录 0 本机环境 笔者的环境为Ubuntu 18 04 43 ros melodic 43 opencv 4 1 1 43 Eigen 3 3 9 43 ceres solver 1 14 跟VINS MONO
  • GPIO库函数开发和寄存器开发的区别

    函数原型为 xff1a void GPIO SetBits GPIO TypeDef GPIOx uint16 t GPIO Pin xff08 1 xff09 gt 箭头操作符要求左操作数必须是个指针GPIO TypeDef GPIOx
  • C++ 编译

    C 43 43 编译原理 参考博客 https www cnblogs com kevinWu7 p 10163443 html C C 43 43 编译就是要将C C 43 43 的代码映射到相应的机器码 xff0c 以及讨论其中的内存管
  • STM32串口中断的方式发送

    我将其改为真正的中断发送 步骤一 xff1a 初始化GPIO GPIO InitTypeDef GPIO InitStructure GPIO InitStructure GPIO Pin 61 GPIO Pin 10 LED1 PC10

随机推荐

  • 什么是大端小端 and 如何判断大端小端

    1 为什么会有大小端模式之分呢 xff1f 这是因为在计算机系统中 xff0c 我们是以字节为单位的 xff0c 每个地址单元都对应着一个字节 xff0c 一个字节为8bit 但是在C语言中除了8bit的char之外 xff0c 还有16b
  • python中串口通信的步骤及实现

    python内置的库函数确实很强大 xff0c serial库中包含了串口通信所用到的一些函数 本文用python实现了串口的一种简单通信 代码实现 xff1a span class token keyword import span se
  • 结构体作用(STM32)

    结构体作用 xff08 STM32 xff09 来源 xff1a 正点原子 MDK 中很多地方使用结构体以及结构体指针 xff0c 下面总结一下其使用结构体的主要作用 1 结构体是将不同的数据类型整合为一个有机整体 xff0c 方便数据管理
  • 两轴舵机云台的一点实践

    两轴舵机云台的一点实践 效果演示硬件使用情况定时器中断代码计算机体系下的云台角代码舵机控制代码工程源码下载 简介 xff1a 为了学习姿态解算相关知识 xff0c 最近做了一个作品 xff0c 模仿炮塔跟随系统 xff0c 用陀螺仪使两个舵
  • 栈的使用场景

    当数据的处理顺序要与接收顺序相反时 xff08 LIFO xff09 last in first out xff0c 就可以用栈 像文字处理器的 撤销 动作 xff0c 或网络应用程序的函数调用 xff0c 你应该都会需要栈来实现 在处理括
  • 如何重装Ubuntu 系统

    如果你弄坏了你的 Ubuntu 系统 xff0c 并尝试了很多方法来修复 xff0c 你最终放弃并采取简单的方法 xff1a 重新安装 Ubuntu 我们一直遇到这样一种情况 xff0c 重新安装 Linux 似乎比找出问题并解决来得更好
  • 精华:QinQ基础,VLAN双层TAG

    QinQ 是 802 1Q in 802 1Q 的简称 xff0c 是基于 IEEE 802 1Q 技术的一种比较简单的二层 VPN 协议 QinQ简介 IEEE 802 1Q 定义的 VLAN ID 域有 12 个比特 xff0c 最多可
  • Ubuntu更换默认终端

    终端是任何Linux系统的关键部分 它允许您通过shell访问Linux系统 虽说现在的Linux发行版 xff0c 比如Ubuntu xff0c CentOS等已经基本上可以采用GUI来完成绝大部分一般性的任务 但是 xff0c 终端程序
  • vim编辑器如何删除一行或者多行内容

    如何从Vim中删除行 xff1f 如何删除多行 xff1f 本文介绍在Vim编辑器中删除行的不同方法 安装vim 在Ubuntu Debian中的安装方式 sudo apt install vim 在RHEL Centos中的安装方式 yu
  • Linux系统入门命令学习经验

    此时此刻我想和大家分享一下我在学习linux过程中的一些经验和教训 xff0c 如果有人能够正好看到我的这篇文章 xff0c 希望能够让想学习linux的同学多少获得一点经验 xff0c 少走一些弯路 能够比较简单 快捷的迅速掌握知识是我们
  • CloudBeaver 参考架构

    CloudBeaver 是一个基于 Web 的云数据库管理工具 xff0c 支持 PostgreSQL MySQL MariaDB SQLite 和 Firebird 等数据库 server osgi 模式 xff0c 依赖dbeaver
  • 如何修改Vim默认注释

    在Linux下vim被注释掉的字体颜色默认为非常刺眼的蓝色 xff0c 看上去很不清晰 xff0c 我们可以通过设置用户根目录下 vimrc文件 xff0c 可以更改颜色的配置 Vim默认注释颜色如下图 xff1a 找到vim的配置文件 x
  • yum install 与 yum groupinstall 的区别

    yum 提供二种安装软件的方式 1 xff0c yum install 它安装单个软件 xff0c 以及这个软件的依赖关系 2 xff0c yum groupinstall 它安装一个安装包 xff0c 这个安装包包涵了很多单个软件 xff
  • 自制正点原子四轴遥控器无法连接minifly

    最近在群里有群友问自制遥控器无法对频的问题 xff0c 我过去也踩过这个坑 xff0c 已经解决了 我已经在群里回答四五次了 xff0c 但可能群友没注意或者进群较晚没看到 xff0c 正好今晚有空 xff0c 把这个坑填上 18年国庆后自
  • 红旗Linux系统安装教程

    用惯了Windows系统的您 xff0c 会不会想尝尝鲜 xff0c 试试Linux的系统呢 以下经验在虚拟机和实机都适用的哦 工具 原料 电脑 Linux系统镜像包 方法 步骤1 首先将镜像写到光盘或者U盘 xff0c 然后到bios设置
  • 安装CentOS7出现dracut:/#……time解决办法

    当选择install CentOS7以后一会就会出现错误 报错信息 xff1a 就是dracut xff1a timeout一大堆 我本来以为是我的启动盘没做好 xff0c 后来我又重做了好几次都是这问题 解决 通过搜索引擎检索 xff0c
  • 【PID控制 Ⅱ】在代码中实现PID控制算法的思路以及伪代码

    一 实现思路 定义PID控制器 xff1a 在代码中定义一个PID控制器 xff0c 包括三个参数 xff1a 比例系数 xff08 Kp xff09 积分系数 xff08 Ki xff09 和微分系数 xff08 Kd xff09 这些参
  • 使用ZED-stereo相机配合SURF算法识别目标并测距

    这是以前做的小项目里的一部分 xff0c 由于时间久远 xff0c 在这里整理以下 xff0c 也方便自己以后查阅 使用ZED stereo相机配合SURF算法识别目标并测距 ZED stereo是很好用功能强大的双目相机 xff0c 可以
  • 联合标定单目相机和imu,使用工具Kalibr

    使用Kalibr工具标定单目相机和IMU的外参 xff0c 操作过程和联合标定双目相机和IMU类似 xff0c 以下介绍不同部分 最后标定时所需要的相机参数由双目变成了单目 xff0c 以下是配置文件的格式 xff1a cam0 camer
  • DETR3D的关键:feature_sampling(3D到2D的图像特征采样)

    流程 xff1a 坐标转换 gt 归一化坐标 gt grid sample 方法 gt mask 坐标转换 gt 归一化坐标 gt grid sample 方法 span class token comment 特征采样部分 xff0c I