pointpillars代码阅读----疑惑篇

1. 在创建Voxelnet的时候,没有初始化的名字,如何找到对应的网络函数的:

使用:

    net = get_voxelnet_class(model_cfg.network_class_name)(。。。)

函数定义:

def get_voxelnet_class(name):
    global REGISTERED_NETWORK_CLASSES
    assert name in REGISTERED_NETWORK_CLASSES, f"available class: {REGISTERED_NETWORK_CLASSES}"
    return REGISTERED_NETWORK_CLASSES[name]

被调用:

@register_voxelnet
class VoxelNet(nn.Module):
    def __init__(self,
                 output_shape,
                 num_class=2,
                 。。。

问题:

REGISTERED_NETWORK_CLASSES初始化是空集,如何出来了两个元素的。

可能原因:

(1)在被调用函数前是一个函数修饰器(@):

装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能。装饰器的作用就是为已经存在的对象添加额外的功能。

@register_voxelnet
class VoxelNet(nn.Module):

也就是说,上面的这个结构也就是 VoxelNet=register_voxelnet(VoxelNet),其中在VoxelNet被调用之前,register_voxelnet函数就已经被调用了。register_voxelnet如下:

def register_voxelnet(cls, name=None):
    global REGISTERED_NETWORK_CLASSES
    if name is None:
        name = cls.__name__
    assert name not in REGISTERED_NETWORK_CLASSES, f"exist class: {REGISTERED_NETWORK_CLASSES}"
    REGISTERED_NETWORK_CLASSES[name] = cls
    return cls

debug发现,所以运行的过程是:

第一,register_voxelnet函数预先生成REGISTERED_NETWORK_CLASSES集合。
第二,运行加载名称函数net = get_voxelnet_class(model_cfg.network_class_name)
第三,运行网络构造函数VoxelNet

自己新建的函数名称,需要在__iniy__.py文件中加入进去。

2.dataloader部分

  • 制作database

这一步是在create_data的操作。不细看了。

  • voxel_generator

(1)过程:voxel_builder.build–>VoxelGeneratorV2(一些参数)–>points_to_voxel(把点划分到格子中)
-------------------------------VoxelGeneratorV2过程的参数定义-------------------------------------------

属性 shape 含义
_coor_to_voxelidx [400,1280,1056]
_voxel_size 3 = [0.05,0.05,0.1]
_point_cloud_range 6 = [0.0,-32,-3,52.8,32,1.0]
_max_num_points 1 =5
_max_voxels 1 =20000
_grid_size 3 =[1056,1280,40]
_full_mean bool = False
_block_filtering bool = False
_block_factor 1 =0
_height_threshold 1 =0.0
_block_size 1 =0.0
_height_high_threshold 1 =0.0

-------------------------------points_to_voxel -把点划分到格子中-------------------------------------------

函数定义如下

def points_to_voxel(points,
                    voxel_size,
                    coors_range,
                    coor_to_voxelidx,
                    max_points=35,
                    max_voxels=20000,
                    full_mean=False,
                    block_filtering=True,
                    block_factor=1,
                    block_size=8,
                    height_threshold=0.2,
                    height_high_threshold=3.0,
                    pad_output=False):

关于参数的解释如下:

输入参数 解释
points [N, ndim] float tensor. 前3个维度表示(x,y,z),后面的为其他信息
voxel_size voxel size
coors_range voxel range
coor_to_voxelidx
max_points int array. used as a dense map. 密集表示[40,1056,1280]
max_voxels for voxelnet, 20000 is a good choice
full_mean bool. if true, all empty points in voxel will be filled with mean of exist points.
block_filtering filter voxels by height. used for lidar point cloud.
返回参数 解释
voxels [M, max_points, ndim] float tensor. only contain points.注意到只有含有点的voxels,M表示的在一个batch中含有点的voxel的个数.max_points=5。也就是 [含有点的voxel个数,5,4]
coordinates [M, 3] int32 tensor. zyx format,点云中所有点的个数的坐标
num_points_per_voxel [M] int32 tensor。每一个含有点的voxel中含有点的个数,最大为5

好吧,这一个函数并没有多大的用处,看下一个吧!!!

  • example中prep_pointcloud函数
    函数解释如下:

convert point cloud to voxels, create targets if ground truths exists.
也就是把点放入voxel中,以及得到gt的targets方便用于Loss的计算

部分内容如下:
pointpillars代码阅读----疑惑篇_第1张图片

  • create targets

考察如何建立起voxel和gt之间的关系的.
重要的代码在target_assigner.py文件中的generate_anchors_dict

        for anchor_generator, match_thresh, unmatch_thresh, fsize in zip(
                self._anchor_generators, matched_thresholds,
                unmatched_thresholds, feature_map_sizes):
。。。

设置了一堆>0.6和小于0.4IOU参数,应该是用于判定pos和neg的。

  • dataset中都有些什么

dataset 也就是训练数据集。包含四个主要部分:

(1)_class_names:也就是car,pedestrain,cyclist和van
(2)_kitti+infos:在creat_data.py文件运行时建立的数据信息整合,每一个子项对应着该个item的pc位置,image位置,cliab位置和对应的annos标注.
(3)_prep_func:一些参数,比如需要shuffe,voxel_generater等,如下:
pointpillars代码阅读----疑惑篇_第2张图片
尤其是anchor_cache感觉内容挺多的:
在这里插入图片描述
(4)root_path

  • anchor_cache 内容
    anchor_cacahe主要也是由5部分组成,前2个部分分别是对应的7个维度的三维anchor和4个维度的二维anchor,3~4应该是对应的IOU为多大为预测时的预测准确的,前四个部分的shape都是包含4个类的,大小也都168960的shape,(42240*4).最后一个部分应该是gt的部分,如下:

pointpillars代码阅读----疑惑篇_第3张图片

(1)每一个类别都分别对应anchor,matched_threshold和unmatch_threshold.
(2)每一种都是42240对应的大小.
(3)对于IOU:car[0.6,0.45],cyclist[0.35,0.2],pedestrain[0.35,0.2],Van[0.6,0.45]
(4)目前的anchor应该只有anchor的形式,没有内容.

3 回归Loss的fea内容

在计算loss的时候,如下:

 loc_losses = loc_loss_ftor(
        box_preds, reg_targets, weights=reg_weights)  # [N, M]

这里的reg_targets和box——pred大小都是 [ b s , 160 ∗ 132 ∗ 8 , 7 ] [bs,160∗132∗8,7] [bs,1601328,7],问题是:

1.作者又是如何把gt从三维降到二维。
2.reg_targets是gt的feature,对于[1601328]个anchor,里边肯定具有很多不是pos的anchor,那么这些不是pos的anchor对应的内容又是什么呢?

  • gt从三维降到二维

不用从三维降到二维,初始化anchor时,是在xy平面上每隔(0.4,0.4)则得到一个anchor(7个维度),最终也就是[160,132,7]而不是[1280,1056,7]。然后再根据anchor和gt之间分别的IOU来确定对应的labels和reg。

  • 不是pos的anchor对应的内容又是什么呢

是pos的gt的anchor的7个维度是[x,y,z,w,h,l,yaw],而neg则全是-1.

4 voxel和anchor的区别与联系

  • 区别

(1)voxel是划分格子提取特征的,其每个格子的size是[0.05,0.05,0.1],在一块点云中划分出来的size是[1280,1056,40],同时在z轴方向上也是有格子的;anchor划分时是根据feature_map_size的大小来设定的,其中feature_map_size大小是根据config中的下采样因子(=8)来的,该feature_map_size要对应到后面经过rpn之后的feature_map大小[bs,160,132,2*channel],同时,anchor在z轴上是没有的,仅仅在xy平面上存在。

  • 联系

对Non-empty的voxel提取特征后,scatter回[bs,1280,1056,channels]的voxel中,然后使用稀疏卷积mid_spconv进行3D特征提取,到[bs,2,160,132,cahnnes]–>[bs,2*channel,160,132](这个经过3D稀疏卷积的fea-map就是featuremapsize,大小刚好和anchor的一样,只是anchor是在原始点云的空间中根据这里的feature-map的大小生成的,但是在实际中,这里的feature实际上是和mid_cov相关的而不是和config的downsample_factor没有关系,因此如果修改anchor的feature_map,也要相应的修改mid_cov的层次结构),后再通过rpnhead的处理得到上采样的组合的fea-map[bs,256,160,132],然后进行回归和预测。

你可能感兴趣的:(深度学习-点云基础网路-分类)