importopen3daso3dif__name__=="__main__":pcd_data=o3d.data.PCDPointCloud()print(f"Reading pointcloud from file: fragment.pcd stored at {pcd_data.path}")pcd=o3d.io.read_point_cloud(pcd_data.path)print(pcd)print("Saving pointcloud to file: copy_of_fragment.pcd")o3d.io.write_point_cloud("copy_of_fragment.pcd",pcd)
Check the folder before and after o3d.io.write_point_cloud()
2. Visualize Point Cloud
1
2
3
4
5
6
7
8
9
print("Load a ply point cloud, print it, and render it")sample_ply_data=o3d.data.PLYPointCloud()pcd=o3d.io.read_point_cloud(sample_ply_data.path)# Flip it, otherwise the pointcloud will be upside down.pcd.transform([[1,0,0,0],[0,-1,0,0],[0,0,-1,0],[0,0,0,1]])print(pcd)# PointCloud with 196133 points.o3d.visualization.draw_geometries([pcd])
It looks like a dense surface, but it is actually a point cloud rendered as surfels.
The GUI supports various keyboard functions.
For instance, the - key reduces the size of the points (surfels).
3. Voxel Downsampling
Voxel downsampling uses a regular voxel grid to create a uniformly downsampled point cloud from an input point cloud.
Voxel in 3D point cloud = Pixel in 2D image
It is often used as a pre-processing step for many point cloud processing tasks.
The algorithm operates in two steps:
Points are bucketed into voxels.
Each occupied voxel generates exactly one point by averaging all points inside.
1
2
3
4
print("Downsample the point cloud with a voxel of 0.05")downpcd=pcd.voxel_down_sample(voxel_size=0.05)print(downpcd)# PointCloud with 4838 points.o3d.visualization.draw_geometries([downpcd])
4. Vertex Normal Estimation
estimate_normals() computes the normal for every point.
The function finds adjacent points and calculates the principal axis of the adjacent points using covariance analysis.
The function takes an instance of KDTreeSearchParamHybrid class as an argument.
it specifies search radius radius = 0.1 and maximum nearest neighbor max_nn=30 to save computation time.
1
2
3
4
5
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],point_show_normal=True)
Open3D tries to orient the normal to align with the original normal if it exists.
Otherwise, Open3D does a random guess.
Further orientation functions such as orient_normals_to_align_with_direction and orient_normals_towards_camera_location need to be called if the orientation is a concern.
5. Crop Point Cloud
read_selection_polygon_volume() reads a json file that specifies polygon selection area.
vol.crop_point_cloud(pcd) filters out points. Only the chair remains.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
print("Load a ply point cloud, crop it, and render it")sample_ply_data=o3d.data.DemoCropPointCloud()pcd=o3d.io.read_point_cloud(sample_ply_data.point_cloud_path)vol=o3d.visualization.read_selection_polygon_volume(sample_ply_data.cropped_json_path)chair=vol.crop_point_cloud(pcd)# Flip the pointclouds, otherwise they will be upside down.pcd.transform([[1,0,0,0],[0,-1,0,0],[0,0,-1,0],[0,0,0,1]])chair.transform([[1,0,0,0],[0,-1,0,0],[0,0,-1,0],[0,0,0,1]])print("Displaying original pointcloud ...")o3d.visualization.draw([pcd])print("Displaying cropped pointcloud")o3d.visualization.draw([chair])
6. Paint Point Cloud
paint_uniform_color([R,G,B]) paints all the points to a uniform color.
source.compute_point_cloud_distance(target) computes for each point in the source point cloud the distance to the closest point in the target point cloud.
1
2
3
4
5
6
7
8
9
dists=pcd.compute_point_cloud_distance(chair)dists=np.asarray(dists)print("Printing average distance between the two point clouds ...")print(dists)# .shape = # of points# Filter out the points that has distance from the chairind=np.where(dists>0.01)[0]pcd_without_chair=pcd.select_by_index(ind)o3d.visualization.draw_geometries([pcd_without_chair])
8. Bounding Volumes
Open3D implements an AxisAlignedBoundingBox and an OrientedBoundingBox that can also be used to crop the geometry.
1
2
3
4
5
6
7
8
9
10
axis_aligned=pcd.get_axis_aligned_bounding_box()axis_aligned.color=(1,0,0)oriented=pcd.get_oriented_bounding_box()oriented.color=(0,1,0)print("Displaying axis_aligned_bounding_box in red and oriented bounding box in green ...")o3d.visualization.draw([pcd,axis_aligned,oriented])
9. DBSCAN Clustering
Given a Point Cloud from a RGB-Depth sensor, we want to group local point cloud clusters together.
Open3D implements DBSCAN [Ester1996] that is a Density-based clustering algorithm.
The algorithm is implemented in cluster_dbscan and requires two parameters:
eps defines the distance to neighbors in a cluster and
min_points defines the minimum number of points required to form a cluster.
The function returns labels, where the label -1 indicates noise.