bev_feature与真实坐标的关系

news/2024/10/6 4:17:57/文章来源:https://www.cnblogs.com/swc-blog/p/18285955

在生成 BEV feature 时的 scatter:

nx = int((point_cloud_range[3]-point_cloud_range[0])/voxel_size[0])# Create the canvas for this sample
canvas = torch.zeros(self.in_channels,self.nx * self.ny,dtype=voxel_features.dtype,device=voxel_features.device)# coors[:,2] 体素y坐标
# coors[:,3] 体素x坐标
indices = coors[:, 2] * self.nx + coors[:, 3]
indices = indices.long()
voxels = voxel_features.t()
# Now scatter the blob back to the canvas.
canvas[:, indices] = voxels
# Undo the column stacking to final 4-dim tensor
canvas = canvas.view(1, self.in_channels, self.ny, self.nx)

示例:
image-20240705104826677|500

nx = 8
ny = 4
indices = []for y in range(ny):for x in range(nx):idx = x + y*nxindices.append(idx)indices_tensor = torch.from_numpy(np.array([indices]))
print(indices_tensor)indices_tensor = indices_tensor.view(ny, nx)
print(indices_tensor)indices_tensor = indices_tensor.permute(1, 0)
print(indices_tensor)

result:

tensor([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]])tensor([[ 0,  1,  2,  3,  4,  5,  6,  7],[ 8,  9, 10, 11, 12, 13, 14, 15],[16, 17, 18, 19, 20, 21, 22, 23],[24, 25, 26, 27, 28, 29, 30, 31]])tensor([[ 0,  8, 16, 24],[ 1,  9, 17, 25],[ 2, 10, 18, 26],[ 3, 11, 19, 27],[ 4, 12, 20, 28],[ 5, 13, 21, 29],[ 6, 14, 22, 30],[ 7, 15, 23, 31]])

可以看到是按照 x 轴方向,行优先排列的,模型后面所有的操作都是基于这个形状的 feature 做的

occupancy 的输出格式为 1,X,Y,C

# bev_feature: (B, C_i, Dy, Dx)
# (B, C_i, Dy, Dx) -> (B, C_o, Dy, Dx) -> (B, Dx, Dy, C_o)
occ_pred = self.final_conv(bev_feats).permute(0,3,2,1)
bs, Dx, Dy = occ_pred.shape[:3]
# (B, Dx, Dy, C_o) -> (B, Dx, Dy, 2*C_o) ->(B, Dx, Dy, n_cls*Dz)
if self.use_predictor:occ_pred = self.predictor(occ_pred)
# (B, Dx, Dy, n_cls*Dz) -> (B, Dx, Dy, Dz, n_cls)
occ_pred = occ_pred.view(bs, Dx, Dy, self.Dz, self.num_classes)occ_score = occ_pred.softmax(-1)
# (B, Dx, Dy, Dz)
occ_res = occ_score.argmax(-1).float().contiguous()

cuda 得到 point 结果:

int y = coor_idx % occupancy_dim_size.y;
int x = coor_idx / occupancy_dim_size.y;
int occupied_idx = 0;
float lidar_x, lidar_y, lidar_z;
for (int z = 0; z < occupancy_dim_size.z; ++z) {int semantic = round(occ_out_deveice[coor_idx * occupancy_dim_size.z + z]);if(semantic > 0 && semantic != 2) {occupied_idx = atomicAdd(occupied_num_device, 1);lidar_x = (x + 0.5) * occupancy_voxel_size.x + range.min_x;lidar_y = (y + 0.5) * occupancy_voxel_size.y + range.min_y;lidar_z = (z + 0.5) * occupancy_voxel_size.z + range.min_z;occupied_out_device[4 * occupied_idx] = lidar_x;occupied_out_device[4 * occupied_idx + 1] = lidar_y;occupied_out_device[4 * occupied_idx + 2] = lidar_z;occupied_out_device[4 * occupied_idx + 3] = semantic;}
}

根据 Core Concepts — NVIDIA cuDNN v9.2.1 documentation 的解释

data:
image-20240704181218487

NHWC 排布的数据在内存中的顺序:

image-20240704181256275

回到 BEV feature map,在 permute(0,3,2,1) 后,2,3 维度是 X, Y 内存是行排列的

int y = coor_idx % occupancy_dim_size.y;
int x = coor_idx / occupancy_dim_size.y;

图示:

occ 中的 feature:
这里得到的 BEV feature 与上述一致:

# 真实坐标id
tensor([[ 0,  8, 16, 24], # 第一列在原始BEV中的索引, 映射为内存中的 0,1,2,3[ 1,  9, 17, 25],[ 2, 10, 18, 26],[ 3, 11, 19, 27],[ 4, 12, 20, 28],[ 5, 13, 21, 29],[ 6, 14, 22, 30],[ 7, 15, 23, 31]])
# 映射到内存中的id:
tensor([[ 0,  1,  2,  3],[ 4,  5,  6,  7],[ 8,  9, 10, 11],[12, 13, 14, 15],[16, 17, 18, 19],[20, 21, 22, 23],[24, 25, 26, 27],[28, 29, 30, 31]])

IMG_20240704_193250

在目标检测中,centerhead 导出的onnx 最后输出的 feature map 顺序是 1,X,Y,C, 与 occ 是翻转关系:

reg_res = reg_res.permute(0, 2, 3, 1).contiguous()
height_res = height_res.permute(0, 2, 3, 1).contiguous()
dim_res = dim_res.permute(0, 2, 3, 1).contiguous()
rot_res = rot_res.permute(0, 2, 3, 1).contiguous()

数据排布:

tensor([[ 0,  1,  2,  3,  4,  5,  6,  7],[ 8,  9, 10, 11, 12, 13, 14, 15],[16, 17, 18, 19, 20, 21, 22, 23],[24, 25, 26, 27, 28, 29, 30, 31]])
int x = coor_idx % occupancy_dim_size.x;
int y = coor_idx / occupancy_dim_size.x;

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

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

相关文章

【设计模式(六)】结构性模式--代理模式

结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大…

面试必会之事物控制

01- 什么是事务 ? 事务就是用户定义的一系列数据库操作,这些操作可以视为一个完成的逻辑处理工作单元,要么全部执行,要么全部不执行,是不可分割的工作单元 02- 事务的特性有哪些 ?原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。一致性…

字节面试 用double,1.0-0.9的结果不是0.1,为什么?

让我详细解释一下为什么 1.0 - 0.9 在二进制中不能精确表示。 1.0 的二进制表示 1.0 在二进制中可以精确表示。它的二进制表示为: 1.0 = 1.0 (二进制)0.9 的二进制表示 0.9 是一个无法在二进制中精确表示的小数。二进制小数是通过求和 1/2, 1/4, 1/8, 1/16, ... 等幂次表示的。…

关于oracle中的undo

一,undo介绍 二,undo视图说明 三,常用脚本说明 四.释放UNDO表空间 五.参考 一,undo介绍 Oracle中 undo的作用主要有两个:第一是回滚事务,第二是产生一致性读。同时也衍生出了一些新的 功能,比如Flashback query。传统的 undo是通过undo segment 来管理的,我们看下面的示…

闪迪U盘数据恢复

一、检查并取消隐藏项目 连接U盘:首先,确保闪迪U盘与电脑稳定连接。 打开U盘目录:在电脑中找到并打开U盘所在的目录。 显示隐藏项目:在文件资源管理器的顶部菜单中,点击“查看”选项,并勾选“显示隐藏的项目”。如果数据只是被隐藏了,这一步应该能够显示出被隐藏的文件。…

移动硬盘坏道修复

一、使用系统自带的磁盘检查工具 如果使用的是Windows系统,可以通过系统自带的磁盘检查工具来尝试修复坏道。 连接移动硬盘:首先,确保移动硬盘已经通过USB线连接到电脑上,并且系统能够识别到它。 打开磁盘属性:在文件资源管理器中,右键点击移动硬盘的图标,选择“属性”。…

MyBatis-Plus-实用的功能自动填充字段

MyBatis-Plus-实用的功能自动填充字段前言: java项目用到了mybatis-plus,在一些类里面需要在更新时候,统一设置,修改人,修改ID,修改时间。新增时候设置 创建人,创建时间等 基础类:@Data public abstract class BaseModel implements Serializable {/*** 逻辑删除*/@Tabl…

BOSHIDA DC/AC电源模块在不同的电源类型之间进行转换

BOSHIDA DC/AC电源模块在不同的电源类型之间进行转换 电力转换是现代社会不可或缺的一部分,它使我们能够在不同的电源类型之间进行转换,从而满足各种设备和应用的需求。DC/AC电源模块是一种用于将直流电转换为交流电的设备,它在电子设备、太阳能系统、电池充电等领域发挥着重…

面试必会之SpringBootSpringCloud

01- 讲一讲SpringBoot自动装配的原理 1.在SpringBoot项目的启动引导类上都有一个注解@SpringBootApplication @SpringBootApplication @MapperScan("com.hxx.admin.dao") public class AdminApplication {public static void main(String[] args) {SpringApplication…

在Docker中搭建rabbit MQ集群 (Mac + OrbStack)

我以为用docker搭建一个rabbitMq集群会非常简单,但是结果却出乎意料,我花了差不多两个半天才搞定。这还是依赖了AI的协助,否则难度不敢想象。我的环境是Mac上的OrbStack。用了Kimi + 文心一言 + ChatGPT + Claude,还是Kimi价值最大。back and forth 的过程就不讲了,这里直…

信息安全驱动汽车行业快速向数字化转型

经纬恒润针对ISO/SAE 21434、WP.29 R155等法规进行了深入研究,结合多年功能安全、信息安全经验,可以为客户提供信息安全全流程解决方案。 开发一款安全性良好的软件是困难的,它需要专业知识的积累以及对常见编程缺陷和规则的了解,例如检查输入范围、管理内存分配和回…

Java进阶:HashMap底层原理(通俗易懂篇)

1.底层结构 Java 7及之前版本 在Java 7及之前的版本中,HashMap的底层数据结构主要是数组加链表。具体实现如下:数组:HashMap的核心是一个Entry数组(Entry<K,V>[] table),这个数组的大小总是2的幂。每个数组元素是一个单一的Entry节点,或者是一个链表的头节点。链表…