ply文件:
ply文件是一种储存3d图形的文件类型。其不止可以储存3d点,还可以储存三角形的顶点。本节暂时只讨论点云的应用,所以没有三角形图形。
ply文件除了开头的header部分,顶点组的部分根据编码类型决定 (在header中表明),一般来说是binary的形式。
数据格式 (header解释),以sensaturban为例:
ply
format binary_little_endian 1.0
element vertex 2350907
property float32 x
property float32 y
property float32 z
property uint8 red
property uint8 green
property uint8 blue
property uint8 class
end_header
第一行:代表数据的编码格式。通常为二进制binary_little_endian 1.0
或ascii 1.0
,此外也有少量数据集binary_little_endian
以作为编码的。
第二行 - 倒数第二行:代表数据集的一组数据 (element)。vertex
是这组数据的名字,2350907
代表这组数据的点 (或顶点) 数量,而剩余的行说明每数据有哪些属性和对应的数据类型。
这个ply文件中只有一组数据,如果文件中有多组数据 (主要出现于三角形表示中) ,则在 property uint8 class
后面再添加
element el2 114514
property uchar heng
...
处理的库:
这里讨论python。ply常见的处理的库有:open3d和plyfile。此外Rand-LA库中的helper_ply.py
也可以作为使用辅助。
o3d:
读: pc = o3d.io.read_point_cloud(path)
,返回一个o3d.geometry.PointCloud
类的对象。它会自动把名字为 x,y,z
的属性提取到pc.points
, 把red,green,blue
提取到pc.colors
。通过 np.asarray(pc.points)
可以返回属性的np数组。pc还有covariances,normals
两个属性, 除此之外的属性名如 class,label
则无法通过o3d读取。
o3d的所有属性均由float64
储存,对于颜色它会把0-255转化为0-1。因此o3d在储存效率上较低,对于训练效率也会有所影响。
写: 需要先创建一个PointCloud对象,然后将numpy数组 (num_points, 3) 转换为v3d。因为属性是固定的,所以不需要结构化。
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(xyz)
plyfile:
读:如果是二进制文件,ply库需要以二进制打开。返回一个PlyData对象
with open(file_dir, 'rb') as file:
plydata = PlyData.read(file)
数据储存在 plydata.elements[0].data
是一个形状为 (num_points,) 的结构化numpy数组。每一项数据类似于一个tuple,data.dtype有所有属性的数据类型。因为结构化数组和Dataframe结构类似,可以直接转化为 pd.DataFrame(data)
。
写:见文档creating a ply部分。一个简洁的写法是:
element1 = PlyElement.describe(np_array, 'vertex')
element2 = PlyElement.describe(np_array2, 'another group')
...
PlyData([element1, element2, ...]).write('file_name.ply')
describe要求传入结构化数组,其中数据的属性名会作为点的属性名。也就是说比如点云有坐标和颜色的6个属性,就需要传入np.array(arraydata , dtype=[('x','f4'), ('y', 'f4'), ('z', 'f4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')])
。
因为在numpy默认数组无法指定单列数据的数据类型,而结构数组中操作较为麻烦。可以通过pandas来操作后,用arr = df.to_records(index=False)
从Dataframe转化得来。
'vertex'
是这一组数据的名字。多组数据在PlyData([element1, element2, ...])
中括起来,对于3d点云来说通常只有一组。