import open3d as o3d
import numpy as np
pcd = o3d.io.read_point_cloud("test.pcd")
print(pcd) # 输出点云个数
print(np.asarray(pcd.points)) # 输出点的三维坐标
o3d.io.write_point_cloud("write.pcd", pcd, True) # 默认false,保存为Binarty;True 保存为ASICC形式
print(pcd)
pcd = o3d.io.read_point_cloud("../../test_data/my_points.txt", format='xyz')
import open3d as o3d
import numpy as np
pcd = o3d.io.read_point_cloud("test.pcd")
print(pcd)
o3d.visualization.draw_geometries([pcd])
o3d.visualization.draw_geometries([pcd1, pcd2, ... ,pcdn])
import open3d as o3d
import numpy as np
pcd1 = o3d.io.read_point_cloud("bunny.pcd")
print(pcd1)
pcd2 = o3d.io.read_point_cloud("bunny0.pcd")
print(pcd2)
o3d.visualization.draw_geometries([pcd1, pcd2])
draw_geometries(geometry_list, window_name='Open3D', width=1920, height=1080, left=50, top=50, point_show_normal=False, mesh_show_wireframe=False, mesh_show_back_face=False)
参数 | 含义 |
---|---|
geometry_list | 要可视化的几何体列表 |
window_name | (str, optional, default=‘Open3D’),可视化窗口的显示标题 |
width | (int, optional, default=1920),可视化窗口的宽度 |
height | (int, optional, default=1080),可视化窗口的高度 |
left | (int, optional, default=50),可视化窗口的左边距 |
top | (int, optional, default=50),可视化窗口的顶部边距 |
point_show_normal | ((bool, optional, default=False),如果设置为true,则可视化点法线,需要事先计算点云法线 |
mesh_show_wireframe | (bool, optional, default=False),如果设置为true,则可视化网格线框 |
mesh_show_back_face | ((bool, optional, default=False),可视化网格三角形的背面 |
draw_geometries(geometry_list, window_name='Open3D', width=1920, height=1080, left=50, top=50, point_show_normal=False, mesh_show_wireframe=False, mesh_show_back_face=False, lookat, up, front, zoom)
参数 | 含义 |
---|---|
lookat | (numpy.ndarray[float64[3, 1]]),相机的注视向量 |
up | (numpy.ndarray[float64[3, 1]]),相机的上方向向量 |
front | (numpy.ndarray[float64[3, 1]]),相机的前矢量 |
zoom | (float),相机的缩放倍数 |
# 法线估计
radius = 0.01 # 搜索半径
max_nn = 30 # 邻域内用于估算法线的最大点数
pcd.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius, max_nn)) # 执行法线估计
pcd_tree = o3d.geometry.KDTreeFlann(pcd) # 建立KDTree
pcd_tree.search_knn_vector_3d(search_Pt, k) # K近邻搜索
pcd_tree.search_radius_vector_3d(search_Pt, radius) # 半径R近邻搜索
pcd_tree.search_hybrid_vector_3d(search_pt, radius, max_nn) # 混合邻域搜索,返回半径radius内不超过max_nn个近邻点
返回值为 [K邻域内点数/R半径内点数/混合邻域内点数 , 点的索引, ]
# 将点云设置为灰色
pcd.paint_uniform_color([0.5, 0.5, 0.5])
# 跳过查询点本身为点云赋色
np.asarray(pcd.colors)[idx_radius[1:], :] = [1, 0, 0]
octree = o3d.geometry.Octree(max_depth=4)
octree.convert_from_point_cloud(pcd, size_expand=0.01)
o3d.visualization.draw_geometries([octree])
voxel_grid = o3d.geometry.VoxelGrid.create_from_point_cloud(pcd, voxel_size=0.2)
o3d.visualization.draw_geometries([voxel_grid])
octree = o3d.geometry.Octree(max_depth=4)
octree.create_from_voxel_grid(voxel_grid)
o3d.visualization.draw_geometries([octree])
voxel_size = 0.5
downpcd = pcd.voxel_down_sample(voxel_size)
num_neighbors = 20 # K邻域点的个数
std_ratio = 2.0 # 标准差乘数
# 执行统计滤波,返回滤波后的点云sor_pcd和对应的索引ind
sor_pcd, ind = pcd.remove_statistical_outlier(num_neighbors, std_ratio)
sor_pcd.paint_uniform_color([0, 0, 1])
# 提取噪声点云
sor_noise_pcd = pcd.select_by_index(ind,invert = True)
sor_noise_pcd.paint_uniform_color([1, 0, 0])
num_points = 20 # 邻域球内的最少点数,低于该值的点为噪声点
radius = 0.05 # 邻域半径大小
# 执行半径滤波,返回滤波后的点云sor_pcd和对应的索引ind
sor_pcd, ind = pcd.remove_radius_outlier(num_points, radius)
sor_pcd.paint_uniform_color([0, 0, 1])
# 提取噪声点云
sor_noise_pcd = pcd.select_by_index(ind,invert = True)
sor_noise_pcd.paint_uniform_color([1, 0, 0])
radius = 0.01 # 搜索半径
max_nn = 30 # 邻域内用于估算法线的最大点数
pcd.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius, max_nn)) # 执行法线估计
o3d.visualization.draw_geometries([pcd], point_show_normal=True)
eps = 0.5 # 同一聚类中最大点间距
min_points = 50 # 有效聚类的最小点数
with o3d.utility.VerbosityContextManager(o3d.utility.VerbosityLevel.Debug) as cm:
labels = np.array(pcd.cluster_dbscan(eps, min_points, print_progress=True))
max_label = labels.max() # 获取聚类标签的最大值 [-1,0,1,2,...,max_label],label = -1 为噪声,因此总聚类个数为 max_label + 1
print(f"point cloud has {max_label + 1} clusters")
colors = plt.get_cmap("tab20")(labels / (max_label if max_label > 0 else 1))
colors[labels < 0] = 0 # labels = -1 的簇为噪声,以黑色显示
pcd.colors = o3d.utility.Vector3dVector(colors[:, :3])
o3d.visualization.draw_geometries([pcd])
distance_threshold = 0.2 # 内点到平面模型的最大距离
ransac_n = 3 # 用于拟合平面的采样点数
num_iterations = 1000 # 最大迭代次数
# 返回模型系数plane_model和内点索引inliers,并赋值
plane_model, inliers = pcd.segment_plane(distance_threshold, ransac_n, num_iterations)
# 输出平面方程
[a, b, c, d] = plane_model
print(f"Plane equation: {a:.2f}x + {b:.2f}y + {c:.2f}z + {d:.2f} = 0")
# 平面内点点云
inlier_cloud = pcd.select_by_index(inliers)
inlier_cloud.paint_uniform_color([0, 0, 1.0])
# 平面外点点云
outlier_cloud = pcd.select_by_index(inliers, invert=True)
outlier_cloud.paint_uniform_color([1.0, 0, 0])
diameter = np.linalg.norm(np.asarray(pcd.get_max_bound()) - np.asarray(pcd.get_min_bound()))
camera = [0, 0, diameter] # 视点位置
radius = diameter * 100 # 噪声点云半径,The radius of the sperical projection
_, pt_map = pcd.hidden_point_removal(camera, radius) # 获取视点位置能看到的所有点的索引 pt_map
alpha = 0.03
print(f"alpha={alpha:.3f}")
mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(pcd, alpha)
mesh.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh], mesh_show_back_face=True)
# ---------------------- 定义点云体素化函数 ----------------------
def get_mesh(_relative_path):
mesh = o3d.io.read_triangle_mesh(_relative_path)
mesh.compute_vertex_normals()
return mesh
# =============================================================
# ------------------------- Ball pivoting --------------------------
print("->Ball pivoting...")
_relative_path = "bunny.ply" # 设置相对路径
N = 2000 # 将点划分为N个体素
pcd = get_mesh(_relative_path).sample_points_poisson_disk(N)
o3d.visualization.draw_geometries([pcd])
radii = [0.005, 0.01, 0.02, 0.04]
rec_mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_ball_pivoting(pcd, o3d.utility.DoubleVector(radii))
o3d.visualization.draw_geometries([pcd, rec_mesh])
# ==============================================================
create_from_point_cloud_poisson
depth 定义了用于曲面重建的八叉树的深度,表示生成的三角形网格的分辨率。depth值越高,网格的细节就越多。
直接读取
print('run Poisson surface reconstruction')
radius = 0.001 # 搜索半径
max_nn = 30 # 邻域内用于估算法线的最大点数
pcd.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius, max_nn)) # 执行法线估计
with o3d.utility.VerbosityContextManager(o3d.utility.VerbosityLevel.Debug) as cm:
mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(pcd, depth=12)
print(mesh)
o3d.visualization.draw_geometries([mesh])
import open3d as o3d
import numpy as np
# -------------------------- 定义点云体素化函数 ---------------------------
def get_mesh(_relative_path):
mesh = o3d.io.read_triangle_mesh(_relative_path)
mesh.compute_vertex_normals()
return mesh
# =====================================================================
# -------------------- Poisson surface reconstruction ------------------
# 加载点云
print("->Poisson surface reconstruction...")
_relative_path = "bunny.ply" # 设置相对路径
N = 5000 # 将点划分为N个体素
pcd = get_mesh(_relative_path).sample_points_poisson_disk(N)
pcd.normals = o3d.utility.Vector3dVector(np.zeros((1, 3))) # 使现有法线无效
# 法线估计
pcd.estimate_normals()
o3d.visualization.draw_geometries([pcd], point_show_normal=True)
pcd.orient_normals_consistent_tangent_plane(100)
o3d.visualization.draw_geometries([pcd], point_show_normal=True)
# 泊松重建
print('run Poisson surface reconstruction')
with o3d.utility.VerbosityContextManager(
o3d.utility.VerbosityLevel.Debug) as cm:
mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(
pcd, depth=9)
print(mesh)
o3d.visualization.draw_geometries([mesh])
# =====================================================================
# true实现点云平移,false点云质心平移到第一个参数指定的位置
pcd.translate((tx,ty,tz),relative=True)
pcd.rotate(R) # 不指定旋转中心 绕质心旋转
pcd.rotate(R,center=(x,y,z)) # 指定旋转中心
pcd_scale.rotate(2,center=pcd.get_center()) # 缩放前后质心一致
pcd_scale.rotate(2,center=(x,y,z)) # 缩放后质心为(x,y,z)
T = np.eye(4)
T[ :3, :3] = pcd.get_rotation_matrix_from_xyz((np.pi/6,np.pi/4,0)) # 旋转矩阵
T[0,3] = 5.0 # 平移向量的dx
T[1,3] = 3.0 # 平移向量的dy
pcd_T.transform(T)
pcd_T.paint_uniform_color([0,0,1])
dists = pcd1.compute_point_cloud_distance(pcd2)
dists = np.asarray(dists)
# 轴向最小包围盒 AABB盒
aabb = pcd.get_axis_aligned_bounding_box()
# 最小包围盒 obb盒
obb = pcd.get_oriented_bounding_box()
hull, _ = pcd.compute_convex_hull()
hull_ls = o3d.geometry.LineSet.create_from_triangle_mesh(hull)
voxel_grid = o3d.geometry.VoxelGrid.create_from_point_cloud(pcd, voxel_size=0.005)
pcd.get_center()
inlier_pcd = pcd.select_by_index(self, indices, invert=False)
outlier_pcd = pcd.select_by_index(idx, invert=True) # 对索引取反
# 将点云进行单一颜色赋值 RGB范围[0,1]
pcd.paint_uniform_color([1,0.706,0])