前言
由于lidar360直接输出ply或las或pcd会出现特征缺失的情况, 只有输出txt是全的, 因此写一个脚本手动将lidar360输出的txt文件转换为ply格式。
代码同时实现了坐标归一化功能, 参数需要手动调整。
代码
"""
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!')