python open3d_Open3D点云操作

 MANUAL

Open3D中文手册  点 |  云  | 操 |  作

本教程演示了对点云的基本操作。

显示点云

本教程的第一部分:读取点云并将其显示。
[2]:print("Load a ply point cloud, print it, and render it")pcd = o3d.io.read_point_cloud("../../test_data/fragment.ply")print(pcd)print(np.asarray(pcd.points))o3d.visualization.draw_geometries([pcd],                                  zoom=0.3412,                                  front=[0.4257, -0.2125, -0.8795],                                  lookat=[2.6172, 2.0475, 1.532],                                  up=[-0.0694, -0.9768, 0.2024])
Load a ply point cloud, print it, and render itPointCloud with 196133 points.[[0.65234375 0.84686458 2.37890625] [0.65234375 0.83984375 2.38430572] [0.66737998 0.83984375 2.37890625] ... [2.00839925 2.39453125 1.88671875] [2.00390625 2.39488506 1.88671875] [2.00390625 2.39453125 1.88793314]]

python open3d_Open3D点云操作_第1张图片

  read_point_cloud  从文件中读取点云。它尝试根据扩展名对文件进行解码。有关支持的文件类型的列表,请参阅 Open3D文件读写。

 draw_geometries 可视化点云。使用鼠标/轨迹板从不同的视角查看几何体。

它看起来像一个稠密的曲面,但实际上它是一个渲染为曲面的点云。GUI支持各种键盘功能。例如,  - 键可减小点(surfels)的大小。

注意:

按 H 键可打印出GUI键盘指令的完整列表。有关可视化GUI的更多信息,请参阅 [可视化](http://www.open3d.org/docs/release/tutorial/geometry/visualization.ipynb) 和 [自定义可视化](http://www.open3d.org/docs/release/tutorial/visualization/customized_visualization.html)。

注意:

在macOS上,GUI窗口可能不会接收键盘事件。在本例中,尝试使用 pythonw 而不是 Python启动 , Python。

体素降采样

体素降采样,是使用规则的(大小一致)立体网格将输入点云分割成一个个体素,创建统一降采样的点云。它通常用作许多点云处理任务的预处理步骤。该算法分为两个步骤:

1. 点被存储到体素中,即将 点云分块 存储。

2. 每个被占用的体素通过平均其内部的所有点来精确地生成一个点,即 逐块进行降采样 。

python open3d_Open3D点云操作_第2张图片

[3]:print("Downsample the point cloud with a voxel of 0.05")downpcd = pcd.voxel_down_sample(voxel_size=0.05)o3d.visualization.draw_geometries([downpcd],                                  zoom=0.3412,                                  front=[0.4257, -0.2125, -0.8795],                                  lookat=[2.6172, 2.0475, 1.532],                                  up=[-0.0694, -0.9768, 0.2024])
Downsample the point cloud with a voxel of 0.05

python open3d_Open3D点云操作_第3张图片

顶点法线估计    点云的另一个基本操作是点法线估计。按   N  查看点法线。键   -   和键   +  可用于控制法线的长度。
[4]:print("Recompute the normal of the downsampled point cloud")downpcd.estimate_normals(    search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.1, max_nn=30))o3d.visualization.draw_geometries([downpcd],                                  zoom=0.3412,                                  front=[0.4257, -0.2125, -0.8795],                                  lookat=[2.6172, 2.0475, 1.532],                                  up=[-0.0694, -0.9768, 0.2024],                                  point_show_normal=True)
Recompute the normal of the downsampled point cloud

python open3d_Open3D点云操作_第4张图片

 estimate_normals 计算每个点的法线。 该函数通过协方差分析找到相邻点并计算相邻点的主轴。        该函 数以 KDTreeSearchParamHybrid 类的实例作为参数。 两个关键参数指定搜索半径和最大邻点数: radius = 0.1  和 max_nn = 30 表示搜索半径为10cm,最多只考虑30个邻点以节省计算时间。

注意:

       协方差分析算法产生两个相反的方向作为正常候选。如果不知道几何体的全局结构,两者都可以是正确的。这就是所谓的法向问题。Open3D尝试调整法线的方向,使其与原始法线对齐(如果存在)。否则,Open3D会随机猜测。如果需要考虑方向,则需要调用其他方向函数,如 orient_normals_to_align_with_direction 和 orient_normals_towards_camera_location 。

访问估计顶点法线      可以通过   downpcd  的成员变量   normals   来检索估计的法向量。
[5]:print("Print a normal vector of the 0th point")print(downpcd.normals[0])
Print a normal vector of the 0th point[-0.21838377 -0.94240442 -0.25334252]
        若要检查其他变量,请使用   help(downpcd)  。法向量可以用   np.asarray  转化为一个numpy数组。
[6]:print("Print the normal vectors of the first 10 points")print(np.asarray(downpcd.normals)[:10, :])
Print the normal vectors of the first 10 points[[-0.21838377 -0.94240442 -0.25334252] [-0.04374285 -0.94373358 -0.32780099] [-0.00694405 -0.99478075 -0.10179902] [-0.46344316 -0.68643798 -0.56037785] [-0.43476205 -0.62438493 -0.64894177] [-0.27498453 -0.67317361 -0.68645524] [ 0.01316083 -0.99964286 -0.02325814] [-0.01038945 -0.99968858 -0.02268921] [-0.00816546 -0.99965616 -0.02491762] [-0.13075895 -0.94176382 -0.30981124]]

查阅 [Working with NumPy](http://www.open3d.org/docs/release/tutorial/geometry/working_with_numpy.html) 获取有关numpy数组的更多示例。

裁剪点云
[7]:print("Load a polygon volume and use it to crop the original point cloud")vol = o3d.visualization.read_selection_polygon_volume(    "../../test_data/Crop/cropped.json")chair = vol.crop_point_cloud(pcd) #过滤出椅子的点云o3d.visualization.draw_geometries([chair],                                  zoom=0.7,                                  front=[0.5439, -0.2333, -0.8060],                                  lookat=[2.4615, 2.1331, 1.338],                                  up=[-0.1781, -0.9708, 0.1608])
Load a polygon volume and use it to crop the original point cloud

python open3d_Open3D点云操作_第5张图片

 read_selection_polygon_volume 读取指定多边形选择区域的json文件。 vol.crop_point_cloud(pcd) 过滤出点,只剩下椅子了。

绘制点云
[8]:print("Paint chair")chair.paint_uniform_color([1, 0.706, 0])o3d.visualization.draw_geometries([chair],                                  zoom=0.7,                                  front=[0.5439, -0.2333, -0.8060],                                  lookat=[2.4615, 2.1331, 1.338],                                  up=[-0.1781, -0.9708, 0.1608])
Paint chair

python open3d_Open3D点云操作_第6张图片

 paint_uniform_color 将所有点绘制为统一的颜色。颜色在RGB空间[0,1]范围内。

点云距离       Open3D 提供 compute_point_cloud_distance 方法来计算源点云到目标点云的距离。 即,它计算源点云中每个点到目标点云中最近点的距离。

        在下面的示例中,我们使用函数来计算两个点云之间的差。请注意,此方法也可以用于计算两点云之间的切角距离。

[9]:# Load datapcd = o3d.io.read_point_cloud("../../test_data/fragment.ply")vol = o3d.visualization.read_selection_polygon_volume(    "../../test_data/Crop/cropped.json")chair = vol.crop_point_cloud(pcd)dists = pcd.compute_point_cloud_distance(chair)dists = np.asarray(dists)ind = np.where(dists > 0.01)[0]pcd_without_chair = pcd.select_by_index(ind)o3d.visualization.draw_geometries([pcd_without_chair],                                  zoom=0.3412,                                  front=[0.4257, -0.2125, -0.8795],                                  lookat=[2.6172, 2.0475, 1.532],                                  up=[-0.0694, -0.9768, 0.2024])

python open3d_Open3D点云操作_第7张图片

边界包络体       与Open3D中的所有其他几何体类型一样, PointCloud 几何体类型具有边界体。 目前,Open3D实现了一个 AxisAlignedBoundingBox 和 OrientedBoundingBox ,它们也可用于裁剪几何体。
[10]:aabb = chair.get_axis_aligned_bounding_box()aabb.color = (1, 0, 0)obb = chair.get_oriented_bounding_box()obb.color = (0, 1, 0)o3d.visualization.draw_geometries([chair, aabb, obb],                                  zoom=0.7,                                  front=[0.5439, -0.2333, -0.8060],                                  lookat=[2.4615, 2.1331, 1.338],                                  up=[-0.1781, -0.9708, 0.1608])

python open3d_Open3D点云操作_第8张图片

包络凸面体       点云的凸面体是包含所有点的最小凸集。Open3D包含计算点云的凸包的方法 compute_convex_hull 。其实现基于[Qhull]( http://www.qhull.org/ )。        在下面的示例代码中,我们首先从网格中采样点云,然后计算作为三角形网格返回的凸包。 然后,我们把凸包想象成一个红色的 线集 。
[11]:pcl = o3dtut.get_bunny_mesh().sample_points_poisson_disk(number_of_points=2000)hull, _ = pcl.compute_convex_hull()hull_ls = o3d.geometry.LineSet.create_from_triangle_mesh(hull)hull_ls.paint_uniform_color((1, 0, 0))o3d.visualization.draw_geometries([pcl, hull_ls])
downloading bunny meshextract bunny mesh

python open3d_Open3D点云操作_第9张图片

DBSCAN 聚类群集       给定一个点云,例如一个深度传感器,我们希望将局部点云簇组合在一起。为此,我们可以使用聚类算法。Open3D 实现了基于密度的聚类算法DBSCAN [[Ester1996\]]( http://www.open3d.org/docs/release/tutorial/reference.html#Ester1996 ) 。算法在 cluster_dbscan 方法中实现并需要2个参数:  eps 定义到群集中邻点的距离; min_points 定义形成群集所需的最小点数。该函数返回 labels , 当 label = -1 时表示噪声。
[12]:pcd = o3d.io.read_point_cloud("../../test_data/fragment.ply")with o3d.utility.VerbosityContextManager(        o3d.utility.VerbosityLevel.Debug) as cm:    labels = np.array(        pcd.cluster_dbscan(eps=0.02, min_points=10, print_progress=True))max_label = labels.max()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] = 0pcd.colors = o3d.utility.Vector3dVector(colors[:, :3])o3d.visualization.draw_geometries([pcd],                                  zoom=0.455,                                  front=[-0.4999, -0.1659, -0.8499],                                  lookat=[2.1813, 2.0619, 2.0999],                                  up=[0.1204, -0.9852, 0.1215])
[Open3D DEBUG] Precompute Neighbours[Open3D DEBUG] Done Precompute Neighbours[Open3D DEBUG] Compute Clusters[Open3D DEBUG] Done Compute Clusters: 10point cloud has 10 clusters

python open3d_Open3D点云操作_第10张图片

注:

      该算法预先计算所有点在 epsilon 半径上的所有邻近点。如果选择的 epsilon 太大,这可能需要大量内存。

平面分割       Open3D还支持使用RANSAC(随机抽样一致算法)点云分割几何图元。 要找到点云中最大的平面,可以使用 segment_plane 。 该方法有三个参数: istance_threshold  定义一个点到被视为内线的估计平面的最大距离,  ransac_n 定义随机采样来估计平面的点数, 和 num_iterations 定义随机平面采样和验证的频率。 然后,函数返回平面为 (a,b,c,d) ,这样对于平面上的每个点 (x,y,z) 我们得到 (ax+by+cz+d=0) 。 该函数进一步返回内部点的索引列表。
[13]:pcd = o3d.io.read_point_cloud("../../test_data/fragment.pcd")plane_model, inliers = pcd.segment_plane(distance_threshold=0.01,                                         ransac_n=3,                                         num_iterations=1000)[a, b, c, d] = plane_modelprint(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([1.0, 0, 0])outlier_cloud = pcd.select_by_index(inliers, invert=True)o3d.visualization.draw_geometries([inlier_cloud, outlier_cloud],                                  zoom=0.8,                                  front=[-0.4999, -0.1659, -0.8499],                                  lookat=[2.1813, 2.0619, 2.0999],                                  up=[0.1204, -0.9852, 0.1215])
Plane equation: -0.05x + -0.10y + 0.99z + -1.06 = 0

python open3d_Open3D点云操作_第11张图片

移除隐藏点       假设您希望从给定的视点渲染点云,但背景点由于未被其他点遮挡而显露到前景。为此,我们可以应用一种隐藏点去除算法。在Open3D中,[[Katz2007\]]( http://www.open3d.org/docs/release/tutorial/reference.html\Katz2007 )实现了根据给定视角来近似点云的可见性,而无需曲面重建或法向估计。
[14]:print("Convert mesh to a point cloud and estimate dimensions")pcd = o3dtut.get_armadillo_mesh().sample_points_poisson_disk(5000)diameter = np.linalg.norm(    np.asarray(pcd.get_max_bound()) - np.asarray(pcd.get_min_bound()))o3d.visualization.draw_geometries([pcd])
Convert mesh to a point cloud and estimate dimensionsdownloading armadillo meshextract armadillo mesh

python open3d_Open3D点云操作_第12张图片

[15]:print("Define parameters used for hidden_point_removal")camera = [0, 0, diameter]radius = diameter * 100print("Get all points that are visible from given view point")_, pt_map = pcd.hidden_point_removal(camera, radius)print("Visualize result")pcd = pcd.select_by_index(pt_map)o3d.visualization.draw_geometries([pcd])
Define parameters used for hidden_point_removalGet all points that are visible from given view pointVisualize result

python open3d_Open3D点云操作_第13张图片

 >>>>>>>>>>>> THE END <<<<<<<<<<<<

python open3d_Open3D点云操作_第14张图片

扫码关注我们 喜欢就点“在看” 

你可能感兴趣的:(python,open3d)