Paddle3D 2 雷达点云CenterPoint模型训练

2 Paddle3D 雷达点云CenterPoint模型训练–包含KITTI格式数据地址

2.0 数据集 百度DAIR-V2X开源路侧数据转kitti格式。

2.0.1 DAIR-V2X-I\velodyne中pcd格式的数据转为bin格式

参考源码:雷达点云数据.pcd格式转.bin格式

def pcd2bin():
    import numpy as np
    import open3d as o3d
    from tqdm import tqdm
    import os

    pcdPath = r'E:\DAIR-V2X-I\velodyne'
    binPath = r'E:\DAIR-V2X-I\kitti\training\velodyne'

    files = os.listdir(pcdPath)
    files = [f for f in files if f[-4:]=='.pcd']

    for ic in tqdm(range(len(files)), desc='进度 '):
        f = files[ic]
        pcdname = os.path.join(pcdPath, f)
        binname = os.path.join(binPath, f[:-4] + '.bin')

        # 读取PCD文件
        # pcd = o3d.io.read_point_cloud("./data/002140.ply")
        pcd = o3d.io.read_point_cloud(pcdname)
        # print('==============pcd\n', pcd)
        # print('==============pcd.points\n', pcd.points)

        points = np.asarray(pcd.points)
        # print('==============points\n', points)
        # print(type(points))
        # print(points.shape)
        # 添加全0列
        point0 = np.zeros((points.shape[0], 1))
        points = np.column_stack((points,point0))
        # print(points.shape)

        # 查看点云图像
        # o3d.visualization.draw_geometries([pcd])
        # 将PCD格式保存为BIN格式,使用.tofile实现;
        # 理论上o3d.io.write_point_cloud也可以实现,但是运行的时候,没有报错,但也并没有保存文件
        points.tofile(binname)
        o3d.io.write_point_cloud(os.path.join(binPath, f[:-4]+'.bin'), pcd)  

        # if ic == 1:
        #     break

可视化查看bin文件

def visBinData():
    """
    可视化的形式查看点云数据的Bin文件
    :return:
    """
    import numpy as np
    from tqdm import tqdm
    import mayavi.mlab
    import os

    binPath = r'D:\lidar3D\data\Lidar0\bin'
    # binPath = r'./data'
    files = os.listdir(binPath)
    files = [f for f in files if f[-4:] == '.bin']

    for ic in tqdm(range(len(files)), desc='进度 '):
        f = files[ic]
        binname = os.path.join(binPath, f)
        pointcloud = np.fromfile(binname, dtype=np.float32, count=-1).reshape([-1,4])
        x = pointcloud[:, 0]
        y = pointcloud[:, 1]
        z = pointcloud[:, 2]
        r = pointcloud[:, 3]
        d = np.sqrt(x ** 2 + y ** 2)  # Map Distance from sensor

        degr = np.degrees(np.arctan(z / d))

        vals = 'height'
        if vals == "height":
            col = z
        else:
            col = d

        fig = mayavi.mlab.figure(bgcolor=(0, 0, 0), size=(640, 500))
        mayavi.mlab.points3d(x, y, z,
                             col,  # Values used for Color
                             mode="point",
                             colormap='spectral',  # 'bone', 'copper', 'gnuplot'
                             # color=(0, 1, 0),   # Used a fixed (r,g,b) instead
                             figure=fig,
                             )

        mayavi.mlab.show()
        break
def visBinData():
    import open3d as o3d
    import numpy as np
    import os

    # 替换为你的 bin 文件路径
    bin_file_path = r'E:\DAIR-V2X-I\kitti_s\training\velodyne'
    files = os.listdir(bin_file_path)
    for f in files[:]:

        # 读取 bin 文件
        bin_file = os.path.join(bin_file_path, f)
        print(bin_file)
        points_np = np.fromfile(bin_file, dtype=np.float32)
        print(points_np.shape)
        points_np = points_np.reshape(-1, 4)
        print(points_np.shape)

        # 创建 Open3D 点云对象
        pcd = o3d.geometry.PointCloud()
        pcd.points = o3d.utility.Vector3dVector(points_np[:, :3])

        # 可视化点云
        o3d.visualization.draw_geometries([pcd])

打印查看bin文件中的数据

def readbinfiles():
    import numpy as np

    print('\n' + '*' * 10 + 'myData' + '*' * 10)
    path = r'D:\lidar3D\data\mydatas1\kitti_my\training\velodyne\000003.bin'
    # b1 = np.fromfile(path, dtype=np.float)
    b2 = np.fromfile(path, dtype=np.float32, count=-1).reshape([-1, 4])
    print(type(b2))
    print(b2.shape)
    print(b2)
2.0.2 先对应training中的所有数据准备好
————————training
______________calib
______________image_2
______________Label_2
______________velodyne
【1】velodyne

这里是所有的.bin格式的点云文件

【2】iamge_2

这里是velodyne中的点云文件对应的图片文件。从原文件里面相同名称的图片复制过来就可以了,这里原图片文件是.jpg的格式,kitti里面查找.png的格式好像是写死的,为避免麻烦,可以先把图片直接重命名为.png的格式。()

def jpg2png():
    import os
    path = r'E:\DAIR-V2X-I\example71\training\image_2'
    files = os.listdir(path)
    for f in files:
        fsrc = os.path.join(path, f)
        fdes = os.path.join(path, f[:-4]+'.png')
        os.rename(fsrc, fdes)
【3】calib

两种方式,一种方式是忽略DAIR-V2X数据中的标定,直接复制kitti中calib/000000.txt

    if calibFlag:
        '''copy kitti-mini/training/calib/00000.txt cotent to my calib'''
        calibPath = r'E:\DAIR-V2X-I\training\calib'
        binPath = r'E:\DAIR-V2X-I\training\velodyne'
        kitti_miniCalibPath = r'D:\lidar3D\data\kitti_mini\training\calib/000000.txt'

        with open(kitti_miniCalibPath, "r") as calib_file:
            content = calib_file.read()
        for f in os.listdir(binPath):
            with open(os.path.join(calibPath, f[:-4]+".txt"),  "w") as wf:
                wf.write(content)

另外一种方式是提取single-infrastructure-side\calib中的标定信息写进calib/xxxxxx.txt文件。因为DAIR-V2X只有一台相机,写到p0: ,R0_rect 和 Tr_velo_to_cam 也从中读取。由于Tr_velo_to_cam 是固定的,所以写死在了代码里面

    if calibFlag1:
        V2XVelodynePath = r'E:\DAIR-V2X-I\training\velodyne'
        files = os.listdir(V2XVelodynePath)
        files = [f[:-4]+'.txt' for f in files]
        for f in files:
            content=[]
            cameintriPath = r'E:\DAIR-V2X-I\single-infrastructure-side\calib\camera_intrinsic'
            with open(os.path.join(cameintriPath,f[:-4]+'.json'), "r") as rf1:
                data = json.load(rf1)
                p0 = 'P0:'
                for d in data["P"]:
                    p0 += ' {}'.format(d)
                R0_rect = 'R0_rect:'
                for r in data["R"]:
                    R0_rect += ' {}'.format(r)
            content.append(p0+'\n')
            content.append('P1: 1 0 0 0 0 1 0 0 0 0 1 0\n')
            content.append('P2: 1 0 0 0 0 1 0 0 0 0 1 0\n')
            content.append('P3: 1 0 0 0 0 1 0 0 0 0 1 0\n')
            content.append('R0_rect: 1 0 0 0 1 0 0 0 1\n')

            # vir2camePath = os.path.join(V2XCalibPath, cliblist[1])
            # with open(os.path.join(vir2camePath,f[:-4]+'.json'), "r") as rf1:
            #     data = json.load(rf1)
            #     R = data["rotation"]
            #     t = data["translation"]

            Tr_velo_to_cam = 'Tr_velo_to_cam: -0.032055018882740139 -0.9974518923884874 0.020551248965447915 -2.190444561668236 -0.2240930139414797 0.002986041494130043 -0.8756800120708629 5.6360862566491909 0.9737455440255373 -0.041678350017788 -0.2023375046787095 1.4163664770754852\n'
            content.append(Tr_velo_to_cam)
            content.append('Tr_imu_to_velo: 1 0 0 0 0 1 0 0 0 0 1 0')

            fcalibname = os.path.join(mykittiCalibPath, f)
            # content[-1] = content[-1].replace('\n', '')
            with open(fcalibname, 'w', encoding='utf-8') as wf:
                wf.writelines(content)
【4】Label_2

方法{{{见 《 2.1.3中——【4】问题记录3 —— 重新生成label_2文件过程如下》章节}}}

点云的标签文件single-infrastructure-side\label\virtuallidar*.json转为txt文件存储,这里3Class,故只取类型([“Car”, “Cyclist”, “Pedestrian”])([‘Cyclist’, ‘Car’, ‘Truck’])。

这里将每个标签(目标)记作temp, temp [0:16] 共计16列,含义分别为:

类别[0]+是否截断[1]+是否遮挡[2]+观察角度[3]+图像左上右下[4:8]+高宽长[8:11]+相机坐标系xyz[11:14]+方向角[14]+置信度[15]

注意:测试数据集才有最后一列的置信度。

json转txt代码如下,因为只训练点云数据,所以与图片相关的值这里用0代替。

如下代码是直接取json文件中的数据,尺寸取雷达坐标系下的,位置取相机坐标系下的。

    if label_2Flag:
        # 1 创建文件夹 label_2
        label_2Path = r'E:\DAIR-V2X-I\kitti_s\training\label_22_kitti3clsNewXYZ'
        judgefolderExit_mkdir(label_2Path)

        V2XVelodynePath = r'E:\DAIR-V2X-I\kitti_s\training\velodyne'
        files = os.listdir(V2XVelodynePath)
        files = [f[:-4] + '.txt' for f in files]

        V2XLabelPathcamera = r'E:\DAIR-V2X-I\single-infrastructure-side\label\camera'
        V2XLabelPathlidar = r'E:\DAIR-V2X-I\single-infrastructure-side\label\virtuallidar'
        # 2 转化生成对应的.txt标签文件
        labelsList = {}
        labelsListnew = {}
        for f in files[:]:
            # print(f)
            with open(os.path.join(V2XLabelPathcamera, f[:-4] + '.json'), "r") as rf1:
                dataca = json.load(rf1)
            with open(os.path.join(V2XLabelPathlidar, f[:-4] + '.json'), "r") as rf1:
                datali = json.load(rf1)
            label_list = []
            if len(dataca) != len(datali):
                print('Error:  len(dataca) != len(datali)')
                continue
            for oi in range(len(dataca)):
                obj_ca = dataca[oi]
                obj_li = datali[oi]
                label_name = obj_ca["type"]
                label_nameli = obj_li["type"]
                if label_name != label_nameli:
                    print('Error: label_name != label_nameli')
                    continue
                # static labels
                if label_name in labelsList.keys():
                    labelsList[label_name] += 1
                else:
                    labelsList[label_name] = 1

                # updata label type
                # Car 、 Cyclist、
                if label_name == 'Trafficcone' or label_name == 'ScooterRider' or label_name == 'Barrowlist':
                    continue
                elif label_name == 'Motorcyclist':
                    label_name = 'Cyclist'
                elif label_name == 'Van':
                    label_name = 'Car'
                elif label_name == 'Bus':
                    label_name = 'Car'
                elif label_name == 'Truck':
                    label_name = 'Car'

                if label_name in labelsListnew.keys():
                    labelsListnew[label_name] += 1
                else:
                    labelsListnew[label_name] = 1


                scale = obj_li["3d_dimensions"]     # 尺寸取雷达坐标系下的
                pos = obj_ca["3d_location"]         # 位置取相机坐标系下的
                rot = obj_li["rotation"]
                alpha = obj_ca["alpha"]  # 观察角度[3]
                cabox = obj_ca["2d_box"] # 图像左上右下[4:8]
                occluded_state = obj_ca["occluded_state"] # 是否遮挡[2]
                truncated_state = obj_ca["truncated_state"] # 是否截断[1]

                tempFlag = True  # label_list.append(temp)
                if tempFlag == True:
                    # 2.1  temp 追加目标类型
                    # temp [0:16] 共计16列
                    # 类别[0]+是否截断[1]+是否遮挡[2]+观察角度[3]+图像左上右下[4:8]+高宽长[8:11]+
                    #         相机坐标系xyz[11:14]+方向角[14]+置信度[15]
                    # 注意:测试数据集才有最后一列的置信度
                    temp = label_name + ' '+ truncated_state +' '+ occluded_state +' 0 ' + \
                           cabox["xmin"] + ' ' + cabox["ymin"] + ' ' + cabox["xmax"] + ' ' + cabox["ymax"] + ' '

                    temp += (scale['h'].split('.')[0] + "." + scale['h'].split('.')[1][:2] + ' ')
                    temp += (scale['w'].split('.')[0] + "." + scale['w'].split('.')[1][:2] + ' ')
                    temp += (scale['l'].split('.')[0] + "." + scale['l'].split('.')[1][:2] + ' ')

                    # 2.2.1  pos_xyz
                    # temp += (pos['x'].split('.')[0] + "." + pos['x'].split('.')[1][:2] + ' ')
                    # temp += (pos['y'].split('.')[0] + "." + pos['y'].split('.')[1][:2] + ' ')
                    # temp += (pos['z'].split('.')[0] + "." + pos['z'].split('.')[1][:2] + ' ')

                    # 2.2 固定使用转换矩阵lidar_to_cam后
                    # 此处的矩阵目的将lidar转到cam下,再转换到rect下,同样追加到temp中(temp追加pos_xyz)
                    # trans_Mat: calib中的 Tr_velo_to_cam
                    trans_Mat = np.array(
                        [[-3.205501888274e-02, -9.974518923885e-01, 2.055124896545e-02, -2.190444561668e+00],
                         [-2.240930139415e-01, 2.986041494130e-03, -8.756800120709e-01, 5.636086256649e+00],
                         [9.737455440255e-01, -4.167835001779e-02, -2.023375046787e-01, 1.416366477075e+00],
                         [0, 0, 0, 1]])
                    # R0_rect: 三维单位矩阵
                    rect_Mat = np.array([[1, 0, 0, 0],
                                         [0, 1, 0, 0],
                                         [0, 0, 1, 0],
                                         [0, 0, 0, 1]])
                    ptx = str2float(pos["x"])
                    pty = str2float(pos["y"])
                    # print('pos["z"], scale["l"], type(scale["l"])\n', pos["z"], scale["l"], type(scale["l"]))
                    ptz = str2float(pos["z"]) - (0.5 * str2float(scale["l"]))
                    # lidar坐标系下的相机中心点
                    pt_in_lidar = np.array([[ptx],
                                            [pty],
                                            [ptz],
                                            [1.]])

                    pt_in_camera = np.matmul(trans_Mat, pt_in_lidar)
                    pt_in_rect = np.matmul(rect_Mat, pt_in_camera)

                    temp += str(pt_in_rect[0, 0]).split('.')[0] + "." + str(pt_in_rect[0, 0]).split('.')[1][0:2]
                    temp += " "
                    temp += str(pt_in_rect[1, 0]).split('.')[0] + "." + str(pt_in_rect[1, 0]).split('.')[1][0:2]
                    temp += " "
                    temp += str(pt_in_rect[2, 0]).split('.')[0] + "." + str(pt_in_rect[2, 0]).split('.')[1][0:2]
                    temp += " "

                    ## 2.3  temp 追加 rot_xyz(先将 rot 航向角 返回到0-360°之间)
                    rot = - str2float(rot) - (np.pi / 2)
                    if rot > np.pi:
                        rot = rot - 2 * np.pi
                    elif rot < -np.pi:
                        rot = rot + 2 * np.pi
                    temp += str(rot).split('.')[0] + "." + str(rot).split('.')[1][0:2] + "\n"
                    label_list.append(temp)

            label_list[-1] = label_list[-1].replace('\n', '')
            # print(label_list)
            with open(os.path.join(label_2Path, f[:-4]+'.txt'), "w") as wf:
                wf.writelines(label_list)

        print('labels Statics = ', labelsList)
        print('labels Statics = ', labelsListnew)

如下代码考虑重新计算了位置信息,固定使用转换矩阵lidar_to_cam。[“Car”, “Cyclist”, “Pedestrian”]

    if label_2Flag:
        # 1 创建文件夹 label_2
        label_2Path = r'E:\DAIR-V2X-I\kitti\training\Label_2'
        judgefolderExit_mkdir(label_2Path)

        V2XVelodynePath = r'E:\DAIR-V2X-I\kitti\training\velodyne'
        files = os.listdir(V2XVelodynePath)
        files = [f[:-4] + '.txt' for f in files]

        V2XLabelPathcamera = r'E:\DAIR-V2X-I\single-infrastructure-side\label\camera'
        V2XLabelPathlidar = r'E:\DAIR-V2X-I\single-infrastructure-side\label\virtuallidar'
        # 2 转化生成对应的.txt标签文件
        labelsList = {}
        labelsListnew = {}
        for f in files[:]:
            # print(f)
            with open(os.path.join(V2XLabelPathcamera, f[:-4] + '.json'), "r") as rf1:
                dataca = json.load(rf1)
            with open(os.path.join(V2XLabelPathlidar, f[:-4] + '.json'), "r") as rf1:
                datali = json.load(rf1)
            label_list = []
            if len(dataca) != len(datali):
                print('Error:  len(dataca) != len(datali)')
                continue
            for oi in range(len(dataca)):
                obj_ca = dataca[oi]
                obj_li = datali[oi]
                label_name = obj_ca["type"]
                label_nameli = obj_li["type"]
                if label_name != label_nameli:
                    print('Error: label_name != label_nameli')
                    continue
                # static labels
                if label_name in labelsList.keys():
                    labelsList[label_name] += 1
                else:
                    labelsList[label_name] = 1

                # updata label type
                # Car 、 Cyclist、
                if label_name == 'Trafficcone' or label_name == 'ScooterRider' or label_name == 'Barrowlist':
                    continue
                elif label_name == 'Motorcyclist':
                    label_name = 'Cyclist'
                elif label_name == 'Van':
                    label_name = 'Car'
                elif label_name == 'Bus':
                    label_name = 'Car'
                elif label_name == 'Truck':
                    label_name = 'Car'

                if label_name in labelsListnew.keys():
                    labelsListnew[label_name] += 1
                else:
                    labelsListnew[label_name] = 1


                scale = obj_li["3d_dimensions"]     # 尺寸取雷达坐标系下的
                pos = obj_ca["3d_location"]         # 位置取相机坐标系下的
                rot = obj_li["rotation"]

                tempFlag = False  # label_list.append(temp)
                if tempFlag == True:
                    # 2.1  temp 追加目标类型
                    # temp [0:16] 共计16列
                    # 类别[0]+是否截断[1]+是否遮挡[2]+观察角度[3]+图像左上右下[4:8]+高宽长[8:11]+
                    #         相机坐标系xyz[11:14]+方向角[14]+置信度[15]
                    # 注意:测试数据集才有最后一列的置信度
                    temp = label_name + ' 0 0 0 0 0 0 0 '
                    temp += (scale['h'].split('.')[0] + "." + scale['h'].split('.')[1][:2] + ' ')
                    temp += (scale['w'].split('.')[0] + "." + scale['w'].split('.')[1][:2] + ' ')
                    temp += (scale['l'].split('.')[0] + "." + scale['l'].split('.')[1][:2] + ' ')

                    # 2.2.1  pos_xyz
                    # temp += (pos['x'].split('.')[0] + "." + pos['x'].split('.')[1][:2] + ' ')
                    # temp += (pos['y'].split('.')[0] + "." + pos['y'].split('.')[1][:2] + ' ')
                    # temp += (pos['z'].split('.')[0] + "." + pos['z'].split('.')[1][:2] + ' ')

                    # 2.2 固定使用转换矩阵lidar_to_cam后
                    # 此处的矩阵目的将lidar转到cam下,再转换到rect下,同样追加到temp中(temp追加pos_xyz)
                    trans_Mat = np.array(
                        [[6.927964000000e-03, -9.999722000000e-01, -2.757829000000e-03, -2.457729000000e-02],
                         [-1.162982000000e-03, 2.749836000000e-03, -9.999955000000e-01, -6.127237000000e-02],
                         [9.999753000000e-01, 6.931141000000e-03, -1.143899000000e-03, -3.321029000000e-01],
                         [0, 0, 0, 1]])

                    rect_Mat = np.array([[9.999128000000e-01, 1.009263000000e-02, -8.511932000000e-03, 0],
                                         [-1.012729000000e-02, 9.999406000000e-01, -4.037671000000e-03, 0],
                                         [8.470675000000e-03, 4.123522000000e-03, 9.999556000000e-01, 0],
                                         [0, 0, 0, 1]])
                    ptx = str2float(pos["x"])
                    pty = str2float(pos["y"])
                    # print('pos["z"], scale["l"], type(scale["l"])\n', pos["z"], scale["l"], type(scale["l"]))
                    ptz = str2float(pos["z"]) - (0.5 * str2float(scale["l"]))
                    # lidar坐标系下的相机中心点
                    pt_in_lidar = np.array([[ptx],
                                            [pty],
                                            [ptz],
                                            [1.]])

                    pt_in_camera = np.matmul(trans_Mat, pt_in_lidar)
                    pt_in_rect = np.matmul(rect_Mat, pt_in_camera)

                    temp += str(pt_in_rect[0, 0]).split('.')[0] + "." + str(pt_in_rect[0, 0]).split('.')[1][0:2]
                    temp += " "
                    temp += str(pt_in_rect[1, 0]).split('.')[0] + "." + str(pt_in_rect[1, 0]).split('.')[1][0:2]
                    temp += " "
                    temp += str(pt_in_rect[2, 0]).split('.')[0] + "." + str(pt_in_rect[2, 0]).split('.')[1][0:2]
                    temp += " "

                    ## 2.3  temp 追加 rot_xyz(先将 rot 航向角 返回到0-360°之间)
                    rot = - str2float(rot) - (np.pi / 2)
                    if rot > np.pi:
                        rot = rot - 2 * np.pi
                    elif rot < -np.pi:
                        rot = rot + 2 * np.pi
                    temp += str(rot).split('.')[0] + "." + str(rot).split('.')[1][0:2] + "\n"
                    label_list.append(temp)

            # label_list[-1] = label_list[-1].replace('\n', '')
            # with open(os.path.join(label_2Path, f[:-4]+'.txt'), "w") as wf:
            #     wf.writelines(label_list)

        print('labels Statics = ', labelsList )
        print('labels Statics = ', labelsListnew )
2.0.3 kitti\testing中的数据类似training中数据

仅需移动部分数据作为test是数据即可

————————testing
______________calib
______________image_2
______________Label_2
______________velodyne
2.0.4 写kitti/ImageSets 中的txt文件

注意:如下代码中val.txt 与test.txt中的文件是一致的

def filesPath2txt():
    import os, random

    pathtrain = 'E:\DAIR-V2X-I\kitti_s/training/velodyne/'
    pathtest = 'E:\DAIR-V2X-I\kitti_s/testing/velodyne/'
    txtPath = 'E:\DAIR-V2X-I\kitti_s/ImageSets/'

    txt_path_train = os.path.join(txtPath, 'train.txt')
    txt_path_val = os.path.join(txtPath, 'val.txt')
    # txt_path_trainval = os.path.join(txtPath, 'trainval.txt')
    txt_path_test = os.path.join(txtPath, 'test.txt')
    # mkdirImageSets(txt_path_train, txt_path_val, txt_path_trainval, txt_path_test)

    files = os.listdir(pathtrain)
    filesList = [f[:-4] + '\n' for f in files]

    filestr = filesList
    filestr[-1] = filestr[-1].replace('\n', '')
    with open(txt_path_train, 'w', encoding='utf-8') as wf:
        wf.writelines(filestr)

    files = os.listdir(pathtest)
    filesList = [f[:-4] + '\n' for f in files]
    filesval = filesList  # random.sample(filesList, 700)
    filesval[-1] = filesval[-1].replace('\n', '')
    with open(txt_path_val, 'w', encoding='utf-8') as wf:
        wf.writelines(filesval)

    # filestest = random.sample(filesList, 400)
    # filestest[-1] = filestest[-1].replace('\n', '')
    with open(txt_path_test, 'w', encoding='utf-8') as wf:
        wf.writelines(filesval)

2.1 paddle3D训练

cd ./Paddle3D
2.1.1 数据
【1】数据

数据存放在Paddle3D/datasets目录下,结构如下:

datasets/
datasets/KITTI/
————datasets/KITTI/ImageSets
————datasets/KITTI/testing
————datasets/KITTI/training
【2】数据预处理

使用如下代码完成数据的预处理操作

python tools/create_det_gt_database.py --dataset_name kitti --dataset_root ./datasets/KITTI --save_dir ./datasets/KITTI

上述过程打印如下,运行结束会生成datasets/KITTI/kitti_train_gt_database目录。

root/anaconda3/envs/pip_paddle_env/lib/python3.8/site-packages/setuptools/sandbox.py:13: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
  import pkg_resources
root/anaconda3/envs/pip_paddle_env/lib/python3.8/site-packages/pkg_resources/__init__.py:2871: DeprecationWarning: Deprecated call to `pkg_resources.declare_namespace('mpl_toolkits')`.
Implementing implicit namespace packages (as specified in PEP 420) is preferred to `pkg_resources.declare_namespace`. See https://setuptools.pypa.io/en/latest/references/keywords.html#keyword-namespace-packages
  declare_namespace(pkg)
root/anaconda3/envs/pip_paddle_env/lib/python3.8/site-packages/pkg_resources/__init__.py:2871: DeprecationWarning: Deprecated call to `pkg_resources.declare_namespace('google')`.
Implementing implicit namespace packages (as specified in PEP 420) is preferred to `pkg_resources.declare_namespace`. See https://setuptools.pypa.io/en/latest/references/keywords.html#keyword-namespace-packages
  declare_namespace(pkg)
ortools not installed, install it by "pip install ortools==9.1.9490" if you run BEVLaneDet model
2023-12-26 17:45:46,823 -     INFO - Begin to generate a database for the KITTI dataset.
2023-12-26 17:46:06,774 -     INFO - [##################################################] 100.00%
2023-12-26 17:46:07,012 -     INFO - The database generation has been done.
2.1.2 模型配置文件

为避免修改原模型配置文件,先复制一份并命名为centerpoint_pillars_016voxel_kitti_my.yml

cp ./configs/centerpoint/centerpoint_pillars_016voxel_kitti.yml ./configs/centerpoint/centerpoint_pillars_016voxel_kitti_my.yml

核对文件中的相关配置信息

train_dataset:
  type: KittiPCDataset
  dataset_root: datasets/KITTI
  ... ...
  class_names: ["Car", "Cyclist", "Pedestrian"]
2.1.3 训练流程及问题调试
【1】使用如下代码进行训练
# python -m paddle.distributed.launch --gpus 0,1,2,3,4,5,6,7 tools/train.py --config configs/centerpoint/centerpoint_pillars_016voxel_kitti.yml --save_dir ./output_kitti --num_workers 4 --save_interval 5

python tools/train.py --config configs/centerpoint/centerpoint_pillars_016voxel_kitti_my.yml --save_dir ./output_kitti --save_interval 5 > 112.log

参数介绍

-m:使用python -m paddle.distributed.launch方法启动分布式训练任务。
参考:https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/distributed/launch_cn.html
> 112.log : 将其中的打印保存在112.log中
【2】问题记录1
【2-1】SystemError: (Fatal) Blocking queue is killed because the data reader raises an exception.
【2-2】KeyError: ‘DataLoader worker(1) caught KeyError with message:\nTraceback (most recent call last):\n File “/home/… …”… … self.sampler_per_class[cls_name].sampling(num_samples)\n KeyError: ‘Car’\n’

【2-1、2-2】解决方法

参考1:SystemError: (Fatal) Blocking queue is killed because the data reader raises an exception : 没找到源码中的相关位置。

参考2:SystemError: (Fatal) Blocking queue is killed (baidu.com)

利用“参考2”中提供的方法, 训练的时候,将num_worker设置为0。如下:

python tools/train.py --config configs/centerpoint/centerpoint_pillars_016voxel_kitti_my.yml --save_dir ./output_kitti --num_workers 0 --save_interval 5

将num_workers 设置为0训练的时候,报如下错误

/Paddle3D/paddle3d/transforms/sampling.py", line 172, in sampling
    sampling_annos = self.sampler_per_class[cls_name].sampling(num_samples)
KeyError: 'Car'

采用如下代码打印/Paddle3D/paddle3d/transforms/sampling.py", line 172中的信息,结果是{}。

print('self.sampler_per_class', self.sampler_per_class)
》》》》》》self.sampler_per_class {}

发现是配置文件中class_balanced_sampling参数是设置为False的原因。修改class_balanced_sampling为True如下

train_dataset:
  type: KittiPCDataset
  dataset_root: datasets/KITTI
  ... ...
  mode: train
  class_balanced_sampling: True
  class_names: ["Car", "Cyclist", "Pedestrian"]
【3】问题记录2
【3-1】ZeroDivisionError: float division by zero

详细报错包含如下

File "/home/mec/hulijuan/Paddle3D/paddle3d/datasets/kitti/kitti_det.py", line 89, in <listcomp>
    sampling_ratios = [balanced_frac / frac for frac in fracs]
ZeroDivisionError: float division by zero

上述问题打印 print(‘kitti_det.py’, cls_dist) 发现是自己数据集中没有"Pedestrian"类别,而class_names中包含该类别。解决办法是增加包含 "Pedestrian"类 的数据。

【4】问题记录3
【4-1】又报错问题同“【2】问题记录1 SystemError: … KeyError: …”,只能是大概上面的问题没有从根本上解决掉

首先看KeyError的问题。

在paddle3d/transforms/sampling.py/class SamplingDatabase(TransformABC):/def __ init __()中增加打印。如下

    def __init__(self,
                 min_num_points_in_box_per_class: Dict[str, int],
                 max_num_samples_per_class: Dict[str, int],
                 database_anno_path: str,
                 database_root: str,
                 class_names: List[str],
                 ignored_difficulty: List[int] = None):
        self.min_num_points_in_box_per_class = min_num_points_in_box_per_class
        self.max_num_samples_per_class = max_num_samples_per_class
        self.database_anno_path = database_anno_path
        with open(database_anno_path, "rb") as f:
            database_anno = pickle.load(f)
        print('sampling.py__line58~~~~~~~~~~~~~~~~~~~~58database_anno: ', database_anno)
        if not osp.exists(database_root):
            raise ValueError(
                f"Database root path {database_root} does not exist!!!")
        self.database_root = database_root
        self.class_names = class_names
        self.database_anno = self._filter_min_num_points_in_box(database_anno)

        self.ignored_difficulty = ignored_difficulty
        if ignored_difficulty is not None:
            self.database_anno = self._filter_ignored_difficulty(self.database_anno)

        self.sampler_per_class = dict()
        print('sampling.py__line70~~~~~~~~~~~~~~~70database_anno: ', self.database_anno)
        for cls_name, annos in self.database_anno.items():
            self.sampler_per_class[cls_name] = Sampler(cls_name, annos)

通过打印,可以看出sampling.py–line70的打印是空字典,而sampling.py–line58的打印部分如下:
在这里插入图片描述

上图可以看出,num_points_in_box 的值为 0。导致如下代码运行后,database_anno 变成了空字典

self.database_anno = self._filter_min_num_points_in_box(database_anno)

上述问题应该是针对点云文件生成标签文件的时候,方法错了。

重新生成label_2文件过程如下:
1  创建环境
conda create -n pcd2bin_env python=3.8
2  激活环境
conda activate pcd2bin_env
3  安装pypcd
3.1  参考:https://blog.csdn.net/weixin_44450684/article/details/92812746
如下流程:
git clone https://github.com/dimatura/pypcd
cd pypcd
git fetch origin pull/9/head:python3
git checkout python3
python3 setup.py install --user 
python3
from pypcd import pypcd
pc = pypcd.PointCloud.from_path('pointcloud.pcd')

利用开源程序重新生成label_2文件过程如下:
源码百度网盘地址:

执行程序:

2.2 数据集地址KITTI格式(DAIR-V2X-I(7058帧数据)):(长期有效)

大小:22G
链接:https://pan.baidu.com/s/1gG_S6Vtx4iWAfAVAfOxWWw 
提取码:p48l 
数据没有问题 但是label_2中的XYZ需要根据前述lanel_2的方法重新生成。需下载该数据集的标签文件single-infrastructure-side-json.zip

2.3 模型

2.3.1 模型评估

2.3.2 模型测试

2.3.3 导出模型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/289208.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++面向对象语法总结(三)

目录 《C面向对象语法总结(一&#xff09;》《C面向对象语法总结(二&#xff09;》 二十一、多继承 C允许一个类可以有多个父类&#xff08;不建议使用&#xff0c;会增加程序设计复杂度&#xff09;在多继承中&#xff0c;会按照继承顺序将父类的成员变量放到子类成员变量的…

踩坑Vant组件 Dialog的组件调用

今天踩了一个非常蠢的坑&#xff0c;自己给自己蠢死的坑 在使用组件调用时自己没引入Dialog组件导致一直报错 不知道为什么全局引入不好使&#xff0c;后来使用了局部引用 现在没问题了 就这样局部引入一个Dialog.Component就可以了

CEEMDAN +组合预测模型(Transformer - BiLSTM+ ARIMA)

目录 往期精彩内容&#xff1a; 前言 1 风速数据CEEMDAN分解与可视化 1.1 导入数据 1.2 CEEMDAN分解 2 数据集制作与预处理 3 基于CEEMADN的 Transformer - BiLSTM 模型预测 3.1 定义CEEMDAN-Transformer - BiLSTM预测模型 3.2 设置参数&#xff0c;训练模型 4 基于A…

【日积月累】Java Lambda 表达式

目录 【日积月累】Java Lambda 表达式 1.前言2.语法3.应用场景3.1简化匿名内部类的编写3.1简化匿名内部类的编写3.2简化集合类中的操作3.3实现函数式接口3.4简化多个方法的调用3.5简化异步编程 4.总结5.参考 文章所属专区 日积月累 1.前言 Lambda表达式是一个匿名函数&#…

数据库索引、三范式、事务

索引 索引&#xff08;Index&#xff09;是帮助 MySQL 高效获取数据的数据结构。常见的查询算法,顺序查找,二分查找,二叉排序树查找,哈希散列法,分块查找,平衡多路搜索树 B 树&#xff08;B-tree&#xff09;。 常见索引原则有 选择唯一性索引&#xff1a;唯一性索引的值是唯…

爬虫入门与urllibrequests

前情摘要 一、web请求全过程剖析 我们浏览器在输入完网址到我们看到网页的整体内容, 这个过程中究竟发生了些什么? 我们看一下一个浏览器请求的全过程 接下来就是一个比较重要的事情了. 所有的数据都在页面源代码里么? 非也~ 这里要介绍一个新的概念 那就是页面渲染数据的…

[C#]使用onnxruntime部署Detic检测2万1千种类别的物体

【源码地址】 github地址&#xff1a;https://github.com/facebookresearch/Detic/tree/main 【算法介绍】 Detic论文&#xff1a;https://arxiv.org/abs/2201.02605v3 项目源码&#xff1a;https://github.com/facebookresearch/Detic 在Detic论文中&#xff0c;Detic提到…

基于Java SSM框架实现中国古诗词学习平台项目【项目源码】

基于java的SSM框架实现中国古诗词学习平台系统演示 JSP技术介绍 JSP技术本身是一种脚本语言&#xff0c;但它的功能是十分强大的&#xff0c;因为它可以使用所有的JAVA类。当它与JavaBeans 类进行结合时&#xff0c;它可以使显示逻辑和内容分开&#xff0c;这就极大的方便了用…

Docker中的核心概念

1.镜像 Image 一个镜像就代表一个软件。mysql镜像、redis镜像、mq镜像 2.容器 Container 一个镜像运行一次就会生成一个容器&#xff0c;容器就是一个运行的软件服务。 3.远程仓库 Repository 远程仓库用来存储所有软件的镜像&#xff0c;Docker Hub 4.本地仓库 用来存储…

谷歌推出了一种名为提示扩展(Prompt Expansion)的创新框架,旨在帮助用户更轻松地创造出既高质量又多样化的图像。

谷歌推出了一种名为提示扩展&#xff08;Prompt Expansion&#xff09;的创新框架&#xff0c;旨在帮助用户更轻松地创造出既高质量又多样化的图像。 论文标题: Prompt Expansion for Adaptive Text-to-Image Generation 论文链接: https://arxiv.org/pdf/2312.16720.pdf 问…

如何删除K8S中的Pod

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

生信技能32 - 导入UCSC公共数据库SNP数据至本地MySQL数据库

本文以导入SNP151.txt数据库为例,其他数据库文件操作类似。 1. 数据文件下载 UCSC下载网址: https://hgdownload.cse.ucsc.edu/goldenPath/hg19/database/ 以下为Linux下载文件方式 wget https://hgdownload.cse.ucsc.edu/goldenPath/hg19/database/snp151.sql wget -c -…

[ASIS 2019]Unicorn shop

点入题目看见四个可购买的东西&#xff0c;但是都购买不了&#xff0c;最后一个价格大的脱俗&#xff0c;猜测成功买到后会得到flag&#xff0c;但是购买时提示操作失败只允许一个字符。查看源码发现在utf-8后面特意标注提示 涉及到了字符编码和字符集的概念&#xff1a; UTF-…

单机多进程,每个进程多张卡 mpi nccl 程序设计检验

做了部分注释&#xff0c;比较乱 本示例结构&#xff1a; 1&#xff0c;源代码 #include <stdlib.h> #include <stdio.h> #include "cuda_runtime.h" #include "nccl.h" #include "mpi.h" #include <unistd.h> #include <…

流量预测资源总结(不断更新)

目录 整理流量预测数据集&#xff08;1&#xff09;Telecom Italia 意大利电信 2015&#xff08;2&#xff09;City Cellular Traffic Map (C2TM) 2015&#xff08;3&#xff09;、LTE Network Traffic Data_kaggle&#xff08;4&#xff09;、Cellular Traffic Analysis Data …

Python十大实用技巧【附源码】

1、什么是Python? Python简介 Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读性&#xff0c;相比其他语言经常使用英文关键字&#xff0c;其他语言的一些标点符号&#xff0c;它具有比其他语言更有特色语法结构。 …

Nacos学习思维导图

一、服务注册 参考文档&#xff1a;http://www.bryh.cn/a/118936.html https://blog.csdn.net/Saintmm/article/details/121981184 二、服务续约 参考文档&#xff1a;http://www.bryh.cn/a/118936.html https://blog.csdn.net/Saintmm/article/details/121981184 三、服务…

提取 PE 文件的各种信息

前段时间项目需要实现对 Windows PE 文件版本信息的提取&#xff0c;如文件说明、文件版本、产品名称、版权、原始文件名等信息。获取这些信息在 Windows 下当然有一系列的 API 函数供调用&#xff0c;简单方便。 我们先看一下PE文件结构&#xff0c;PE文件由DOS首部&#xff0…

FX3U-1PG使用

作为扩展模块的安装 伺服驱动器的参数设置 1.设置为0&#xff0c;为位置模式&#xff0c;发送脉冲控制&#xff1b; 2. 设置旋转方向&#xff0c;以及脉冲方式&#xff0c;通常设置为01&#xff0c;因为FX3U-1PG只支持正方向脉冲负方向脉冲方式&#xff1b; 当然想改变电机运…

基于AT89C51单片机可做实物的温度烟雾火灾报警设计

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/88658141?spm1001.2014.3001.5503 C 源码仿真图毕业设计实物制作步骤02 摘要 随着现代家庭用火、用电量的增加&#xff0c;家庭火灾发生的频率越来越高。火灾报警…
最新文章