当前位置: 首页 > news >正文

OpenPCDet系列 | 4.2 DataAugmentor点云数据增强模块解析

文章目录

  • DataAugmentor模块解析
  • 1. gt_sampling
  • 2. random_world_flip
  • 3. random_world_rotation
  • 4. random_world_scaling
  • 5. limit_period

DataAugmentor模块解析

在pointpillars算法中,具体的数据增强方法配置是在yaml中的DATA_CONFIG.DATA_AUGMENTOR进行配置,pointpillars的参考配置如下所示:

DATA_AUGMENTOR:DISABLE_AUG_LIST: ['placeholder']   # 禁用该数据增强AUG_CONFIG_LIST:                    # 启用的数据增强列表- NAME: gt_samplingUSE_ROAD_PLANE: True    # 启用道路平面信息,将gt中心位置移动到道路平面上(abcd表示一个平面方程)DB_INFO_PATH:- kitti_dbinfos_train.pkl   # 存储训练集每个类别的对象信息,每个类别用列表来存储,应该与INFO_PATH对应PREPARE: {    # gt的具体采样操作filter_by_min_points: ['Car:5', 'Pedestrian:5', 'Cyclist:5'],  # 表示过滤低于5个点的gt,需要int型赋值filter_by_difficulty: [-1],    # 过滤的困难等级列表}# USE_SHARED_MEMORY: False    # 默认不设置共享内存,若开启需要设置DB_DATA_PATHSAMPLE_GROUPS: ['Car:15','Pedestrian:15', 'Cyclist:15']NUM_POINT_FEATURES: 4DATABASE_WITH_FAKELIDAR: FalseREMOVE_EXTRA_WIDTH: [0.0, 0.0, 0.0]   # 将采样box扩张大小长度LIMIT_WHOLE_SCENE: False- NAME: random_world_flipALONG_AXIS_LIST: ['x']- NAME: random_world_rotationWORLD_ROT_ANGLE: [-0.78539816, 0.78539816]- NAME: random_world_scalingWORLD_SCALE_RANGE: [0.95, 1.05]

在data_augmentor模块初始化后,在进行前向传播的数据准备时,也就是batch = next(dataloader_iter)的时候,会在kitti_dataset的__getitem__函数进行数据的准备,随机获取一个点云帧场景索引,准备好当前点云帧的点特征、gt boxes、gt类别名称、坐标系转换类calib、道路信息road_plane等数据,构建成一个data_dict传入基类的prepare_data函数中,进行数据的进一步处理,形成训练的batch数据。此外,在__getitem__函数中还会困难进行FOV点云视角的范围裁剪,也就是将全方位的点云场景只保留前视图的点云,在这一步之后当前点云帧场景的点云数量会大大降低。

在基类的prepare_data函数中,即会依次进行data_augmentor部分、point_feature_encoder部分、以及data_processor部分三大部分的数据处理,最后形成最终的batch数据输入到模型中进行训练,下面分别对着data_augmentor部分进行记录介绍。在pointpillars配置文件中,数据增强部分就包含了gt_sampling、random_world_flip、random_world_rotation、random_world_scaling四种方法。下面对其进行分别记录。

在数据增强基类DataAugmentor中提供了一些列的数据增强的方法,在初始化阶段会依次添加配置文件中制定的数据增强方式进入队列中,随后在forward函数中对data_dict数据进行依次处理。由于队列先进先出的特性,所以在配置文件中靠前的部分会按顺序优先处理。

def forward(self, data_dict):      # 在prepare_data中进行"""Args:data_dict:points: (N, 3 + C_in)gt_boxes: optional, (N, 7) [x, y, z, dx, dy, dz, heading]gt_names: optional, (N), string...Returns:"""# 遍历增强队列,逐个增强器做数据增强for cur_augmentor in self.data_augmentor_queue:data_dict = cur_augmentor(data_dict=data_dict)......

1. gt_sampling

在pointpillars的数据增强方法中首要的就是gt_sampling方法。对于gt的信息格式存储在db_infos字典中,具体是在database_sampler中进行处理,对于每个类别的每个内容如下所示:
在这里插入图片描述

在pcdet.datasets.augmentor.database_sampler.py文件中提供了DataBaseSampler类来完成这一模块,在__init__初始化类阶段首先会对训练集数据的全部gt样本进行读取,对每个gt的点云数量较少或者是困难等级的gt进行过滤。随后对每个类别的gt重新统计信息,包含采样数量、过滤后的gt数量(变化)、以及重新分配索引(从0开始分配)。这部分的gt过滤操作通过DATA_AUGMENTOR.PREPARE部分来进行设置。以上即设置了两个过滤操作。分别是:filter_by_min_points、filter_by_difficulty。

随后,在具体的数据准备过程中具体调用的DataBaseSampler的__call__方法,这相当于是继承nn.Module时调用的forward方法,即运行对象。在训练集各类别中随机采样与当前帧点云不重叠的gt,作为当前帧额外的独立采样gt,并添加到当前的点云帧场景中,相当于是一个copy paste操作。而挑选不重叠的gt过程的挑选相当于是一个碰撞测试,避免影响到当前点云帧的原始gt,从而实现gt样本的增多,即数据增强的效果。

具体将采样的gt与当前点云帧场景进行结合,并将gt移动到道路平面上具体操作是有DataBaseSampler.add_sampled_boxes_to_scene方法实现的。主要作用就是将gt移动到道路平面上,首先去除原始的gt(这里还会将原始的gt扩张)内的点云,然后将采样的gt点云与背景点点云拼接构造成新的场景。

在对训练集gt样本进行具体体的随机才样操作是通过sample_with_fixed_number函数来具体实现,主要的实现方法是获取打乱顺序后的indices前 sample_num 个db_infos。所以,总的来说gt_sampling这一部分就是围绕着gt的采样来实现。比如对gt进行限制过滤,然后采样其他场景的gt来添加到当前点云帧场景,前提是通过碰撞测试,从而实现数据增强,类似的一个copy paste的思路。具体实现上还有FOV的范围筛选,道路平面的转移等操作细节。核心代码如下所示:

# 将采样的box扩大,sampler_cfg.REMOVE_EXTRA_WIDTH即为dx,dy和dz的放大长度
large_sampled_gt_boxes = box_utils.enlarge_box3d(sampled_gt_boxes[:, 0:7], extra_width=self.sampler_cfg.REMOVE_EXTRA_WIDTH
)# 核心代码:更新当前点云场景信息
points = box_utils.remove_points_in_boxes3d(points, large_sampled_gt_boxes)    # 只保留背景点,去除前景点
points = np.concatenate([obj_points[:, :points.shape[-1]], points], axis=0)    # 将采样+原始gt点云与放大后保留的背景点拼接,组成新的点云
gt_names = np.concatenate([gt_names, sampled_gt_names], axis=0)     # 将类别拼接
gt_boxes = np.concatenate([gt_boxes, sampled_gt_boxes], axis=0)     # 将box拼接

在进行gt‘采样后的数据增强时,data_dict数据字典中只保留了4个有效键值对,如下所示。分别是当前点云帧索引,gt类别名称,gt boxes以及加入采样gt后的新点云场景points
在这里插入图片描述


2. random_world_flip

对点云和gt沿x轴或者y轴按一定分布概率进行随机反转,具体的实现函数是在augmentor_utils中。

  • 沿x轴进行反转的核心代码:
if enable is None:enable = np.random.choice([False, True], replace=False, p=[0.5, 0.5])   # 一半的概率选择是否翻转
if enable:gt_boxes[:, 1] = -gt_boxes[:, 1]    # y坐标翻转gt_boxes[:, 6] = -gt_boxes[:, 6]    # 方位角翻转,直接取负数,因为方位角定义为与x轴的夹角(这里按照顺时针的方向取角度)points[:, 1] = -points[:, 1]        # 点云y坐标翻转
  • 沿y轴进行反转的核心代码:
if enable is None:enable = np.random.choice([False, True], replace=False, p=[0.5, 0.5])   # 一半的概率选择是否翻转
if enable:gt_boxes[:, 0] = -gt_boxes[:, 0]    # x坐标翻转gt_boxes[:, 6] = -(gt_boxes[:, 6] + np.pi)  # 方位角加pi后,取负数(这里按照顺时针的方向取角度)points[:, 0] = -points[:, 0]        # 点云x坐标取反

通过设置ALONG_AXIS_LIST来进行xy轴的反转设置,如果确定反转,会在data_dict中对反转的轴进行保留。


3. random_world_rotation

对点云和gt进行随机旋转,具体的实现函数是在augmentor_utils中,其会调用common_utils.rotate_points_along_z函数来实现沿z轴进行点云场景的旋转。

对于点云的旋转来说,一般都是利用旋转角度构建成沿z轴旋转的旋转矩阵来与坐标进行相乘,随后将旋转后的点云坐标再与原始的反射特征强度进行拼接,拼接成原来的点云特征维度(dim=4)。在函数实现中,这里是实现对batch数据进行数据增强操作,batch内的每帧数据都会分配一个随机选择angle,然后构建成一个batch的旋转矩阵。

  • 沿z轴进行旋转的核心代码:
cosa = torch.cos(angle)
sina = torch.sin(angle)
zeros = angle.new_zeros(points.shape[0])    # [0]
ones = angle.new_ones(points.shape[0])      # [1]
rot_matrix = torch.stack((  # 根据旋转角构造沿z轴旋转的旋转矩阵cosa,  sina, zeros,-sina, cosa, zeros,zeros, zeros, ones
), dim=1).view(-1, 3, 3).float()
points_rot = torch.matmul(points[:, :, 0:3], rot_matrix)    # 对点云坐标进行旋转 (B, N, 3)
points_rot = torch.cat((points_rot, points[:, :, 3:]), dim=-1) 

此外,这里的旋转角度是从给点的阈值范围内进行均匀分布而产生,增加了随机性。随机产生的旋转角度也会记录在data_dict中。


4. random_world_scaling

对点云和gt进行随机缩放,具体实现函数是在augmentor_utils中。

具体的缩放操作比较简单,直接将点云坐标与gt坐标和尺寸与缩放因子进行相乘即可。随机产生的缩放大小也会记录在data_dict中。核心代码如下所示:

if scale_range[1] - scale_range[0] < 1e-3:  # 如果缩放的尺度过小,则直接返回原来的box和点云return gt_boxes, points
noise_scale = np.random.uniform(scale_range[0], scale_range[1]) # 在缩放范围内随机产生缩放尺度
points[:, :3] *= noise_scale
gt_boxes[:, :6] *= noise_scale  # [:, :6]表示xyz,dxdydz均进行缩放

在进行了以上多种数据增强方式后,相关的记录都会记录在data_dict字典中,其中的gt boxes和points点云特征会不断进行更新,处理后的键值对如下所示:
在这里插入图片描述


5. limit_period

由于在gt的方向中存在大于π的偏移,这里额外将方位角限制在[-pi, pi],方位角定义为与x轴的夹角(这里按照顺时针的方向取角度)

# 功能: 将方位角限制在[-pi, pi],方位角定义为与x轴的夹角(这里按照顺时针的方向取角度)
# common_utils.py
def limit_period(val, offset=0.5, period=np.pi):val, is_numpy = check_numpy_to_torch(val)   # 格式转换,其中val表示的角度ans = val - torch.floor(val / period + offset) * period  # 将方位角限制在[-pi, pi]return ans.numpy() if is_numpy else ans# 将方位角限制在[-pi,pi]
# data_augmentor.py
data_dict['gt_boxes'][:, 6] = common_utils.limit_period(data_dict['gt_boxes'][:, 6], offset=0.5, period=2 * np.pi
)

在保存限制方位角后的gt,此时的data_dict即更新完毕,即将送入下一个模块中。


相关文章:

OpenPCDet系列 | 4.2 DataAugmentor点云数据增强模块解析

文章目录 DataAugmentor模块解析1. gt_sampling2. random_world_flip3. random_world_rotation4. random_world_scaling5. limit_period DataAugmentor模块解析 在pointpillars算法中&#xff0c;具体的数据增强方法配置是在yaml中的DATA_CONFIG.DATA_AUGMENTOR进行配置&#…...

精准测试之过程与实践 | 京东云技术团队

作者&#xff1a;京东工业 宛煜昕 一、怎样的技术 •百度百科&#xff1a; 精准测试是一套计算机测试辅助分析系统。 精准测试的核心组件包含的软件测试示波器、用例和代码的双向追溯、智能回归测试用例选取、覆盖率分析、缺陷定位、测试用例聚类分析、测试用例自动生成系统…...

类ChatGPT逐行代码解读(1/2):从零实现Transformer、ChatGLM-6B

前言 最近一直在做类ChatGPT项目的部署 微调&#xff0c;关注比较多的是两个&#xff1a;一个LLaMA&#xff0c;一个ChatGLM&#xff0c;会发现有不少模型是基于这两个模型去做微调的&#xff0c;说到微调&#xff0c;那具体怎么微调呢&#xff0c;因此又详细了解了一下微调代…...

车道线检测

前言 目前&#xff0c;车道线检测技术已经相当成熟&#xff0c;主要应用在自动驾驶、智能交通等领域。下面列举一些当下最流行的车道线检测方法&#xff1a; 基于图像处理的车道线检测方法。该方法是通过图像处理技术从摄像头传回的图像中提取车道线信息的一种方法&#xff0c…...

云渲染靠谱吗,使用云渲染会不会被盗作品?

云渲染靠谱吗、安全吗&#xff1f;如果使用 云渲染会不会被盗作品......Renderbus瑞云渲染作为一个正经的云渲染平台&#xff0c;也时不时会收到这类疑问&#xff0c;首先&#xff0c;瑞云渲染是肯定靠谱的,各位可以放心使用。另外小编也将在本篇教你如何辨别云渲染平台是否安全…...

什么是FPGA?关于FPGA基础知识 一起来了解FPGA lattice 深力科 MachXO3系列 LCMXO3LF-9400C-5BG256C

什么是FPGA&#xff1f;关于FPGA基础知识 一起来了解FPGA lattice 深力科 MachXO3系列 LCMXO3LF-9400C-5BG256C FPGA基础知识&#xff1a;FPGA是英文Field&#xff0d;Programmable Gate Array的缩写&#xff0c;即现场可编程门阵列&#xff0c;它是在PAL、GAL、CPLD等可编程器…...

有什么好用的云渲染?

在CG制作流程中&#xff0c;离线渲染一直是必要且耗时的环节。你的场景越复杂&#xff0c;渲染出现问题的可能性就越大&#xff0c;尤其是当你独自工作&#xff0c;没有人给你建议的时候&#xff0c;灯光、模型、场景任何一个环节渲染时出现问题都可能让你焦头烂额&#xff0c;…...

什么是医学影像PACS系统?PACS系统功能有哪些?作用有哪些?对接哪些设备?业务流程是什么?

一、什么是医学影像PACS系统 PACS&#xff1a;为Picture Archive and CommunicationSystem的缩写&#xff0c;是图象归档和通讯系统。PACS系统应用在医院影像科室的系统&#xff0c;主要的任务就是把日常产生的各种医学影像&#xff08;包括核磁&#xff0c;CT&#xff0c;超声…...

分布式缓存:什么是它以及为什么需要它?

前言 随着网络的快速发展&#xff0c;分布式应用变得越来越普遍。这种类型的应用程序需要访问多个组件和服务&#xff0c;而这些组件可能分散在不同的物理位置上。在这种情况下&#xff0c;由于网络通信的高延迟和低带宽&#xff0c;性能问题变得尤为明显。为解决这一问题&…...

MySQL基础(二十二)逻辑架构

1.逻辑架构剖析 1.1 第1层&#xff1a;连接层 系统&#xff08;客户端&#xff09;访问MySQL服务器前&#xff0c;做的第一件事就是建立TCP连接。 经过三次握手建立连接成功后&#xff0c;MySQL服务器对TCP传输过来的账号密码做身份认证、权限获取。 用户名或密码不对&#…...

《Kubernetes证书篇:使用TLS bootstrapping简化kubelet证书制作》

一、背景 Master apiserver启用TLS认证后&#xff0c;Node节点kubelet和kube-proxy要与kube-apiserver进行通信&#xff0c;必须使用CA签发的有效证书才可以&#xff0c;当Node节点很多时&#xff0c;这种客户端证书颁发需要大量工作&#xff0c;同样也会增加集群扩展复杂度。 …...

vue+elementui+nodejs机票航空飞机航班查询与推荐

语言 node.js 框架&#xff1a;Express 前端:Vue.js 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat 开发软件&#xff1a;VScode )本系统主要是为旅客提供更为便利的机票预定方式&#xff0c;同时提高民航的预定机票的工作效率。通过网络平台实现信息化和网络化&am…...

将ssh发布密钥添加到服务器的ssh授权密钥中,但是为什么我仍然无法ssh登录到此服务器?

我已经将ssh发布密钥添加到服务器的ssh授权密钥中&#xff0c;但是为什么我仍然无法ssh登录到此服务器&#xff1f; 即使将ssh公钥添加到服务器的授权密钥中&#xff0c;您也可能无法通过SSH登录到服务器&#xff0c;这有几个原因: 1.服务器的authorized_keys文件的权限不正确…...

LeetCode——子串能表示从 1 到 N 数字的二进制串

1016. 子串能表示从 1 到 N 数字的二进制串 - 力扣&#xff08;Leetcode&#xff09; 目录 一、题目 二、题目解读 三、代码 一、题目 给定一个二进制字符串 s 和一个正整数 n&#xff0c;如果对于 [1, n] 范围内的每个整数&#xff0c;其二进制表示都是 s 的 子字符串 &…...

看火山引擎DataLeap如何做好电商治理(二):案例分析与解决方案

接上篇&#xff0c;以短视频优质项目为例&#xff0c;火山引擎DataLeap平台治理团队会去对每天发布的这种挂购物车车短视频打上标签&#xff0c;识别这些短视频它是优质的还是低质的&#xff0c;以及具体原因。一个视频经过这个模型识别之后&#xff0c;会给到奖惩中心去做相应…...

MySQL笔记-多表查询

本文标签 : 多表查询 事务四大特性 并发事务问题 事务隔离级别 文章目录 目录 文章目录 一、多表查询 1.多表关系 2.多表查询概念 3.多表查询的分类 4.内连接 5.外连接 6.自连接 7.联合查询 8.子查询 1.标量子查询 2.列子查询 3.行子查询 4.表子查询 9.多表查询案例练习 二…...

如何用100天时间,让CSDN的粉丝数从0狂飙到10000

2022年10月7日&#xff0c;正式开通了CSDN账号。但因为工作忙的原因&#xff0c;一直没有时间写博客文章&#xff0c;也没有投入精力在CSDN上。理所当然的&#xff0c;我的粉丝数量很稳定&#xff0c;一直保持着0的记录。 2023年春节假期过后&#xff0c;有点空闲时间了&#x…...

各种同质图神经网络模型的理论和节点表征学习任务的集合包rgb_experiment

诸神缄默不语-个人CSDN博文目录 最近更新时间&#xff1a;2023.5.10 最早更新时间&#xff1a;2023.5.10 本文仅考虑同质图setting下的模型。 对于异质图场景&#xff0c;可以参考我写的另一篇博文&#xff1a;异质图神经网络&#xff08;持续更新ing…&#xff09; node2ve…...

【C++进阶之路】类和对象(中)

文章目录 前言六大默认成员函数 一.构造函数性质默认构造函数构造函数(需要传参) 二.析构函数性质默认析构函数练习 三.拷贝构造函数基本性质&#xff1a;形参必须是引用默认拷贝构造浅拷贝深拷贝自定义类型 四.赋值运算符重载函数基本特征全局的运算符重载函数局部的运算符重载…...

AIMD 为什么收敛(tcp reno/cubic 为什么好)

TCP 拥塞控制目标是缓解并解除网络拥塞&#xff0c;让所有流量公平共享带宽&#xff0c;合在一起就是公平收敛。 AIMD(几乎所有与拥塞控制相关的协议或算法都有 AIMD 的影子&#xff0c;包括 RoCE&#xff0c;BBRv2) 为什么收敛&#xff1f;我一般会给出下面的老图&#xff1a;…...

医院智能导诊系统,医院导航解决方案

随着现代医院规模不断扩大&#xff0c;功能区域越来越细化&#xff0c;面对复杂的楼宇结构&#xff0c;集中的就诊人流&#xff0c;患者在就诊中经常会面临找不到目的地的困境&#xff0c;就诊体验变差。针对这个问题&#xff0c;一些面积和规模都比较大的医院&#xff0c;已经…...

【论文复现】基于区块链的分布式光伏就地消纳交易模式研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

在滴滴和字节跳动划水4年,过于真实了...

先简单交代一下吧&#xff0c;沅哥是某不知名211的本硕&#xff0c;18年毕业加入滴滴&#xff0c;之后跳槽到了头条&#xff0c;一直从事测试开发相关的工作。之前没有实习经历&#xff0c;算是四年半的工作经验吧。 这四年半之间他完成了一次晋升&#xff0c;换了一家公司&am…...

tensorflow GPU训练环境布置

tensorflow GPU训练环境布置 一、显卡驱动安装1.1 如何处理**Failed to initialize NVML: Driver/library version mismatch的问题**1.2 卸载旧的版本1.3 驱动安装 1.3.1 利用apt 安装1.3.2 手动安装 二、安装CUDA2.1 确定CUDA版本2.2 下载文件1. 找匹配版本2. 选合适的平台 2…...

理解和使用Java中的枚举

枚举是一种特殊的数据类型&#xff0c;用于定义一组具名的常量。Java中的枚举类型可以包含多个枚举常量&#xff0c;每个常量都具有唯一的名称和值。本文将详细介绍Java中的枚举&#xff0c;包括为什么要使用枚举、枚举的好处、如何定义和使用枚举等。 为什么要使用枚举&#…...

C++和Java:哪种语言更适合你

C和Java&#xff1a;哪种语言更适合你 一、引言1 背景介绍2 问题阐述3 目的和意义 二、C与Java的介绍1 C的特点和优缺点2 Java的特点和优缺点3 两种语言的比较4 选择C的理由4.1 适合底层开发的特点4.2高效的编译器和运行速度4.3 自由且灵活的语言风格4.4 良好的内存管理能力 5 …...

FE_Vue学习笔记 框架的执行流程详解

1 分析脚手架结构 &#xff08;1&#xff09;CLI就是 command line interface 的缩写。Vue CLI官网&#xff1a;Vue CLI &#xff08;2&#xff09;安装过程&#xff1a; &#xff08;PS&#xff1a; 提前安装过node.js了&#xff0c;没有安装的可以打开这个&#xff1a;Downl…...

KingbaseES V8R6 等待事件之LWLock Buffer_IO

等待事件含义 当进程同时尝试访问相同页面时&#xff0c;等待其他进程完成其输入/输出(I/O)操作时&#xff0c;会发生LWLock:BufferIO等待事件。其目的是将同一页读取到共享缓冲区中。 每个共享缓冲区都有一个与LWLock:BufferIO等待事件相关联的I/O锁&#xff0c;每次都必须在共…...

桂院导航小程序 静态项目 二次开发教程

Gitee代码仓库&#xff1a;桂院导航小程序 先 假装 大伙都成功安装了静态项目&#xff0c;并能在 微信开发者工具 和 手机 上正确运行。 接着就是 将项目 改成自己的学校。 代码里的注释我就不说明了&#xff0c;有提到 我的学校 的文字都改成你自己的就行 1. 全局 app.json…...

即时通讯APP开发费用成本多少?

移动互联网的发展&#xff0c;为人们的通讯交流提供了非常多的便利&#xff0c;一些即时通讯APP的出现&#xff0c;将人与人的距离再一次缩短。通过即时通讯APP软件&#xff0c;人们可以随时随地了解身边发生的新鲜事物&#xff0c;以及和朋友探讨各类趣事&#xff0c;甚至可以…...