3d点云基础,ply文件的读写和操作

在这里插入图片描述

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.0ascii 1.0,此外也有少量数据集binary_little_endian以作为编码的。

第二行 - 倒数第二行:代表数据集的一组数据 (element)。vertex是这组数据的名字,2350907代表这组数据的点 (或顶点) 数量,而剩余的行说明每数据有哪些属性和对应的数据类型。

这个ply文件中只有一组数据,如果文件中有多组数据 (主要出现于三角形表示中) ,则在 property uint8 class 后面再添加

element el2 114514
property uchar heng
...

处理的库:

这里讨论python。ply常见的处理的库有:open3dplyfile。此外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点云来说通常只有一组。

  • 10
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用PythonNumPy和Open3D库来完成这个任务。以下是一个示例代码: ```python import os import numpy as np import open3d as o3d def fit_sphere(pcd): # 使用最小二乘法拟合球心 sphere = pcd.compute_fit_sphere() return sphere.center def fit_plane(points): # 拟合点集的平面 pcd = o3d.geometry.PointCloud() pcd.points = o3d.utility.Vector3dVector(points) plane_model, inliers = pcd.segment_plane(distance_threshold=0.01, ransac_n=3, num_iterations=1000) return plane_model[:3] if __name__ == '__main__': dir_path = '/path/to/ply/folder' point_clouds = [] # 读取文件的所有点云.ply文件 for file_name in os.listdir(dir_path): if file_name.endswith('.ply'): file_path = os.path.join(dir_path, file_name) pcd = o3d.io.read_point_cloud(file_path) point_clouds.append(pcd) # 拟合每个点云的球心 sphere_centers = [fit_sphere(pcd) for pcd in point_clouds] # 拟合所有点云的平面 points = np.array(sphere_centers) plane_normal = fit_plane(points) print('拟合平面的法向量坐标为:', plane_normal) ``` 这段代码首先通过`os.listdir()`函数遍历文件的所有.ply文件,并使用Open3D的`read_point_cloud()`函数读取每个点云文件。然后,对于每个点云,使用`compute_fit_sphere()`函数拟合其球心,并将所有拟合得到的球心坐标存储到`sphere_centers`列表。 最后,将所有的球心坐标存储到一个NumPy数组,使用`segment_plane()`函数拟合出所有点云的平面,并将平面法向量的前三个元素作为拟合平面的法向量坐标。最后打印输出拟合平面的法向量坐标。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值