1. 点云边界框

点云几何类型和其他类型一样,也有包围框。当前,open3d实现了两个包围框接口, AxisAlignedBoundingBox OrientedBoundingBox ,它们区别如下表所示。同时他们也可以用来裁剪几何图形。

函数 名称 说明 图形说明
AxisAlignedBoundingBox 轴对齐边界框aabb 每条边都有平行的轴 在这里插入图片描述
OrientedBoundingBox 定向边界框obb 边和轴有一定的 夹角 在这里插入图片描述
import open3d as o3d
import numpy as np
#*******************************包围框***********************************
pcd = o3d.io.read_point_cloud("../test_data/fragment.ply") # 读取ply或者pcd文件
#读取裁剪的文件
vol = o3d.visualization.read_selection_polygon_volume(
    "../test_data/Crop/cropped.json")
chair = vol.crop_point_cloud(pcd)#裁剪椅子
# o3d.visualization.draw_geometries([chair]) #显示椅子
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])

2. 凸包(convex hull)

点云的凸包是包含所有点的最小凸集,open3d实现了计算凸包的方法compute_convex_hull,这个接口的实现基于Qhull

import open3d as o3d
import numpy as np
#*******************************凸包***********************************
pcd = o3d.io.read_point_cloud("../test_data/fragment.ply") # 读取ply或者pcd文件
# 裁剪点云
vol = o3d.visualization.read_selection_polygon_volume(
    "../test_data/Crop/cropped.json")
chair = vol.crop_point_cloud(pcd)
# 计算点云的凸包
hull, _ = chair.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([chair, hull_ls])

3. DBSCAN聚类

open3d实现了DBSCAN[Ester1996]算法,这是一种基于密度的聚类算法。该算法需要两个参数。

labels = np.array(pcd.cluster_dbscan(eps=0.02, min_points=10, print_progress=True))
 
  • eps: 定义到聚类相邻点云的距离
  • min_points: 定义形成聚类所需的最小点数

该函数返回一个标签,其中标签-1表示噪音。

import open3d as o3d
import numpy as np
import matplotlib.pyplot as plt
#*******************************DBSCAN***********************************
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] = 0
pcd.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 neighbors.
Precompute neighbors.[========================================] 100%
[Open3D DEBUG] Done Precompute neighbors.
[Open3D DEBUG] Compute Clusters
[Open3D DEBUG] Done Compute Clusters: 10==========>] 97%
point cloud has 10 clusters

4. RANSAC平面分割

Open3D还支持使用RANSAC从点云分割算法,其中segment_plane用于平面分割算法,该算法的有三个参数:

  1. distance_threshold:inlier的最大距离阈值
  2. ransac_n:随机采样的平面点数
  3. num_iterations:表示最小迭代次数。
import open3d as o3d
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_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([1.0, 0, 0]) # inliers为红色
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.06x + -0.10y + 0.99z + -1.06 = 0

5. 隐点移除(Hidden point removal)

由于点云分辨率的问题,如果你只想看前景点,就需要滤掉背景点。为此,我们可以应用隐藏点移除(Hidden point removal)算法该方法可以近似的给出一个视角下的可视点云

import open3d as o3d
import numpy as np
pcd = o3d.io.read_point_cloud("../test_data/fragment.ply") # 读取ply或者pcd文件
diameter = np.linalg.norm(
    np.asarray(pcd.get_max_bound()) - np.asarray(pcd.get_min_bound()))
o3d.visualization.draw_geometries([pcd])
print("Define parameters used for hidden_point_removal")
camera = [0, 0, diameter] # 定义用于隐藏点删除的参数,获取从给定视图中可见的所有点,可视化结果
radius = diameter * 100
print("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_removal
Get all points that are visible from given view point
Visualize result

原始视角下的视图:
在这里插入图片描述
经过隐点移除之后的视图:
在这里插入图片描述

此函数尝试将 Qhull/convexhulln 生成的 3D 点云凸包转换为(更多)凹包。 同样,输出格式为 k [nx 3],它将 n 个三角形定义为 XYZ 中的行。 如果该函数找到一个三角形,该三角形的 2 条边的中点距离点云中的另一个点比 thresh 更远,它会删除该三角形并用三个新三角形替换它,这些三角形由数据云中最近的点定义到老二中点。 该算法肯定还不是最佳的,如果有人有想法甚至改进的实现,我自己会很高兴。 我仍然上传了它,因为很长时间以来我一直在寻找自己类似的东西,却没有找到对我有用的东西。 输入: – XYZ:xyz 坐标点云thresh:阈值定义所有中点的接近程度线远离点云中的最近点,使算法停止。 尽管如此,即使设置,算法有时在此之前停止,如果距离不再改善。 在换句话说,该算法不保证阈值总是匹配的。 输出:-k:三角索引(作为凹面的输出) Open3D还支持使用RANSAC点云中分割几何图元。 要查找点云中最有可能存在的平面,我们使用segement_plane函数。 该方法具有三个参数:destance_threshold定义了一个点到一个估计平面的最大距离,这些距离内的点被认为是内点(inlier),ransac_n定义了使用随机抽样估计一个平面的点的个数,num_iterations定义了随机平面采样和验证的频率(迭代次数)。这个函数返回(a,b,c,d)作为一个平面,对于平面上每个点(x,y,z)我们有ax+by+cz+d=0。这个 点云特征在定义上(以我个人理解)大致可以分为两大类: 一类是类似于深度学习的featrue map意义,通过计算一些算子来描述点云局部,这种描述只是一种标识符,并没有实际的几何意义,比如 PFH或者 FPFH 之类的,它们只是通过对每个点的局部邻域计算一个 125125125 维或者 333333 维的向量来描述当前点,这跟机器学习中的 featurefeaturefeature 是一样的,通过这类特征可以用来做点云的配准(其中某些特征可以进一步处理【模式识别】得到几何特征,因为某一类的几何特征在 1、原理介绍 由Edelsbrunner H提出的alpha shapes算法是一种简单、有效的快速提取边界点算法。其克服了点云边界点形状影响的缺点,可快速准确提取边界点,其原理如下: 如下图所示,对于任意形状的平面点云,若一个半径为a的圆,绕其进行滚动,其滚动的轨迹形成的点为轮廓点。需要注意的是,alpha shapes算法只能探测二维点的轮廓点,大多数是将点投影到二维平面,形成二维点,再进行轮廓点探测。 通过计算凸包,我们可以得到点云数据的简化表示,以及进行形状分析、物体识别和运动规划等任务。通过使用Open3D,我们可以方便地进行点云数据的几何计算和可视化。在上述代码中,我们首先生成了一个包含100个随机二维点的点云数据。然后,我们创建了一个Open3D点云对象,并将随机点云数据赋值给它。除了计算二维凸包Open3D还提供了许多其他功能,如三维凸包计算、体素网格化、点云滤波等。在本文中,我们将探讨如何使用Open3D计算二维点云凸包。通过运行上述代码,您将能够看到显示出的二维点云以及计算得到的凸包点云(Point Cloud) 这文章将会介绍点云数据的一些基本用法。(本教程可视化的点云数据为官方图片,自己可以根据手头数据进行测试,或者去官方github主页下载对应测试数据) 可视化点云 本教程的第一部分是读取点云数据并将其可视化。 print("Load a ply point cloud, print it, and render it") pcd = o3d.io.read_point_cloud("../../TestData/fragment.ply") print(pcd) print( 可视化的目标检测,故开始考虑使用点云在ros的rviz中进行实验。画boundingbox需要用到的函数boudingBOX.py。本机相关环境:ubutnu20.04 ros_neotic。准备小车模型:将解压后的car.dae存放在指定路径下。