OpenPCDet系列 | 5.4.1 DenseHead中的AnchorGenerator锚框生成模块
文章目录
- AnchorGenerator模块
- AnchorGenerator.generate_anchors函数
AnchorGenerator模块
首先,根据点云场景将其划分为一个个grid,这个grid size是可以通过配置文件设定的点云场景方位和voxel大小计算出来的。
POINT_CLOUD_RANGE: [0, -39.68, -3, 69.12, 39.68, 1]
VOXEL_SIZE: [0.16, 0.16, 4]
在dense_head的初始化过程,就会在基类进行anchor的生成。
# 功能:dense head模块的基类
class AnchorHeadTemplate(nn.Module):def __init__(self, model_cfg, num_class, class_names, grid_size, point_cloud_range, predict_boxes_when_training):......# anchor生成配置anchor_generator_cfg = self.model_cfg.ANCHOR_GENERATOR_CONFIG # list:存储每个类别的anchor生成设置anchors, self.num_anchors_per_location = self.generate_anchors(anchor_generator_cfg, grid_size=grid_size, point_cloud_range=point_cloud_range,anchor_ndim=self.box_coder.code_size)......@staticmethoddef generate_anchors(anchor_generator_cfg, grid_size, point_cloud_range, anchor_ndim=7):"""Args:anchor_generator_cfg: 每个类别的anchor配置grid_size: 网格大小 [432 496 1]point_cloud_range: 点云范围 [ 0. -39.68 -3. 69.12 39.68 1. ]anchor_ndim: anchor维度: 7 位置 + 大小 + 方向 [x,y,z,dx,dy,dz,rot]"""anchor_generator = AnchorGenerator(anchor_range=point_cloud_range,anchor_generator_config=anchor_generator_cfg)# 对每个类别生成anchor的feature map [array([216, 248]), array([216, 248]), array([216, 248])]feature_map_size = [grid_size[:2] // config['feature_map_stride'] for config in anchor_generator_cfg]# 返回每个类别构建好的anchor[(1,248,216,1,2,7), ...] 和 每个位置anchor的数量[2, 2, 2]anchors_list, num_anchors_per_location_list = anchor_generator.generate_anchors(feature_map_size)if anchor_ndim != 7: # 默认情况是为7, 如果anchor的维度不等于7,则补0for idx, anchors in enumerate(anchors_list):pad_zeros = anchors.new_zeros([*anchors.shape[0:-1], anchor_ndim - 7])new_anchors = torch.cat((anchors, pad_zeros), dim=-1)anchors_list[idx] = new_anchorsreturn anchors_list, num_anchors_per_location_list
这里3d点云检测的anchor生成和yolov5等目标检测2d算法在图像网格点生成anchor类似。由于这里有3个类别,那么首先对每个列表都构建一个feature map,每个feature map尺度在这里和点特征矩阵的尺寸是一样的。随后,将这个feature map列表送入AnchorGenerator.generate_anchors函数来进行具体的anchor生成。
AnchorGenerator.generate_anchors函数解析如下。
AnchorGenerator.generate_anchors函数
以点云场景限制为:[ 0. -39.68 -3. 69.12 39.68 1. ] 为例。由于设定了grid size,那么就可以知道每个grid之间的步长,那么根据这个步长就有可以将整个点云场景均匀的划分为一个个等大的grid。
# 步长的确定:PointPillars不在z轴进行划分,所以z轴步长不需要考虑
x_stride = (self.anchor_range[3] - self.anchor_range[0]) / (grid_size[0] - 1) # x方向步长
y_stride = (self.anchor_range[4] - self.anchor_range[1]) / (grid_size[1] - 1) # y方向步长
x_offset, y_offset = 0, 0# 根据步长构建xy方向的间隔点
x_shifts = torch.arange( # (69.12 - 0) / (216 - 1) = 0.321488 间隔点有216个,所以步长为0.321488self.anchor_range[0] + x_offset, self.anchor_range[3] + 1e-5, step=x_stride, dtype=torch.float32,
).cuda()
y_shifts = torch.arange( # (39.68 - (-39.68)) / (248 - 1) = 0.321295 间隔点有248个,所以步长为0.321295self.anchor_range[1] + y_offset, self.anchor_range[4] + 1e-5, step=y_stride, dtype=torch.float32,
).cuda()
z_shifts = x_shifts.new_tensor(anchor_height) # [-1.78] PointPillar不对z轴进行区间划分
更具步长来构建一个三维的网格坐标是通过meshgrid函数来实现的。meshgrid可以理解为在原来的维度上进行扩展(此时3者的坐标维度是一样的)。随后将其进行拼接在一起,此时就获得了在点云场景中的一个三维坐标表示。拼接后的维度是[216,248,1,3],前三维信息是表示xyz轴,最后一维表示分别的坐标。
# 根据xyz步长构建三维网格坐标 [x_grid, y_grid, z_grid] --> [(216,248,1), (216,248,1),(216,248,1)]
x_shifts, y_shifts, z_shifts = torch.meshgrid([x_shifts, y_shifts, z_shifts
]) # [x_grid, y_grid, z_grid]
# meshgrid可以理解为在原来的维度上进行扩展, (np.meshgrid 和 torch.meshgrid 是返回结果不一样的)
# 例如:
# x原来为(216,)-->(216,1, 1)--> (216,248,1)
# y原来为(248,)--> (1,248,1)--> (216,248,1)
# z原来为 (1,) --> (1,1,1) --> (216,248,1)# xyz位置信息堆叠,完成anchor位置信息的构建: (216,248,1,3)
anchors = torch.stack((x_shifts, y_shifts, z_shifts), dim=-1) # [x,y,z,3]-->[216,248,1,3]
anchor坐标位置构建完后,随后与anchor的尺寸大小、旋转角信息进行组合:
# 将anchor的位置信息与尺寸大小进行组合: (216,248,1,1,6)
anchors = anchors[:, :, :, None, :].repeat(1, 1, 1, anchor_size.shape[0], 1) # (216,248,1,3) -> (216,248,1,1,3)
anchor_size = anchor_size.view(1, 1, 1, -1, 3).repeat([*anchors.shape[0:3], 1, 1]) # (1,1,1,1,3) -> (216,248,1,1,3)
anchors = torch.cat((anchors, anchor_size), dim=-1) # anchors的位置+大小 --> (216,248,1,1,6)# 将anchor的位置信息、尺寸大小、旋转角信息进行组合: (216,248,1,1,2,7)
anchors = anchors[:, :, :, :, None, :].repeat(1, 1, 1, 1, num_anchor_rotation, 1) # (216,248,1,1,1,6) -> (216,248,1,1,2,6)
anchor_rotation = anchor_rotation.view(1, 1, 1, 1, -1, 1).repeat([*anchors.shape[0:3], num_anchor_size, 1, 1]) # (1,1,1,1,2,1) -> (216,248,1,1,2,1)
anchors = torch.cat((anchors, anchor_rotation), dim=-1) # anchors的位置+大小+旋转方向 --> (216,248,1,1,2,7)# 最后调整anchor的维度: (1,248,216,1,2,7)
# 最后一维的7表示的特征信息为: [x, y, z, dx, dy, dz, rot], [位置信息xyz, 尺寸信息, 旋转角度]
anchors = anchors.permute(2, 1, 0, 3, 4, 5).contiguous() # (216,248,1,1,2,7) -> (1,248,216,1,2,7)
#anchors = anchors.view(-1, anchors.shape[-1])
最后获取的anchor的维度: (1,248,216,1,2,7)。其中(1,248,216)表示点云场景每个grid的位置。2表示每个grid位置有两种方向的anhcor。然后7表示每种方向的anchor的具体位置信息、尺寸大小、旋转角度。如此,依次对每个类别进行anchor的生成,最后返回的是anchors_list。
ps:这里的anhcor的z轴位置信息还回加上anchor的高度,以汽车类别为例,由于每个anchor的z轴gird位置设置为'anchor_bottom_heights': [-1.78],然后再加上anchor高度的一半也就是1.56 // 2 = 0.78,z轴的位置信息就被更新为1,这个就是anchor的具体在z轴上的位置。下面就是某个grid位置的anchor配置信息,可以看见一个位置的一类anchor会有两个方向的尺寸位置一样的配置。

函数的最后返回的是anchor_list列表以及每个位置每个类别有多少种anchor的列表,如下所示:

至此,完成了每个grid每个类别的anchor生成配置。思路上是比较清晰的,具体的细节就是各种anchor信息在各位置的拼接处理。
相关文章:
OpenPCDet系列 | 5.4.1 DenseHead中的AnchorGenerator锚框生成模块
文章目录 AnchorGenerator模块AnchorGenerator.generate_anchors函数 AnchorGenerator模块 首先,根据点云场景将其划分为一个个grid,这个grid size是可以通过配置文件设定的点云场景方位和voxel大小计算出来的。 POINT_CLOUD_RANGE: [0, -39.68, -3, 6…...
【开发者指南】如何在MyEclipse中使用HTML或JSP设计器?(上)
MyEclipse v2022.1.0正式版下载 一、HTML & JSP 可视化设计器 本文简要介绍了 MyEclipse HTML 和 JSP Web 设计器的概念、功能和基本操作过程。这两个设计器具有相似的功能和相同的操作模型,但本文为专门针对其类型的内容。本文档中的示例是使用 MyEclipse HT…...
Node开发Web后台服务
简介 Node.js 是一个基于Google Chrome V8 引擎的 JavaScript 运行环境。Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。Node.js 的包管理器 npm,是全球最大的开源库生态系统。 能方便地搭建响应速度快、易于扩展的网络应用&#…...
Linux下对mmap封装使用
Linux下对mmap封装使用 1、mmap简介2、Linux下mmap使用介绍2.1、mmap函数2.2、munmap函数 3、对mmap进行封装4、对封装类MEM_MAP进行测试5、mmap原理6、源代码下载 1、mmap简介 mmap即memory map,是一种内存映射文件的技术。mmap可以将一个文件或者其它对象映射到进…...
深入了解云计算:发展历程、服务与部署模型、未来趋势与挑战
开篇博主 bluetata 的观点:PaaS 服务必将是未来10年云计算权重最高的趋势(05/02/2023 15:32) 文章目录 一、前言二、认识了解云计算2.1 什么是云计算2.1.1 维基百科上的云计算定义2.1.2 NIST 标准云计算定义2.1.3 如果被面试如何解释云计算 2…...
使用乐鑫 Web IDE 助力物联网开发
乐鑫 Web IDE 是基于 Eclipse Theia 的框架,支持 ESP-IDF VS Code 插件同时具备多项辅助工具。您可以观看我们在 Espressif DevCon22 上的演示视频,了解它的实际应用。 【乐鑫开发者大会-21】搭载 ESP-IDF Visual Studio Code 插件的乐鑫 …...
Maven(5)---Maven的部署和发布
Maven的部署和发布 在前面的博客中,我们已经学习了Maven的基础知识、依赖管理、插件和生命周期,以及多模块项目管理。本篇博客将介绍Maven的部署和发布功能。 什么是部署和发布 在软件开发过程中,部署和发布是非常重要的环节。部署是指将软…...
内网渗透之权限维持-黄金白银票据隐藏账户远控-RustDeskGotoHTTP
0x01权限维持-隐藏用户 CreateHiddenAccount工具 CreateHiddenAccount -u test -p Psswrd用户管理能查看到,命令查看看不到,单机版无法删除(不在任何组),域环境(在administrator组中)可以删除 0x02权限维持-黄金白银票据 ⻩⾦票据⽣成攻…...
动态规划——带权活动选择
带权活动选择Time Limit: 3000 MSMemory Limit: 1000 KB Description 给定n个活动,活动ai表示为一个三元组(si,fi,vi),其中si表示活动开始时间,fi表示活动的结束时间,vi表示活动的权重, si<fi。带权活动选择问题是选择一些活…...
软考A计划-真题-分类精讲汇总-第十八章(面向对象程序设计)
点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分享&am…...
【C++ 入坑指南】(09)数组
文章目录 简介一维数组1. 定义2. 特点3. 用途4. 示例 二维数组1. 定义2. 用途3. 示例 简介 C 支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。 一维数组 1. 定义…...
Vue.js
文章目录 Vue(前端框架)data基本语法v-bind(属性)v-if(条件)v-formethods事件v-model表单绑定todolist(添加删除展示内容,含上下移动)es6语法生命周期函数axios发送ajax请…...
博士毕业答辩流程 注意事项
前言:2023年5月17日14:00-17:00,与实验室其他同学一起旁听了本实验室的博士论文答辩。接下来,我对博士毕业答辩的大致流程进行简要介绍,并对个环节的注意事项进行总结归纳,供毕业生参考。 目录 1. 准备阶段2. 汇报期间…...
拼多多开放平台订单详情接口解析
API接口订单接口是指用于实现订单相关操作的程序接口。通过这个接口,用户可以实现创建、修改、查询和取消订单等功能。 常见的API接口订单接口包括: 创建订单接口,用于实现用户下单操作。 修改订单接口,用于修改已有订单信息。 …...
如何把ipa文件(iOS安装包)安装到iPhone手机上? 附方法汇总
苹果APP安装包ipa如何安装在手机上?很多人不知道怎么把ipa文件安装到手机上,这里就整理了苹果APP安装到iOS设备上的方式,仅供参考 苹果APP安装包ipa如何安装在手机上?使用过苹果手机的人应该深有感触,那就是苹果APP安…...
由浅入深了解 深度神经网络优化算法
CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 导言 优化是从一组可用的备选方案中选择最佳方案。优化无疑是深度学习的核心。基于梯度下降的方法已经成为训练深度神经网络的既定方法。 在最简单的情况下,优化问题包括通过系统地从允许集合中…...
LIN-报文结构
文章目录 协议规范一、字节场二、报文头(HEADER FIELDS)同步间隔(synchronisation break)同步场(SYNCH FIELD)标识符场(IDENTIFIER FIELD) 三、数据场(DATE FIELDS)四、校…...
南京邮电大学通达学院2023c++实验报告(三)
题目 实验题目1 某公司财务部需要开发一个计算雇员工资的程序。该公司有3类员工,工资计算方式如下: (1)工人工资:每小时工资额(通过成员函数设定)乘以当月工作时数(通过成员函数设定),再加上工龄工资。 (2)销售员工资:每小时工资额(通过成员函数设定)乘以当月…...
ISO9000和ISO9001有哪些区别?
作为ISO标准体系的新手,ISO9000和ISO9001是第一个接触到的标准。有些人可能会含糊地表达包含关系的词语,但他们仍然无法真正理解它们。两者的关系是什么?有什么区别?事实上,两者的主要区别体现在以下三个方面: 第一&am…...
第7章异常、断言和曰志
Java和C异 在C中,throw说明符在运行时执行。Java在编译时执行。 处理错误 异常处理的任务就是将控制权从产生错误的地方转移到能够处理这种情况的错误处理器。 如果由于出现错误而使得某些操作没有完成,程序应该:返回到一种安全状态&#…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...
LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
Linux中《基础IO》详细介绍
目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改,实现简单cat命令 输出信息到显示器,你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
第三周 Day 3 🎯 今日目标 理解类(class)和对象(object)的关系学会定义类的属性、方法和构造函数(init)掌握对象的创建与使用初识封装、继承和多态的基本概念(预告) &a…...
JavaScript 标签加载
目录 JavaScript 标签加载script 标签的 async 和 defer 属性,分别代表什么,有什么区别1. 普通 script 标签2. async 属性3. defer 属性4. type"module"5. 各种加载方式的对比6. 使用建议 JavaScript 标签加载 script 标签的 async 和 defer …...
