01 读取与保存图像
001点云图像与保存读取代码:
读取点云图像数据,路径自己可以改成自己的。
import open3d as o3d
print("Testing IO for point cloud ...")
sample_pcd_data = o3d.data.PCDPointCloud()
# 读取点云图像
pcd = o3d.io.read_point_cloud(sample_pcd_data.path)
print(pcd)
# 保存点云图像
o3d.io.write_point_cloud("copy_of_fragment.pcd", pcd)
如果不改自己的路径的话,则会自动进行下载,如下图所示:
它支持以下的格式:常见的pcd,xyz,ply等。
002读取网格图像:三维模型
可以读取stl格式的,ply等格式的
import open3d as o3d
print("Testing IO for meshes ...")
knot_data = o3d.data.KnotMesh()
mesh = o3d.io.read_triangle_mesh(knot_data.path)
print(mesh)
o3d.io.write_triangle_mesh("copy_of_knot.ply", mesh)
支持的格式类型:
02 点云图像的显示
关键函数:o3d.visualization.draw_geometries([ ])
函数参数说明:
Parameters
-
geometry_list (List[open3d.geometry.Geometry]) – List of
geometries to be visualized.# 你需要显示的点云数据,采用列表的形式存储 -
window_name (str, optional, default=‘Open3D’) – The displayed title of the visualization window. # 窗口名称
-
width (int, optional, default=1920) – The width of the visualization window.
-
height (int, optional, default=1080) – The height of the visualization window.
-
left (int, optional, default=50) – The left margin of the visualization window.
-
top (int, optional, default=50) – The top margin of the visualization window.
-
point_show_normal (bool, optional, default=False) – Visualize point normals if set to true. # 这个是显示点云数据的法线
-
mesh_show_wireframe (bool, optional, default=False) – Visualize mesh wireframe if set to true.
-
mesh_show_back_face (bool, optional, default=False) – Visualize also the back face of the mesh triangles.
-
lookat (numpy.ndarray[numpy.float64[3, 1]]) – The lookat vector of the camera.
-
up (numpy.ndarray[numpy.float64[3, 1]]) – The up vector of the camera.
-
front (numpy.ndarray[numpy.float64[3, 1]]) – The front vector of the camera.
-
zoom (float) – The zoom of the camera.
Returns
None
返回值:
None
这个代码中,如果你没有点云数据的话,open3d会自动下载官网的数据集。
例如:
import open3d as o3d
import numpy as np
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)
# 显示函数,pcd为你想要显示的内容
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])
显示的结果:
03 点云数据的上色
关键函数:paint_uniform_color([, ])
函数说明:分别是RGB三种颜色,颜色范围是0-1之间
举个例子:我将图像上色成红色([1,0,0])
import open3d as o3d
import numpy as np
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)
pcd.paint_uniform_color([1,0,0])
# 显示函数,pcd为你想要显示的内容
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])
某个点单独上色:
pcd.colors(n) = (1,0,0)
输出的结果:
04 点云图像的体素化下采样
关键函数:voxel_down_sample(voxel_size=?)
函数说明:voxel_size为人工设定的数,一般很小,参考值0.05
举个例子:
import open3d as o3d
import numpy as np
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)
pcd.paint_uniform_color([1,0,0])
# 进行下采样
downpcd = pcd.voxel_down_sample(voxel_size=0.05)
# 显示函数,pcd为你想要显示的内容
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])
对上面的点云进行体素化下采样后得到:
05 点云的分割
06 点云的配准
点云的配准就是将两个点云进行配准。
点云的粗配准全局配准(粗配准)
步骤1:首先定义一个函数,用于显示图像
# 定义一个函数,用于显示显示
def draw_registration_result(source, target, transformation):
# 分别显示的是源点云,目标点云,
source_temp = copy.deepcopy(source)
target_temp = copy.deepcopy(target)
source_temp.paint_uniform_color([1, 0, 0]) # 源点云上红色
target_temp.paint_uniform_color([0, 1, 0]) # 目标点云上绿色
source_temp.transform(transformation) # 对源点云进行矩阵的变换
# 然后对源点云进行变换后进行,和目标点云一起显示
o3d.visualization.draw_geometries([source_temp, target_temp],
zoom=0.4559,
front=[0.6452, -0.3036, -0.7011],
lookat=[1.9892, 2.0208, 1.8945],
up=[-0.2779, -0.9482, 0.1556])
步骤2:提取特征,提取特征才能进行配准
# 点云配准,第一步肯定需要提取特征才能进行配准
# 写一个函数,用于提取几何特征,为后续的配准做准备
def preprocess_point_cloud(pcd, voxel_size):
# 输出的结果为下采样的点云,以及PCD的FPFH特征点
# print(":: Downsample with a voxel size %.3f." % voxel_size)
# 对输入的点云进行体素化下采样,体素化的大小voxel_size
pcd_down = pcd.voxel_down_sample(voxel_size)
# 人工设置半径大小
radius_normal = voxel_size * 2
# print(":: Estimate normal with search radius %.3f." % radius_normal)
# 对下采样后的点云进行法线估计,采用的方法为KD_Trees,混合搜索方法,两个参数分别为最大半径,以及搜索的数量
pcd_down.estimate_normals(
o3d.geometry.KDTreeSearchParamHybrid(radius=radius_normal, max_nn=30))
# 计算FPFH需要输入一个半径范围
radius_feature = voxel_size * 5
print(":: Compute FPFH feature with search radius %.3f." % radius_feature)
pcd_fpfh = o3d.pipelines.registration.compute_fpfh_feature(
pcd_down,
o3d.geometry.KDTreeSearchParamHybrid(radius=radius_feature, max_nn=100))
return pcd_down, pcd_fpfh
步骤3:准备数据,读取需要配准的数据
# 准备加载的数据
# 写一个函数,用于读取需要加载的数据
def prepare_dataset(voxel_size):
# 这个函数只是用于加载点云数据
print(":: Load two point clouds and disturb initial pose.")
# 以下的三行代码可以根据自己的需要进行更改,更改成自己的点云数据,此处读取的官方的点云数据
demo_icp_pcds = o3d.data.DemoICPPointClouds()
source = o3d.io.read_point_cloud(demo_icp_pcds.paths[0])
target = o3d.io.read_point_cloud(demo_icp_pcds.paths[1])
# 设置一个变换矩阵
# trans_init = np.asarray([[0.0, 0.0, 1.0, 0.0], [1.0, 0.0, 0.0, 0.0],
# [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 0.0, 1.0]])
# # 对源点云进行了变换显示
# source.transform(trans_init)
# # 调用上方的函数进行了显示,分别显示了源点云,目标点云,这个输入的矩阵是单位矩阵。
draw_registration_result(source, target, np.identity(4))
# 对源点云进行下采样,进行提取FPFH特征点
source_down, source_fpfh = preprocess_point_cloud(source,