OpenPCDet系列 | 4.4 DataProcessor点云数据处理模块解析

DataProcessor模块解析

在对batch_data的处理中,经过了point_feature_encoder模块处理后,就轮到了进行data_processor处理。在data_processor的forward流程中比较简单,就是依次经过队列各模块处理即可,如下所示:

def forward(self, data_dict):
    """
    Args:
        data_dict:
            points: (N, 3 + C_in)
            gt_boxes: optional, (N, 7 + C) [x, y, z, dx, dy, dz, heading, ...]
            gt_names: optional, (N), string
            ...

    Returns:
    """
    # 依次进行各类数据处理,不断更新data_dict
    for cur_processor in self.data_processor_queue:
        data_dict = cur_processor(data_dict=data_dict)

其中,这里的data_dict保留了是否启动某些数据增强的相关信息,以及具体确定的随机参数:

在这里插入图片描述

在pointpillars中主要进行3种数据处理,分别是:mask_points_and_boxes_outside_range、shuffle_points、transform_points_to_voxels;下面对别对着几个函数进行记录。


1. mask_points_and_boxes_outside_range

给定点云场景的一个限制范围limit_range: [minx, miny, minz, maxx, maxy, maxz],现在对超过这个范围的点进行过滤,同时对gt中心点在这个范围外也进行过滤。那么得到的结果是gt的部分点可能会因为这个范围限制而被截取。

核心函数与核心代码如下所示:

# 功能: 限制点云在限制范围集中,返回的是每个点云是否符合范围的掩码(布尔变量)
def mask_points_by_range(points, limit_range):
    """
    Args:
        points: (N, 4) 点云特征
        limit_range: [minx, miny, minz, maxx, maxy, maxz]
    """
    mask = (points[:, 0] >= limit_range[0]) & (points[:, 0] <= limit_range[3]) \
           & (points[:, 1] >= limit_range[1]) & (points[:, 1] <= limit_range[4])
    return mask
    
# 功能:移除范围外的gt
def mask_boxes_outside_range_numpy(boxes, limit_range, min_num_corners=1, use_center_to_filter=True):
    """
    Args:
        boxes: (N, 7) [x, y, z, dx, dy, dz, heading, ...], (x, y, z) is the box center
        limit_range: [minx, miny, minz, maxx, maxy, maxz]
        min_num_corners: 1
        use_center_to_filter: True 是否利用gt中心店来进行采样
    Returns:

    """
    if boxes.shape[1] > 7:
        boxes = boxes[:, 0:7]   # 这里去除最后一位的类别id
    if use_center_to_filter:
        box_centers = boxes[:, 0:3]     # 提取xyz中心位置信息
        mask = ((box_centers >= limit_range[0:3]) & (box_centers <= limit_range[3:6])).all(axis=-1)  # 中心点是否在限制范围内
    return mask

2. shuffle_points

随后根据点数量构建一个随机顺序的索引序列,然后根据这个随机的索引序列对点云进行重新编排点顺序,核心代码如下所示:

# 训练过程打乱,测试过程不打乱
if config.SHUFFLE_ENABLED[self.mode]:
    points = data_dict['points']
    shuffle_idx = np.random.permutation(points.shape[0])    # 生成随机序列索引
    points = points[shuffle_idx]    # 根据索引重新编排点顺序
    data_dict['points'] = points

3. transform_points_to_voxels

这部分的具体执行代码调用了sponv进行稀疏卷积,将点场景转换为voxel场景,核心代码如下所示:

# 功能:将点云转换为voxel,调用spconv的VoxelGeneratorV2
def transform_points_to_voxels(self, data_dict=None, config=None):
    # 初始化确认网格大小与体素大小
    if data_dict is None:
        grid_size = (self.point_cloud_range[3:6] - self.point_cloud_range[0:3]) / np.array(config.VOXEL_SIZE)   # 网格数量
        self.grid_size = np.round(grid_size).astype(np.int64)   # 四舍五入取整
        self.voxel_size = config.VOXEL_SIZE      # 从配置文件中获取指定的体素大小
        # just bind the config, we will create the VoxelGeneratorWrapper later,
        # to avoid pickling issues in multiprocess spawn
        return partial(self.transform_points_to_voxels, config=config)

    if self.voxel_generator is None:
        self.voxel_generator = VoxelGeneratorWrapper(
            vsize_xyz=config.VOXEL_SIZE,   # 体素大小 [0.16, 0.16, 4]
            coors_range_xyz=self.point_cloud_range,     # 场景范围 [0, -39.68, -3, 69.12, 39.68, 1]
            num_point_features=self.num_point_features, # 每个点特征数量 4
            max_num_points_per_voxel=config.MAX_POINTS_PER_VOXEL,   # 每个voxel最大点云数 32
            max_num_voxels=config.MAX_NUMBER_OF_VOXELS[self.mode],  # 场景的最大voxel数 训练模式是 16000
        )

    # 调用spconv的voxel_generator的generate方法生成体素
    points = data_dict['points']
    voxel_output = self.voxel_generator.generate(points)
    voxels, coordinates, num_points = voxel_output
    """
        voxels: (num_voxels, max_points_per_voxel, 3 + C)  表示每个体素中有32个点云,每个点有3+C(4)和特征维度
        coordinates: (num_voxels, 3)     在点云场景中voxel的位置信息,pointpillars算法这里的voxel就是pillars,所以只有平面上的2d坐标,没有z维度切分
        num_points: (num_voxels)         表示每个voxel内的有效点数量
    """
    
    ......

在data_process模块处理完后,单帧点云场景的数据处理流程就此结束了,剩下的就是就是收集batch_size各如此的单帧点云数据构建成一个batch数据,然后对batch数据进行处理。


猜你喜欢

转载自blog.csdn.net/weixin_44751294/article/details/130562609
4.4
今日推荐