open3d 点云数据处理
爆肝5万字❤️Open3D 点云数据处理基础(Python版)_python 点云 焊缝-CSDN博客
如何用NumPy读取和保存点云数据 - 知乎
读取并可视化点云
np.loadtxt 从txt中读取点集,并open3d显示单个点云
txt内容:每行皆为一个点 xyz,逗号隔开,xy为图像坐标,z为图像序号,所有图的点集皆存入一个txt
import open3d as o3d
import numpy as np# points_data = np.loadtxt("E:/vsproject/勋仪交接/标克艾芬达暖水管/测量主管尺寸/vp/11pnts.txt", delimiter=",", dtype=np.float32)
points_data = np.loadtxt("E:/vsproject/勋仪交接/标克艾芬达暖水管/测量主管尺寸/vp/11pnts.txt", delimiter=",")
print('shape: ', points_data.shape)
print('data type: ', points_data.dtype)points_data[:,2] = points_data[:,2] * 21 # 将所有行的第三列乘以 21# points_data = np.random.rand(100, 3) # 示例数据:100 个随机 3D 点
colors_data = np.random.rand(100, 3) # 100 个随机 RGB 颜色数组pcd = o3d.geometry.PointCloud() # 创建一个空的点云对象
pcd.points = o3d.utility.Vector3dVector(points_data[:, :3]) # 从NumPy数组points_data中分配3D点(取前3列作为 x,y,z 坐标)
pcd.colors = o3d.utility.Vector3dVector(colors_data) # 分配颜色信息
o3d.visualization.draw_geometries([pcd]) # 可视化点云
读取.pcd文件
import open3d as o3d
import numpy as npprint("->正在加载点云... ")
pcd = o3d.io.read_point_cloud("test.pcd")
print(pcd)print("->正在可视化点云")
o3d.visualization.draw_geometries([pcd])
读取.pts文件,并进行网格化 (Mesh化)
原始点云为.pts
文件,内容为x,y,z
的坐标
import open3d as o3d
import numpy as np# 读取.pts文件
def read_pts_file(filename):with open(filename, 'r') as f:lines = f.readlines()pts = []for line in lines:data = line.strip().split()pts.append([float(data[0]), float(data[1]), float(data[2])])return np.array(pts)# 加载.pts文件
pts_filename = "E:\Airplane.pts" # 替换为.pts文件路径
pts = read_pts_file(pts_filename)# 创建open3d格式的点云对象
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(pts)# 创建alpha shape并进行mesh化
alpha = 0.015 # 设置alpha值
mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(pcd, alpha)# 可视化网格化后的结果
o3d.visualization.draw_geometries([mesh], window_name="网格化结果")
同一窗口可视化多个点云
o3d.visualization.draw_geometries([pcd1, pcd2, ... ,pcdn])
# 加载点云1
pcd1 = o3d.io.read_point_cloud("bunny.pcd")
print(pcd1)# 加载点云2
pcd2 = o3d.io.read_point_cloud("bunny0.pcd")
print(pcd2)# 可视化两个点云
o3d.visualization.draw_geometries([pcd1, pcd2])
space = 2500
pnts_r = np.loadtxt("E:/vsproject/勋仪交接/标克艾芬达暖水管/测量主管尺寸/vpr/11pnts.txt", delimiter=",")
pnts_r[:,2] = pnts_r[:,2] * 36 # 将所有行的第三列乘以 21
pnts_r[:,1] = pnts_r[:,1] + space
pnts_r[:,0] = pnts_r[:,0] * 4
pnts_d = np.loadtxt("E:/vsproject/勋仪交接/标克艾芬达暖水管/测量主管尺寸/vpd/11pnts.txt", delimiter=",")
pnts_d[:,2] = pnts_d[:,2] * 36 # 将所有行的第三列乘以 21
pnts_d[:,1] = pnts_d[:,1] + space*2
pnts_d[:,0] = pnts_d[:,0] * 2
pnts_s = np.loadtxt("E:/vsproject/勋仪交接/标克艾芬达暖水管/测量主管尺寸/散热片划痕/11pnts.txt", delimiter=",")
pnts_s[:,2] = pnts_s[:,2] * 16 # 将所有行的第三列乘以 21
pnts_s[:,1] = pnts_s[:,1] + space*3
pnts_s[:,0] = pnts_s[:,0] * 2def get_pcd(points_data):pcd = o3d.geometry.PointCloud() # 创建一个空的点云对象pcd.points = o3d.utility.Vector3dVector(points_data[:, :3]) # 从NumPy数组points_data中分配3D点(取前3列作为 x,y,z 坐标)pcd.colors = o3d.utility.Vector3dVector(colors_data) # 分配颜色信息return pcdpcd_r = get_pcd(pnts_r)
pcd_d = get_pcd(pnts_d)
pcd_s = get_pcd(pnts_s)
o3d.visualization.draw_geometries([pcd_r,pcd_d,pcd_s]) # 可视化点云
下采样,两种去除离群点,均值滤波
# points_data = np.loadtxt("E:/vsproject/勋仪交接/标克艾芬达暖水管/测量主管尺寸/vp/11pnts.txt", delimiter=",", dtype=np.float32)
points_data = np.loadtxt("E:/vsproject/勋仪交接/标克艾芬达暖水管/测量主管尺寸/vpc/11pnts.txt", delimiter=",")
print('shape: ', points_data.shape)
print('data type: ', points_data.dtype)points_data[:,2] = points_data[:,2] * 36 # 将所有行的第三列乘以 21
points_data[:,0] = points_data[:,0] * 4# points_data = np.random.rand(100, 3) # 示例数据:100 个随机 3D 点
colors_data = np.random.rand(100, 3) # 100 个随机 RGB 颜色数组pcd = o3d.geometry.PointCloud() # 创建一个空的点云对象
pcd.points = o3d.utility.Vector3dVector(points_data[:, :3]) # 从NumPy数组points_data中分配3D点(取前3列作为 x,y,z 坐标)
pcd.colors = o3d.utility.Vector3dVector(colors_data) # 分配颜色信息# 1. 下采样(降采样)
down_pcd = pcd.voxel_down_sample(voxel_size=0.05)
print("下采样后的点云数量:", len(np.asarray(down_pcd.points)))# 2. 去除离群点
# 统计离群点移除
cl, ind = down_pcd.remove_statistical_outlier(nb_neighbors=20, std_ratio=2.0)
statistical_outlier_removed = down_pcd.select_by_index(ind)
print("统计离群点移除后的点云数量:", len(np.asarray(statistical_outlier_removed.points)))# 半径离群点移除
# cl, ind = statistical_outlier_removed.remove_radius_outlier(nb_points=16, radius=0.05)
cl, ind = statistical_outlier_removed.remove_radius_outlier(nb_points=6, radius=11)
radius_outlier_removed = statistical_outlier_removed.select_by_index(ind)
print("半径离群点移除后的点云数量:", len(np.asarray(radius_outlier_removed.points)))# 3. 滤波(平滑) - 自定义均值滤波
def mean_filter(pcd, k=5):''' 对每个点找到其k个最近的邻居并计算均值作为滤波后的点坐标 '''points = np.asarray(pcd.points)filtered_points = np.zeros_like(points)for i in range(len(points)):# 找到k个最近的邻居(这里简化处理,实际应用中可以使用KD树等高效方法)distances = np.linalg.norm(points - points[i], axis=1)nearest_indices = np.argsort(distances)[:k]filtered_points[i] = np.mean(points[nearest_indices], axis=0)filtered_pcd = o3d.geometry.PointCloud()filtered_pcd.points = o3d.utility.Vector3dVector(filtered_points)return filtered_pcdfiltered_pcd = mean_filter(radius_outlier_removed, k=5)
print("均值滤波后的点云数量:", len(np.asarray(filtered_pcd.points)))# 可视化原始点云和处理后的点云
# o3d.visualization.draw_geometries([pcd]) # 可视化点云
o3d.visualization.draw_geometries([pcd], window_name="原始点云")
o3d.visualization.draw_geometries([down_pcd], window_name="下采样后的点云")
o3d.visualization.draw_geometries([statistical_outlier_removed], window_name="统计离群点移除后的点云")
o3d.visualization.draw_geometries([radius_outlier_removed], window_name="半径离群点移除后的点云")
o3d.visualization.draw_geometries([filtered_pcd], window_name="均值滤波后的点云")