草庐IT

MMDetection3D库中的一些模块介绍

byzy 2024-05-15 原文

本文目前仅包含2个体素编码器、2个中间编码器、1个主干网络、1个颈部网络和1个检测头。如果有机会,会继续补充更多模型。
若发现内容有误,欢迎指出。

  MMDetection3D的点云数据一般会经历如下步骤/模块:

训练阶段
测试阶段
点云
体素化
体素编码器
中间编码器
主干网络
颈部网络
检测头
损失函数计算
预测结果生成

  下面分别介绍每个部分的一些典型模型。

0. 体素化函数

  在介绍体素编码器前,需要先介绍体素化函数,以理解体素编码器的输入参数含义。

0.1 mmcv.ops.voxelize中的Voxelization类

  • 初始化参数:
参数名称数据类型默认值含义取值说明
max_voxels(int, int)-最大体素数两个元素分别表示训练时和测试时的最大体素数
max_num_pointsint-体素内最大点数记为 M M M
point_cloud_rangeList(float)点云范围列表长为6,依次表示 x , y , z x,y,z x,y,z方向的最小值和 x , y , z x,y,z x,y,z方向的最大值,即[x_min,y_min,z_min,x_max,y_max,z_max]
voxel_sizeList(float)-每个体素的大小列表长为3,依次表示体素的 x , y , z x,y,z x,y,z尺寸,即[x_size,y_size,z_size]

注:将体素大小z_zise设置为与点云高度范围相同时,就可以实现柱体化操作。

  • forward函数:
参数名称数据类型默认值含义取值说明
inputTensor(float)-点云特征 ( n p , C ) (n_p,C) (np,C),其中 n p n_p np为点的数量, C C C为通道维度
featuresTensor(float)返回值1每个体素内的点 ( n , M , C ) (n,M,C) (n,M,C),其中 n n n为非空体素数,若第 i i i个体素内的点数 m i < M m_i<M mi<M,则features[i,j,:] j ≥ m i j\geq m_i jmi)为零向量
num_pointsTensor(int)返回值2每个体素内的点数 ( n , ) (n,) (n,),其中第 i i i个体素内的点数为num_points[i](即上文的 m i m_i mi
coorsTensor(int)返回值3每个体素的3维位置索引 ( n , 3 ) (n,3) (n,3),其中3表示z_id,y_id,x_id

0.2 MVXTwoStageDetector类中的体素化函数voxelize

参数名称数据类型默认值含义取值说明
pointsList(Tensor(float))-一个batch的点云列表长为batch size,其第 i i i个元素大小为 ( n i , p , C ) (n_{i,p},C) (ni,p,C)
voxelsTensor(float)返回值1每个体素内的点 ( N , M , C ) (N,M,C) (N,M,C),其中 N N N为整个batch的总非空体素数,即 N = ∑ i n i N=\sum_i n_i N=ini
num_pointsTensor(int)返回值2每个体素内的点数大小为 ( N , ) (N,) (N,)
coorsTensor(int)返回值3每个体素的batch索引和3维位置索引 ( N , 4 ) (N,4) (N,4),其中4表示batch_id,z_id,y_id,x_id

1. 体素编码器(VOXEL_ENCODERS)

1.1 HardSimpleVFE

  • 作用:将体素内的点取平均作为体素特征。通常搭配SparseEncoder中间编码器。
  • 初始化参数:
参数名称数据类型默认值含义取值说明
num_featuresint-点云的特征维度记为 C C C
  • forward函数:
参数名称数据类型默认值含义取值说明
featuresTensor(float)-每个体素内的点大小为 ( N , M , C ) (N,M,C) (N,M,C),可为MVXTwoStageDetector类中的voxelize函数输出
num_pointsTensor(int)-每个体素内的点数大小为 ( N , ) (N,) (N,),可为MVXTwoStageDetector类中的voxelize函数输出
coorsTensor(int)-每个体素的batch索引和3维位置索引大小为 ( N , 4 ) (N,4) (N,4),可为MVXTwoStageDetector类中的voxelize函数输出(在本函数中无实际作用,仅为和其余体素编码器有相同的输入)
返回值Tensor(float)返回值非空体素特征大小为 ( N , C ) (N,C) (N,C)

1.2 PillarFeatureNet

  用于点云的柱体表达编码。通常搭配PointPillarsScatter中间编码器。

  • 初始化参数:
参数名称数据类型默认值含义取值说明
in_channelsint-柱体的特征维度记为 C C C
feat_channelsTuple(int)--长度表示图中PFN的数量 N N N,第 i i i个元素表示第 i i i个PFN的输出通道数
with_distanceboolFalse表示是否将点到原点的距离附加在点的通道维度-
with_cluster_centerboolTrue表示是否将点到体素质心的三维偏移量附加在点的通道维度-
with_voxel_centerboolTrue表示是否将点到体素中心的三维偏移量附加在点的通道维度-
voxel_sizeList(float)-每个体素的大小列表长为3,依次表示体素的 x , y , z x,y,z x,y,z尺寸,即[x_size,y_size,z_size]
point_cloud_rangeTuple(float)-点云范围长为6,依次表示 x , y , z x,y,z x,y,z方向的最小值和 x , y , z x,y,z x,y,z方向的最大值,即[x_min,y_min,z_min,x_max,y_max,z_max]
norm_cfgdict归一化类型默认为BN1d设置归一化类型配置文件格式
modestr池化类型默认为最大池化设置池化类型'max’表示最大池化,'avg’表示均值池化
legacyboolTrue-若为True,会导致with_cluster_center=True时影响到原始特征,且若此时with_distance=True,则附加的特征会变为到体素中心的距离而非到原点的距离;为False时结果正常

2. 中间编码器(MIDDLE_ENCODERS)

2.1 SparseEncoder

  • 初始化参数:
参数名称数据类型默认值含义取值说明
in_channelsint-输入通道数记为 C C C
sparse_shapeList(int)-体素空间的shape列表长为3,依次表示 z , y , x z,y,x z,y,x方向的体素数
orderTuple(str)(‘conv’, ‘norm’, ‘act’)表示卷积、归一化和激活函数的顺序-
norm_cfgdict归一化类型默认为BN1d归一化类型设置配置文件格式
base_channelint-第一个卷积的输出通道数-
output_channelsint-最后一个卷积的输出通道数-
encoder_channelsTuple(Tuple(int))-每层的输出通道维度外层元组长度为阶段数(图中 N N N),内层元组长度为每阶段层数(图中 L L L
encoder_paddingsTuple(Tuple(int))-每层的填充值内外层元组长度分别与encoder_channels相同
block_typestr-使用的模块类型可为’conv_module’或’basicblock’(区别如图)
  • forward函数:
参数名称数据类型默认值含义取值说明
voxel_featuresTensor(float)-非空体素特征 ( N , C ) (N,C) (N,C) N N N为体素数;该参数通常是VOXEL_ENCODERS的输出
coorsTensor(int)-非空体素坐标 ( N , 4 ) (N,4) (N,4),该参数通常是体素化函数的输出
batch_sizeint-batch size记为 B B B
spatial_featuresTensor(float)返回值BEV特征图大小为 ( B , C ′ , H , W ) (B,C',H,W) (B,C,H,W),其中 H H H为宽度(y_size), W W W为长度(x_size

2.2 PointPillarsScatter

  用于点云的柱体表达编码。可搭配PillarFeatureNet体素编码器。

  • 作用:将柱体特征根据柱体坐标和batch_id生成BEV特征图。
  • 初始化参数:
参数名称数据类型默认值含义取值说明
in_channelsint-输入通道数-
output_shapeList(int)-输出BEV特征图的大小长度为2,分别为BEV特征图的宽度 H H Hy_size)和长度 W W Wx_size

3. 主干网络(BACKBONES)

3.1 SECOND

  SECOND主干网络通常搭配SECONDFPN颈部网络。前面可搭配体素操作(如HardSimpleVFE + SparseEncoder)或柱体操作(如PillarFeatureNet + PointPillarsScatter)。

  • 初始化参数:
参数名称数据类型默认值含义取值说明
in_channelsint-输入的体素特征维度-
out_channelsList(int)-每个阶段的输出通道数长度为图中 L L L
layer_numsList(int)-每阶段的卷积层数(图中 N N N长度与out_channels相同
layer_stridesList(int)-每阶段第一个卷积的步长长度与out_channels相同
conv_cfgdict默认卷积类型为Conv2d设置卷积类型配置文件格式
norm_cfgdict默认归一化类型为BN设置归一化类型配置文件格式
  • forward函数:
参数名称数据类型默认值含义取值说明
xTensor(float)-点云的BEV表达 ( B , C , H , W ) (B,C,H,W) (B,C,H,W),通常为MIDDLE_ENCODERS的输出
返回值List(Tensor(float))返回值输出为点云的多尺度BEV特征列表长度等于尺度数,每个尺度特征图大小为 ( B , C i , H i , W i ) (B,C_i,H_i,W_i) (B,Ci,Hi,Wi)

4. 颈部网络(NECKS)

4.1 SECONDFPN

  SECONDFPN颈部网络通常搭配SECOND主干网络。

  • 初始化参数:
参数名称数据类型默认值含义取值说明
in_channelsList(int)-表示各尺度特征通道数与SECOND的out_channels相同
out_channelsList(int)-每个DeConv的输出通道数长度为图中 L L L
upsample_stridesList(int)-上采样步长每个上采样块的上采样比例
conv_cfgdict默认卷积类型为Conv2d设置卷积类型配置文件格式
norm_cfgdict默认归一化类型为BN设置归一化类型配置文件格式
upsample_cfgdict默认上采样方式为DeConv上采样方式配置文件格式
use_conv_for_no_strideboolFalse--

use_conv_for_no_stride=False且upsample_stride=1时,或upsample_stride>1时使用upsample_cfg搭建DeConv卷积,否则(即use_conv_for_no_stride=True且upsample_stride=1,或upsample_stride<1)使用conv_cfg搭建Conv2d卷积

  • forward函数:
参数名称数据类型默认值含义取值说明
xList(Tensor(float))-点云多尺度BEV特征列表长度为尺度数,可直接使用SECOND的输出
返回值List(Tensor(float))返回值多尺度融合后的BEV特征列表长度为1

5.检测头(DENSE_HEADS)

检测头模块需要注意两点:
  一是loss函数的计算以及预测结果的生成均是在检测头中实现的方法;
  二是检测头初始化一般都有train_cfg和test_cfg两个参数,但在配置文件中,这两个参数往往需要写到检测器模型(DETECTOR)中而非检测头中。

5.1 CenterHead

  CenterPoint的检测头。可搭配SECOND + SECONDFPN结构使用。

  • 初始化参数:
参数名称数据类型默认值含义取值说明
in_channelsList(int)-输入通道数与颈部网络的输出通道数相同
shared_conv_channelint-第一个共享卷积的输出通道维度-
biasstr’auto’第一个共享卷积层的偏置项设置-
tasksList(dict)-dict为{'num_class': int, 'class_names': List(str)}的结构;列表的每一个元素对应图中的一个SeperateHead结构(即对不同的类别,head的网络参数可能不同)
num_heatmap_convsint-每个中心热图头的卷积数-
common_headsdict--可包含如’reg’(BEV位置偏差)、‘hei’(离地高度)、‘dim’(尺寸)、‘rot’(旋转角)、‘vel’(速度)等项;每一项的值为二元组(int,int):第一元素为最终维度,第二元素为head中的卷积层数(对应图中 N N N
norm_bboxboolTrue是否对数归一化边界框尺寸作为估计值-
conv_cfgdict默认卷积类型为Conv2d设置卷积类型配置文件格式
norm_cfgdict默认归一化类型为BN2d设置归一化类型配置文件格式
bbox_coderdict默认BBOX_CODERS类型为CenterPointBBoxCoder类设置BBOX_CODERS类型配置文件格式
loss_clsdict默认LOSS类型为GaussianFocalLoss设置分类任务的LOSS类型配置文件格式
loss_bboxdict默认LOSS类型为L1Loss设置回归任务的LOSS类型配置文件格式
seperate_headdict默认为SeperateHead类设置SeperateHead的参数配置文件格式,其中需要手动设置的初始化参数包括:head_conv为Head卷积的中间维度;final_kernal为Head卷积核大小

  train_cfg和test_cfg均为字典格式,这里单独拿出来介绍:

  • train_cfg包含:
参数名称数据类型含义取值说明
grid_sizeList(int)原始体素空间的shape列表长为3,依次表示 x , y , z x,y,z x,y,z方向的体素数
point_cloud_rangeList(float)点云范围列表长为6,依次表示 x , y , z x,y,z x,y,z方向的最小值和 x , y , z x,y,z x,y,z方向的最大值,即[x_min,y_min,z_min,x_max,y_max,z_max]
voxel_sizeList(float)体素大小列表长为3,依次表示体素的 x , y , z x,y,z x,y,z尺寸,即[x_size,y_size,z_size]
out_size_factorint下采样倍数最后BEV预测的大小为grid_size//out_size_factor
max_objsint最大检测物体数量会取至多max_objs个物体计算热图回归目标
dense_regfloat与max_objs相乘作为最终的最大检测数量可固定为1,仅设置max_objs即可
gaussian_overlapfloat计算高斯半径时的参数与真实物体尺寸一起用于计算高斯半径,从而生成热图的真值
min_radiusfloat最小高斯半径防止上述计算出来的高斯半径过小
code_weightsList(float)计算损失时的各项权重长度与边界框参数编码项数相同,如边界框编码包含3维位置、3维尺度,以及朝向角的正余弦值则长度应为8
  • test_cfg包含:
参数名称数据类型含义取值说明
post_center_limit_rangeList(float)后处理时物体中心的范围列表长为6,依次表示 x , y , z x,y,z x,y,z方向的最小值和 x , y , z x,y,z x,y,z方向的最大值,即[x_min,y_min,z_min,x_max,y_max,z_max];该范围一般略大于点云范围
nms_typestrNMS方法的类型只能是’circle’(CenterPoint文章提到的NMS方法)或’rotate’(常规的NMS方法)
nms_thrfloatrotate NMS的IoU阈值仅在nms_type='rotate’时需要设置
score_thresholdfloatrotate NMS的分数筛选阈值仅在nms_type='rotate’时需要设置,nms前仅筛选满足分数大于该阈值的物体
pre_max_sizeintrotate NMS前考虑的最大物体数量仅在nms_type='rotate’时需要设置,多余的预测会被丢弃(若需要全部考虑,可设置为None)
post_max_sizeintrotate NMS或circle NMS后保留的最大物体数量-
min_radiusList(float)circle NMS的最小半径仅在nms_type='circle’时需要设置,长度为tasks数;第 i i i项对应第 i i i个task的物体BEV中心距离阈值
  • forward函数(训练和测试阶段均会调用):
参数名称数据类型默认值含义取值说明
featsList(Tensor(float))-(多尺度)特征图通常为颈部网络的输出
返回值Tuple(List(dict))返回值BEV上的预测结果外层元组长为任务数,内层列表长为尺度数,字典的键为’heatmap’以及common_heads中的键(如’reg’、‘hei’、‘dim’、‘rot’),值为相应Head的输出Tensor(大小为 ( B , ∗ , h , w ) (B,*,h,w) (B,,h,w)
  • loss函数(训练阶段调用):
参数名称数据类型默认值含义取值说明
pred_dictsTuple(List(dict))-BEV下的预测结果检测头模块forward函数的输出结果
gt_bboxes_3dList(Tensor(float))-真实边界框参数列表长为batch size,Tensor为 ( n b , box_dim ) (n_b,\textup{box\_dim}) (nb,box_dim),其中 n b n_b nb表示该帧的真实边界框数量
gt_labels_3dList(Tensor(int))-真实边界框类别标签列表长为batch size,Tensor为 ( n b , ) (n_b,) (nb,)
返回值dict返回值损失字典包含各任务的分类损失和回归损失,格式为{'task0.loss_heatmap': float, 'task0.loss_bbox': float, 'task1.loss_heatmap': float, ...}
  • get_bboxes函数(测试阶段调用):
参数名称数据类型默认值含义取值说明
pred_dictsTuple(List(dict))-BEV预测下的预测结果检测头模块forward函数的输出结果
img_metasList(dict)-数据信息检测器模型forward函数输入中的img_meta项;列表长为batch size
返回值List(List(Tensor))-最终的检测结果外层列表长为batch_size,内层列表长为3,分别是预测的边界框参数 ( n b pred , box_dim ) (n_b^\textup{pred},\textup{box\_dim}) (nbpred,box_dim)、分数 ( n b pred , ) (n_b^\textup{pred},) (nbpred,)和类别标签 ( n b pred , ) (n_b^\textup{pred},) (nbpred,)

有关MMDetection3D库中的一些模块介绍的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  3. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  4. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  5. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  6. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  7. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  8. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  9. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  10. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

随机推荐