点云常见数据处理

遍历文件夹下面的所有bin文件

    def init_pcd_files_list(pcd_files_path):
    	pcd_files_list=[]
        for file in Path(pcd_files_path).rglob("*.bin"):
            pcd_files_list.append(str(file))
        pcd_files_list = sorted(spcd_files_list, key=lambda p: Path(p).stem)
        return pcd_files_list

1. .pcd->.bin转换成kitti格式的点云文件:

import os
import numpy as np
import fire

def read_pcd(filepath):
    lidar = []
    with open(filepath,'r') as f:
        line = f.readline().strip()
        while line:
            linestr = line.split(" ")
            if len(linestr) == 4:
                linestr_convert = list(map(float, linestr))
                lidar.append(linestr_convert)
            line = f.readline().strip()
    return np.array(lidar)


def convert(pcdfolder, binfolder):
    current_path = os.getcwd()
    ori_path = os.path.join(current_path, pcdfolder)
    file_list = os.listdir(ori_path)
    des_path = os.path.join(current_path, binfolder)
    if os.path.exists(des_path):
        pass
    else:
        os.makedirs(des_path)
    for file in file_list: 
        (filename,extension) = os.path.splitext(file)
        velodyne_file = os.path.join(ori_path, filename) + '.pcd'
        pl = read_pcd(velodyne_file)
        pl = pl.reshape(-1, 4).astype(np.float32)
        velodyne_file_new = os.path.join(des_path, filename) + '.bin'
        pl.tofile(velodyne_file_new)
    
if __name__ == "__main__":
    fire.Fire()

2.Python txt转pcd(带RGB值,点云)

1、有numpy就能运行,假如需要转换的TXT文件有header,需要删除header才能运行;
2、直接运行代码,按运行提示输入TXT文件路径和PCD文件保存路径即可,不需要修改代码。

import os
import sys
import numpy as np

def creat_pcd(input_path, output_path):
    
    #Lodaing txt
    Full_Data = np.loadtxt(input_path)
    
    #Creating pcd
    if os.path.exists(output_path):
        os.remove(output_path)
    Output_Data = open(output_path, 'a')
    Output_Data.write('# .PCD v0.7 - Point Cloud Data file format\nVERSION 0.7\nFIELDS x y z rgba\nSIZE 4 4 4 4\nTYPE F F F U\nCOUNT 1 1 1 1')
    string = '\nWIDTH ' + str(Full_Data.shape[0])
    Output_Data.write(string)
    Output_Data.write('\nHEIGHT 1\nVIEWPOINT 0 0 0 1 0 0 0')
    string = '\nPOINTS ' + str(Full_Data.shape[0])
    Output_Data.write(string)
    Output_Data.write('\nDATA ascii')
    for j in range(Full_Data.shape[0]):
        R=Full_Data[j,3]
        G=Full_Data[j,4]
        B=Full_Data[j,5]
        value = (int(R) << 16 | int(G) << 8 | int(B))
        string = ('\n' + str(Full_Data[j,0]) + ' ' + str(Full_Data[j, 1]) + ' ' +str(Full_Data[j, 2]) + ' ' + str(value))
        Output_Data.write(string)
    Output_Data.close()
    
    print('--------------Completed--------------')

a = input("请输入TXT文件路径:")#文件路径中斜杆使用"/",比如:D:/pcl/points.txt
b = input("请输入PCD文件保存路径:")#比如:D:/pcl/points.pcd

creat_pcd(a, b)

3.Python 点云.las转.pcd

# -*- coding: utf-8 -*-
# 读取las文件 并保留为 XYZI格式的pcd文件

from pclpy import pcl
from laspy.file import File  # las文件读取
import numpy as np  # np数组处理
import time  # 计算耗时

# las读取转为 pcd的cloud形式,只保留 XYZI
def getCloud(las_path,pcd_path):
    f = File(las_path, mode='r')
    # inFile = np.vstack((f.x, f.y, f.z, f.intensity)).transpose()
    # inFile = np.vstack((f.x-f.x[0], f.y-f.y[0], f.z, f.intensity)).transpose()[0:480000]
    inFile = np.vstack((f.x, f.y, f.z)).transpose() - f.header.offset  #inFile  shape = (N,3)
    rgb = np.vstack((f.red,f.green,f.blue)).transpose()
    # cloud = pcl.PointCloud.PointXYZRGBA().from_array(np.array(inFile, dtype=np.float32),rgb)
    cloud = pcl.PointCloud.PointXYZI().from_array(np.array(inFile, dtype=np.double))
    pcl.io.savePCDFileASCII(pcd_path,cloud)
    # cloud.from_array(np.array(inFile, dtype=np.float32))
    f.close()

    return cloud

def main():
    las_path = r"/media/data/zs/project/semantic3d/data/pcd_seg/pcd/202306210615530000_202306210644350000/202306210622170010_202306210622220153.las"
    pcd_path = r"/media/data/zs/project/semantic3d/data/pcd_seg/pcd/caizhendong/1001140020191217_las2pcd_0.pcd"
    end1 = time.time()
    cloud = getCloud(las_path, pcd_path)
    end2 = time.time()
    print("las2pcd 耗时:%.2f秒" % (end2 - end1))
    print('-------endl----------')

if __name__ == '__main__':
    main()

使用laspy注意事项:
一、las1.4官方文档有下图:
在这里插入图片描述
这里的Xrecord指的是laspy文件中的大写X,Xcoordinate指的是laspy文件中的小写x,Xrecord、Xcoordinate能保存的范围是不同的,例如保存大坐标时,Xcoordinate(laspy文件中的大写X)保存大坐标(大值或者说大范围值,如38537619.88568608),Xrecord(laspy文件中的小写x)保存偏移量(小值或者说小范围值,如170、260等),Xrecord一般时整数。个人理解可能laspy里面只存储了Xrecord和(offset and scale),Xcoordinate是算出来的,因为Xrecord值小,存储不费内存,Xcoordinate值更大,存储更费内存。
弄错了会报如下错误:

发生异常: OverflowError
Values given do not fit after applying offset and scale

Xscale和Xoffset都是laspy文件中head里面的,Xscale一般是小于1的树,比如(0.01,0.01,0.001),Xoffset代表偏移量,一般存储第一个值或者las中的最小值。
二、las.classification
laspy文件中既有las.classification又有las.Classification,使用las.Classification保存点类别标签后,cloudcompare软件查看不了Classification属性,但使用las.classification保存点类别标签后,cloudcompare软件可以查看classification属于,正确写法如下:

# save_point_cloud
def save_point_cloud(las_narray, label, out_path, header=None, is_deployment=True):
    # las_narray[:, 0:3] = las_narray[:, 0:3] + header.offsets
    cloud = las_narray[:, 0:3]
    indensity = las_narray[:, 3]
    gps_time = las_narray[:, 4]
    # label = las_narray[:, 5]
    points = np.array(cloud)
    print('points.shape=', points.shape)
    if header is None:
        header = laspy.LasHeader(point_format=3, version="1.2")
        header.offsets = np.min(points[:, 0:3], axis=0)
        print('header.offsets', header.offsets)
        header.scales = np.array([0.01, 0.01, 0.01])
    # with laspy.open(out_path, mode="w", header=header) as writer:
        # point_record = laspy.ScaleAwarePointRecord.zeros(len(points), header=header)
        # point_record.x = points[:, 0]
        # point_record.y = points[:, 1]
        # point_record.z = points[:, 2]
        # point_record.intensity = indensity
        # print('is_deployment=', is_deployment)
        # if is_deployment is True:
        #     point_record.gps_time = gps_time
        # writer.write_points(point_record)
    # 2. Create a Las
    # header.add_extra_dim(laspy.ExtraBytesParams(name="intensity", type=np.int32))
    las = laspy.LasData(header)
    las.x = points[:, 0]
    las.y = points[:, 1]
    las.z = points[:, 2]
    las.intensity = indensity
    las.classification = label
    las.gps_time = gps_time
    # las.label = label
    las.write(out_path)
    return

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值