基于OpenPCDet框架和kitti数据集格式的自制纯点云数据集的深度学习训练

使用labelCloud打标签

安装与使用(参考安装与使用

git clone https://github.com/ch-sa/labelCloud.git
conda create -n label3.8 python=3.8 -y
conda activate label3.8
pip install -r requirements.txt
python labelCloud.py

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

1.点击Span Bounding Box开始标注
2.box微调控制台,1标注完用它调整位置和大小
3.标注信息的显示

OpenPCDet数据准备与源码阅读

data文件

在这里插入图片描述

1.ImageSets:存放数据索引号
2.label_2:存放标签文件
3.数据集中的点云
注意文件名要对应,标签文件勿改动

数据集预处理,生成数据.pkl

python3 -m pcdet.datasets.custom.custom_dataset create_custom_infos tools/cfgs/dataset_configs/custom_dataset.yaml
下面阅读custom_dataset.py的主要部分(不想了解代码的请跳过)
if __name__=='__main__':
    import sys
    if sys.argv.__len__() > 1 and sys.argv[1] == 'create_custom_infos':
        import yaml
        from pathlib import Path
        from easydict import EasyDict
        dataset_cfg = EasyDict(yaml.safe_load(open(sys.argv[2])))
        ROOT_DIR = (Path(__file__).resolve().parent / '../../../').resolve()
        create_custom_infos(
            dataset_cfg=dataset_cfg,
            class_names=['Car', 'Pedestrian', 'Cyclist'],
            data_path=ROOT_DIR / 'data' / 'custom',
            save_path=ROOT_DIR / 'data' / 'custom'
        )

主要执行 create_custom_infos()

def create_custom_infos(dataset_cfg, class_names, data_path, save_path, workers=4):
    #实例化CustomDataset类对象dataset
    dataset = CustomDataset(dataset_cfg=dataset_cfg, class_names=class_names, root_path=data_path, training=False)
    train_split, val_split = 'train', 'val'

    # No evaluation
    train_filename = save_path / ('custom_infos_%s.pkl' % train_split)
    val_filenmae = save_path / ('custom_infos%s.pkl' % val_split)
    trainval_filename = save_path / 'custom_infos_trainval.pkl'
    test_filename = save_path / 'custom_infos_test.pkl'

    print('------------------------Start to generate data infos------------------------')

    dataset.set_split(train_split)
    custom_infos_train = dataset.get_infos(num_workers=workers, has_label=True, count_inside_pts=True)
    with open(train_filename, 'wb') as f:
        pickle.dump(custom_infos_train, f)
    print('Custom info train file is save to %s' % train_filename)

    dataset.set_split('test')
    custom_infos_test = dataset.get_infos(num_workers=workers, has_label=False, count_inside_pts=False)
    with open(test_filename, 'wb') as f:
        pickle.dump(custom_infos_test, f)
    print('Custom info test file is saved to %s' % test_filename)

    print('------------------------Start create groundtruth database for data augmentation------------------------')
    dataset.set_split(train_split)
    # Input the 'custom_train_info.pkl' to generate gt_database
    dataset.create_groundtruth_database(train_filename, split=train_split)
    print('------------------------Data preparation done------------------------')

实例化CustomDataset创建对象dataset
dataset = CustomDataset(dataset_cfg=dataset_cfg, class_names=class_names, root_path=data_path, training=False)

给idataset的属性sample_id_list赋值,sample_id_list是一个存放了所有数据名字的列表
dataset.set_split(train_split)

def set_split(self, split):
        super().__init__(
            dataset_cfg=self.dataset_cfg, class_names=self.class_names, training=self.training, root_path=self.root_path, logger=self.logger
        )
        self.split = split
        self.root_split_path = self.root_path / ('training' if self.split != 'test' else 'testing')

        #这段代码是用于获取样本索引列表 sample_id_list 的值
        split_dir = self.root_path / 'ImageSets' / (self.split + '.txt')#split_dir= /home/kin/workspace/OpenPCDet/data/custom/ImageSets/train.txt
        print("split_dir=",split_dir)
        self.sample_id_list = [x.strip() for x in open(split_dir).readlines()] if split_dir.exists() else None

split_dir是train.txt的绝对路径,如split_dir= /home/kin/workspace/OpenPCDet/data/custom/ImageSets/train.txt

在这里插入图片描述

open(split_dir).readlines() 返回一个list,每个元素是一行的字符串,如[‘000000’,‘000001’,‘000002’,‘000003’,‘000004’,‘000005’,‘000006’,‘000007’]
x.strip()方法常用于清除字符串中的不必要的空白字符

get_infos()

def get_infos(self, num_workers=4, has_label=True, count_inside_pts=True, sample_id_list=None):
        import concurrent.futures as futures

        # Process single scene
        def process_single_scene(sample_idx):...
   
        sample_id_list = sample_id_list if sample_id_list is not None else self.sample_id_list
        # create a thread pool to improve the velocity
        with futures.ThreadPoolExecutor(num_workers) as executor:
            infos = executor.map(process_single_scene, sample_id_list)
        # infos is a list that each element represents per frame
        return list(infos)

self.sample_id_list值赋给变量sample_id_list

infos = executor.map(process_single_scene, sample_id_list)
executor.map(function, iterable)executor.map() 方法会按顺序迭代 iterable 中的每个元素,并将每个元素作为参数传递给 function 进行处理
将读到train.txt里的数据集标号挨个给到process_single_scene()执行一次

def process_single_scene(sample_idx):
            print('%s sample_idx: %s' % (self.split, sample_idx))
            # define an empty dict
            info = {}
            # pts infos: dimention and idx
            pc_info = {'num_features': 4, 'lidar_idx': sample_idx}
            # add to pts infos
            info['point_cloud'] = pc_info

            # no images, calibs are need to transform the labels

            type_to_id = {'Car': 1, 'Pedestrian': 2, 'Cyclist': 3}
            if has_label:
                # read labels to build object list according to idx
                obj_list = self.get_label(sample_idx)
                # build an empty annotations dict
                annotations = {}
                # add to annotations ==> refer to 'object3d_custom' (no truncated,occluded,alpha,bbox)
                annotations['name'] = np.array([obj.cls_type for obj in obj_list]) # 1-dimension
                # hwl(camera) format 2-dimension: The kitti-labels are in camera-coord
                # h,w,l -> 0.21,0.22,0.33 (see object3d_custom.py h=label[8], w=label[9], l=label[10])
                annotations['dimensions'] = np.array([[obj.l, obj.h, obj.w] for obj in obj_list])             
                annotations['location'] = np.concatenate([obj.loc.reshape(1,3) for obj in obj_list])
                annotations['rotation_y'] = np.array([obj.ry for obj in obj_list]) # 1-dimension

                num_objects = len([obj.cls_type for obj in obj_list if obj.cls_type != 'DontCare'])
                num_gt = len(annotations['name'])
                index = list(range(num_objects)) + [-1] * (num_gt - num_objects)
                annotations['index'] = np.array(index, dtype=np.int32)

                loc = annotations['location'][:num_objects]
                dims = annotations['dimensions'][:num_objects]
                rots = annotations['rotation_y'][:num_objects]
                # camera -> lidar: The points of custom_dataset are already in lidar-coord
                # But the labels are in camera-coord and need to transform
                # loc_lidar = self.get_calib(loc)#由于使用labelCloud标注的格式是Untransformed,这里不用转换
                loc_lidar = loc
                l, h, w = dims[:, 0:1], dims[:, 1:2], dims[:, 2:3]
                # bottom center -> object center: no need for loc_lidar[:, 2] += h[:, 0] / 2
                # print("sample_idx: ", sample_idx, "loc: ", loc, "loc_lidar: " , sample_idx, loc_lidar)
                # get gt_boxes_lidar see https://zhuanlan.zhihu.com/p/152120636
                gt_boxes_lidar = np.concatenate([loc_lidar, l, w, h, (np.pi / 2 - rots[..., np.newaxis])], axis=1) # 2-dimension array
                annotations['gt_boxes_lidar'] = gt_boxes_lidar
                
                # add annotation info
                info['annos'] = annotations
            
            return info

获取对应索引标签文件的路径传给get_objects_from_label()

def get_label(self, idx):
        # get labels
        label_file = self.root_split_path / 'label_2' / ('%s.txt' % idx)
        print("label_file=",label_file)
        assert label_file.exists()
        return object3d_custom.get_objects_from_label(label_file)

打开标签文件,把标签文件的每一行作为一个字符串保存在lines[],便利lines[]每一个元素,传入Object3d类中实例化,在Object3d类中将标签文件的每一行元素中的每个元素解析出来作为Object3d的属性,最后便利完成生成一个objects列表,其中包含每个object的所有信息

object3d_custom.py

def get_objects_from_label(label_file):
    with open(label_file, 'r') as f:
        lines = f.readlines() #列表,每个元素是label.txt的一行元素再加一个换行符
        print("lines=",lines)
    objects = [Object3d(line) for line in lines]
    return objects # 返回一个标定文件中所有目标的列表
class Object3d(object):
    def __init__(self, line):
        label = line.strip().split(' ') #strip()方法去除字符串两端的空格和换行符,split(' ')方法将字符串按空格进行分割,返回一个由分割后的子字符串组成的列表
        self.src = line
        self.cls_type = label[0]
        self.cls_id = cls_type_to_id(self.cls_type)
        # print("RRRRRRR LABEL=",label)
        self.truncation = float(label[1])
        self.occlusion = float(label[2])  # 0:fully visible 1:partly occluded 2:largely occluded 3:unknown
        self.alpha = float(label[3])
        self.box2d = np.array((float(label[4]), float(label[5]), float(label[6]), float(label[7])), dtype=np.float32)
        self.h = float(label[8])
        self.w = float(label[9])
        self.l = float(label[10])
        self.loc = np.array((float(label[11]), float(label[12]), float(label[13])), dtype=np.float32)
        self.dis_to_cam = np.linalg.norm(self.loc)
        self.ry = float(label[14])
        self.score = float(label[15]) if label.__len__() == 16 else -1.0
        self.level_str = None
        self.level = self.get_custom_obj_level()

annotations{}通过遍历objects中的元素给对应的键赋值,形成最终的可使用的数据集合

在这里插入图片描述
以上分析了代码中的train的pkl生成过程,test,val原理相同,都是通过不同参数调用get_infos()形成,有了pkl,openpcdet框架就可以方便的调用数据进行训练了。写的有些乱,欢迎道友们一起沟通交流,未完待续
源码来自:
1.https://github.com/open-mmlab/OpenPCDet
2.https://github.com/OrangeSodahub/CRLFnet/blob/master/src/site_model/src/LidCamFusion/OpenPCDet/README.md(自定义纯点云数据集构建)

  • 12
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具 kitti数据集相关工具
要将DAIR-V2X数据集转换为Kitti数据集格式,你可以使用官方提供的命令行工具\[2\]。在命令行中运行以下命令: python tools/dataset_converter/dair2kitti.py --source-root ./data/DAIR-V2X/single-infrastructure-side \ --target-root ./data/DAIR-V2X/single-infrastructure-side \ --split-path ./data/split_datas/single-infrastructure-split-data.json \ --label-type lidar --sensor-view infrastructure 这个命令将会把DAIR-V2X数据集转换为Kitti数据集格式,并将结果保存在指定的目标路径中。在转换过程中,如果遇到错误,可能会出现一些问题。例如,你提到的错误\[3\]是由于在代码中使用了eval()函数,但是传入的参数不是一个字符串导致的。你可以检查代码中的相关部分,确保传入的参数是一个字符串。 请注意,转换过程可能需要一些时间,具体取决于数据集的大小和计算机的性能。完成后,你将获得一个符合Kitti数据集格式数据集,可以在后续的任务中使用。 #### 引用[.reference_title] - *1* *2* *3* [DAIR-V2X数据集转为kitti数据集格式(保姆级教程)](https://blog.csdn.net/m0_57273938/article/details/126418351)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值