slam系列1:open3d入门笔记

1. 读写数据

这里有很多测试用的pcd文件:
https://github.com/PointCloudLibrary/data/blob/master/tutorials/

import open3d as o3d
pcd = o3d.io.read_point_cloud("test.pcd")
o3d.io.write_point_cloud("write.pcd", pcd, True)	# 默认false,保存为Binarty;True 保存为ASICC形式
# o3d.visualization.draw_geometries([pcd]) # 传统画图法
o3d.visualization.draw_plotly_server([pcd]) # 在jupyter内展示,但是只能绘制点云

在这里插入图片描述

2. 常用工具

2.1 几何

# 读写
## 读取rgbd数据
pcd = o3d.geometry.PointCloud.create_from_rgbd_image(rgbd_image,o3d.camera.PinholeCameraIntrinsic(
		o3d.camera.PinholeCameraIntrinsicParameters.PrimeSenseDefault))
##

## 直接读取
pcd = o3d.io.read_point_cloud(...)
# 绘制法线
pcd.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(0.1, 30))     # 执行法线估计
o3d.visualization.draw_geometries([pcd], point_show_normal = True)

# 建立KDTree用于近邻查询
pcd_tree = o3d.geometry.KDTreeFlann(pcd)
pcd.paint_uniform_color([0.5, 0.5, 0.5])
# 使用K近邻,将第1500个点最近的5000个点设置为蓝色
[num_k, idx_k, _] = pcd_tree.search_knn_vector_3d(pcd.points[1500], 1000)    # 返回邻域点的个数和索引
np.asarray(pcd.colors)= [0, 0, 1]  # 进行赋色

# 建立八叉树用于空间划分
octree = o3d.geometry.Octree(max_depth=10)
octree.convert_from_point_cloud(pcd, size_expand=0.1)
o3d.visualization.draw_geometries([octree])

# 获取体素及下采样
voxel_grid = o3d.geometry.VoxelGrid.create_from_point_cloud(pcd, voxel_size=0.2)
downpcd = pcd.voxel_down_sample(0.5)


# compute_point_cloud_distance方法为源点云中的每个点计算到目标点云中最近点的距离。
dists = pcd1.compute_point_cloud_distance(pcd2)

# pcd.get_center() 获取质心
# pcd.select_by_index() 根据下标列表获取点云子集
# pcd.get_axis_aligned_bounding_box() 获取轴线方向最小包围盒
# pcd.get_oriented_bounding_box() 获取最小包围盒
# pcd.crop_point_cloud() 进行裁剪
# 计算点云凸包
hull, _ = pcd.compute_convex_hull()
hull_ls = o3d.geometry.LineSet.create_from_triangle_mesh(hull)


2.2 滤波

统计滤波
在这里插入图片描述
半径滤波
在这里插入图片描述

# 滤波例子
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])

2.3 聚类和分割

# 聚类例子
print("->正在DBSCAN聚类...")
eps =5    # 同一聚类中最大点间距
min_points = 10   # 有效聚类的最小点数
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_plotly_server([pcd])

# 平面分割
print("->正在RANSAC平面分割...")
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])
print(inlier_cloud)
# 平面外点点云
outlier_cloud = pcd.select_by_index(inliers, invert=True)
outlier_cloud.paint_uniform_color([1.0, 0, 0])
print(outlier_cloud)

# 隐藏点去除
print("->正在剔除隐藏点...")
diameter = np.linalg.norm(np.asarray(pcd.get_max_bound()) - np.asarray(pcd.get_min_bound()))
print("定义隐藏点去除的参数")
camera = [0, 0, diameter]       # 视点位置
radius = diameter * 100         # 噪声点云半径,The radius of the sperical projection
_, pt_map = pcd.hidden_point_removal(camera, radius)    # 获取视点位置能看到的所有点的索引 pt_map
# 可视点点云
pcd_visible = pcd.select_by_index(pt_map)
pcd_visible.paint_uniform_color([0, 0, 1])	# 可视点为蓝色
print("->可视点个数为:", pcd_visible)
# 隐藏点点云
pcd_hidden = pcd.select_by_index(pt_map, invert = True)
pcd_hidden.paint_uniform_color([1, 0, 0])	# 隐藏点为红色
print("->隐藏点个数为:", pcd_hidden)
print("->正在可视化可视点和隐藏点点云...")
o3d.visualization.draw_plotly_server([pcd_visible, pcd_hidden])

2.4 曲面重建

目前实现了如下几种:
在这里插入图片描述

mesh, densities  = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(pcd, depth=8)
mesh  = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(pcd,8)

我们对比一下效果
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2.5 空间变换

# 平移
pcd.translate((tx,ty,tz),relative=True)
# 旋转
R1 = pcd.get_rotation_matrix_from_xyz((0,np.pi/2,0))
pcd.rotate(R1)   

# 点云缩放
pcd.scale(0.5,center=(1,1,1))	

# 一般变换:4×4变换矩阵,前3行3列为旋转矩阵,第4列前3行为平移向量,右下角为缩放系数。
pcd_scale2.transform(T)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值