lidar360输出的txt转ply

前言

由于lidar360直接输出ply或las或pcd会出现特征缺失的情况, 只有输出txt是全的, 因此写一个脚本手动将lidar360输出的txt文件转换为ply格式。

代码同时实现了坐标归一化功能, 参数需要手动调整。

代码

依赖 Python ply pcd 点云读取源码

"""
txt2ply.py
将 Lidar360 或 CloudCompare 生成的txt格式点云转ply格式或pkl格式
修复Lidar360颜色错误, 坐标归一化
github.com/DLW3D
2022年1月1日 01:07:41
"""

import os
import sys
import pickle
import numpy as np

# 获取命令行参数
if len(sys.argv) <= 1:
    print('Error no input file')
    print('Sample: python txt2ply.py in_file.txt out_file.ply')
    sys.exit(2)
elif len(sys.argv) == 2:
    file_path = sys.argv[1]
    out_path = file_path+'.ply'
else:
    file_path = sys.argv[1]
    out_path = sys.argv[2]

if out_path.endswith('.ply'):
    from ply import write_ply

f = open(file_path, 'r')

# 处理文件头
l1 = f.readline()
l2 = f.readline()
if l1.startswith('PointNum'):   
    # Lidar360 生成
    num_of_point = int(l1[10:-1])
    header = l2[:-1].split(',')
    spliter = ','
elif l1.startswith('//'):
    # CC生成
    header = l1[2:-1].split(' ')
    num_of_point = int(l2[:-1])
    spliter = ' '
else:
    raise ValueError('Error: unknow filetype')

# 读取点云
for i in range(num_of_point):
    # 打印进度
    if i % 100000 == 0:
        print('{:.2f} %'.format((i+1)/num_of_point*100))
    l = f.readline()[:-1].split(spliter)
    # 第一行识别格式
    if i == 0:
        typer = ['f4' if '.' in i else 'u4' for i in l]     # 识别数据类型
        dt = np.dtype(list(zip(header, typer)))     # 构建数据类型
        data = np.zeros([num_of_point], dtype=dt)   # 创建数据储存空间
        # center = np.array(l[:2], dtype=np.float64)  # 记录高精度中心点坐标
        center = np.array([0, 0])    # 手动设置中心点坐标 529900, 2538600
    lf = np.array(l, dtype=np.float64)  # 以高精度导入
    lf[:2] -= center    # 坐标归一化
    data[i] = tuple(lf)
f.close()

# 修复RGB
if 'R' in header:
    if data['R'].max() > 256:
        data['R'] //= 256
        data['G'] //= 256
        data['B'] //= 256
        typer[header.index('R')] = 'u1'
        typer[header.index('G')] = 'u1'
        typer[header.index('B')] = 'u1'
    typer[header.index('Intensity')] = 'u1' if data['Intensity'].max() < 256 else 'u4'
    typer[header.index('ReturnNumberType')] = 'u1' if data['ReturnNumberType'].max() < 256 else 'u4'
    dt = np.dtype(list(zip(header, typer)))
    data = data.astype(dt)

# 输出
print('saving in \"%s\"...' % out_path)
if out_path.endswith('.ply'):
    # write_ply(out_path, [data[h] for h in header], header)
    write_ply(out_path, [data['X'], data['Y'], data['Z'], data['R'], data['G'], data['B'], data['Intensity'], data['ReturnNumberType']], ['x', 'y', 'z', 'red', 'green', 'blue', 'scalar_Intensity', 'scalar_ReturnNumber'])
else:
    pickle.dump(data, open(out_path, 'wb'))
print('Done!')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值