numpy中的点云操作

numpy中的点云操作

      • 一、点云数据转换为`numpy`数组
          • 1.1 使用`np.asarray`将点云转换为`ndarray`(推荐)
          • 1.2 使用`np.array`将点云转换为`ndarray`
      • 二、点云数组切片
      • 三、点云数据与`np.where()`使用(重点)
          • 3.1 `np.where`获得点云圆柱
          • 3.2 `np.where()`获得正方形
          • 3.3 `np.where()`获得长方形
          • 3.4 `np.where`向量法提取点云
          • 3.5 `np.where` 椭圆提取
          • 3.6 生成直线
      • 四、获得点云最大最小值
          • 4.1 `np.min()`获得最小值(推荐)
          • 4.2 `min()`获得最小值
          • 4.3 `np.max()`获得最大值(推荐)
          • 4.4 `max()`获得最大值
          • 4.5 `np.argmin()`获得最小值的点云值
          • 4.5 `np.argmax()`获得最大值的点云值
      • 五、`numpy`转回点云数据
      • 六、`np.mean()`计算密度

一、点云数据转换为numpy数组

1.1 使用np.asarray将点云转换为ndarray(推荐)
points = np.asarray(pcd.points)
1.2 使用np.array将点云转换为ndarray
points = np.asarray(pcd.points)

注意

arrayasarray都可以将结构数据转化为ndarray,但是主要区别就是当数据源是ndarray时,array仍然会copy出一个副本,占用新的内存,但asarray不会。

二、点云数组切片

获得数组的长度

>>>print(len(points))
35947

数组切片

获得数组的前10个数据,包括x,y,z轴。points[切片的起始位置:切片的截至位置]

>>>print(points[:10])
[[-0.0378297   0.12794     0.00447467]
 [-0.0447794   0.128887    0.00190497]
 [-0.0680095   0.151244    0.0371953 ]
 [-0.00228741  0.13015001  0.0232201 ]
 [-0.0226054   0.12667499  0.00715587]
 [-0.0251078   0.125921    0.00624226]
 [-0.0371209   0.12744901  0.0017956 ]
 [ 0.033213    0.112692    0.0276861 ]
 [ 0.0380425   0.109755    0.0161689 ]
 [-0.0255083   0.112568    0.0366767 ]]

获得数组前10个位置,只有x轴,points[切片的起始位置:切片的截至位置, 获得轴(x:0, y:1 z:2)]

>>>print(points[:10, 0])
[-0.0378297  -0.0447794  -0.0680095  -0.00228741 -0.0226054  -0.0251078
 -0.0371209   0.033213    0.0380425  -0.0255083 ]

三、点云数据与np.where()使用(重点)

np.where()的存在使得点云数据操作具有更多的灵活性,从直通滤波到特定范围的截取,都可以直接进行。这种灵活性让点云处理的功能得到了极大的扩展,同时由于numpy底层使用了计算机的高效操作指令,因此处理速度更快,以下是冰山一角,更多自行研究即可。

3.1 np.where获得点云圆柱
	pcd = o3d.io.read_point_cloud('res/bunny.pcd')
    # 将点云准换为数组
    points = np.asarray(pcd.points)
    # 获得一个点作为中心
    center = points[0]
    # 获得以中心点半径为0.05的圆柱
    index = np.where((center[0] - points[:, 0])**2 + (center[1] - points[:, 1])**2 < 0.05**2)[0]
    # 获得截取点云
    cl = points[index]
    # 将numpy转换为点云
    project_cloud = o3d.geometry.PointCloud()  # 使用numpy生成点云
    project_cloud.points = o3d.utility.Vector3dVector(cl)
    project_cloud.paint_uniform_color([0, 0, 1.0])  # 渲染颜色
    o3d.visualization.draw_geometries([project_cloud, pcd])

原理

  • (center[0] - points[:, 0])**2 + (center[1] - points[:, 1])**2:计算了每个点与中心点之间的欧氏距离的平方。这是一个数组,其中每个元素表示对应点与中心点的距离的平方。< 0.05**2:检查上述计算的距离平方是否小于0.05的平方。这里0.05是给定的阈值,表示距离的最大允许值。

点云颜色渲染参考: 基础点云学习:点云上色、大小改变、窗口背景改变、绘制常用类型图形-CSDN博客

numpy中的点云操作_第1张图片

3.2 np.where()获得正方形
pcd = o3d.io.read_point_cloud('res/monkey.ply')
# 设置pcd颜色为纯色
pcd.paint_uniform_color([211, 211, 211])  # 渲染颜色灰色
o3d.visualization.draw_geometries([pcd])
# 将点云准换为数组
points = np.asarray(pcd.points)
# 获得一个点作为中心
center = points[0]
# 获得以中心点为0.1的正方形
index = np.where(((center[0] - points[:, 0]) > 0.05) & ((center[1] - points[:, 1]) > 0.05))[0]

# 获得截取点云
cl = points[index]
# 将numpy转换为点云
project_cloud = o3d.geometry.PointCloud()  # 使用numpy生成点云
project_cloud.points = o3d.utility.Vector3dVector(cl)
project_cloud.paint_uniform_color([1, 0, 0])  # 渲染颜色红色
o3d.visualization.draw_geometries([project_cloud, pcd])

注意

x,y轴阈值一定要一致,也就是说不适合长方形,z轴限制随意。

原理

  • (center[0] - points[:, 0]) > 0.05:计算了每个点相对于中心点在水平方向(x 轴方向)的距离是否大于0.05。这是一个布尔值数组,其中每个元素表示对应点在 x 轴方向上是否距离中心点大于0.05。(center[1] - points[:, 1]) > 0.05:类似地,这一部分计算了每个点相对于中心点在垂直方向(y 轴方向)的距离是否大于0.05。这也是一个布尔值数组。((center[0] - points[:, 0]) > 0.05) & ((center[1] - points[:, 1]) > 0.05):通过逻辑与运算符 & 结合两个条件,得到一个新的布尔值数组,其中元素为 True 表示对应点在水平和垂直方向上都大于0.05的条件同时满足。

numpy中的点云操作_第2张图片

3.3 np.where()获得长方形

前提

必须要有两个确定的点。。自行思考即可。。

pcd = o3d.io.read_point_cloud('res/monkey.ply')
# 设置pcd颜色为纯色
pcd.paint_uniform_color([211, 211, 211])  # 渲染颜色灰色
# o3d.visualization.draw_geometries([pcd])
# 将点云准换为数组
points = np.asarray(pcd.points)
# 获得一个点作为开始
center = points[0]
# 设置截至点为
over = points[100]
# 获得限制
x = over[0] - center[0]
y = over[1] - center[1]
# 获得以中心点为0.1的正方形
index = np.where(((center[0] - points[:, 0]) > x) & ((center[1] - points[:, 1]) > y))[0]
print(index)
# 获得截取点云
cl = points[index]
# 将numpy转换为点云
project_cloud = o3d.geometry.PointCloud()  # 使用numpy生成点云
project_cloud.points = o3d.utility.Vector3dVector(cl)
project_cloud.paint_uniform_color([1, 0, 0])  # 渲染颜色红色
o3d.visualization.draw_geometries([project_cloud, pcd])

注意

必须要有两个确定的点。。自行思考即可。。

原理

  • (center[0] - points[:, 0]) > x:计算了每个点相对于中心点在水平方向(x 轴方向)的距离是否大于 x。这是一个布尔值数组,其中每个元素表示对应点在 x 轴方向上是否距离中心点大于 x

    (center[1] - points[:, 1]) > y:类似地,这一部分计算了每个点相对于中心点在垂直方向(y 轴方向)的距离是否大于 y。这也是一个布尔值数组。((center[0] - points[:, 0]) > x) & ((center[1] - points[:, 1]) > y):通过逻辑与运算符 &结合两个条件,得到一个新的布尔值数组,其中元素为True表示对应点在水平和垂直方向上都大于xy` 的条件同时满足。

numpy中的点云操作_第3张图片

3.4 np.where向量法提取点云

参考点云数据点根据向量提取(传统方法)-CSDN博客

等等。。。。。太多了后面慢慢来吧。。

3.5 np.where 椭圆提取
# 获得一个实心椭圆柱
    pcd = o3d.io.read_point_cloud('res/bunny.pcd')
    pcd.paint_uniform_color([0.5, 0.5, 0.5])
    points = np.asarray(pcd.points)
    pcd.colors[0] = [0, 1, 0]  # 给定查询点并渲染为绿色
    start = points[0]
    end = points[len(points) - 1]
    pcd.colors[len(points) - 1] = [0, 1, 0]  # 给定查询点并渲染为绿色
    dis = np.sqrt((end[0] - start[0])**2 + (end[1] - start[1])**2) + 0.05   # 为了跟明显加个阈值
    index = np.where((np.sqrt((points[:, 0] - end[0])**2 + (points[:, 1] - end[1])**2) + np.sqrt((points[:, 0] - start[0])**2 + (points[:, 1] - start[1])**2))<=dis)[0]
    # 获得点云
    cl = pcd.select_by_index(index)
    cl.paint_uniform_color([1, 0.706, 0])
    o3d.visualization.draw_geometries([cl, pcd])

原理
根据已知的2给点云,计算所有点到这两给点的距离,使其小于2个点的距离即可,为了更加清晰,增添了一个阈值。
点云上色参考:基础点云学习:点云上色、大小改变、窗口背景改变、绘制常用类型图形
numpy中的点云操作_第4张图片

3.6 生成直线
	x = np.linspace(-3, 3, 1500)  # 获得-3-3的1500个数
    mesh_x, mesh_y = np.meshgrid(x, x)
    xyz = np.zeros((np.size(mesh_x), 3))
    xyz[:, 0] = np.reshape(mesh_x, -1)     # x轴
    xyz[:, 1] = 0.1                        # y
    xyz[:, 2] = -0.0025                    # z

    project_cloud = o3d.geometry.PointCloud()  # 使用numpy生成点云
    project_cloud.points = o3d.utility.Vector3dVector(xyz)  # points numpy数组
    o3d.visualization.draw_geometries([project_cloud])

原理
首先使用np.linspace函数生成一个从-3到3的包含1500个数的数组x。然后,利用np.meshgrid函数生成了一个二维网格坐标系,其中mesh_x和mesh_y分别表示x和y坐标轴上的坐标值网格。
接着,创建了一个形状为(n*m, 3)的零数组xyz,其中n和m分别是mesh_x和mesh_y的形状。然后,通过np.reshape函数将mesh_x数组展平为一维数组,并将其赋值给xyz数组的第一列,以表示x坐标轴上的坐标值。将0.1赋值给xyz数组的第二列,以表示y坐标轴上的坐标值。将-0.0025赋值给xyz数组的第三列,以表示z坐标轴上的坐标值。
最终,xyz数组中的每一行都表示了三维空间中一个网格点的坐标。
numpy中的点云操作_第5张图片

四、获得点云最大最小值

4.1 np.min()获得最小值(推荐)
>>>print(np.min(points[:, 0])) # 可以自己选择轴 0:x 1:y z:2
-1.184253
4.2 min()获得最小值
>>>print(min(points[:, 0])) # 可以自己选择轴 0:x 1:y z:2
-1.184253

注意:

np.min通常比Python内置的min函数更高效,特别是对于大型数组的处理。

4.3 np.max()获得最大值(推荐)
>>>print(np.max(points[:, 0])) # 可以自己选择轴 0:x 1:y z:2
1.477114
4.4 max()获得最大值
print(max(points[:, 0])) # 可以自己选择轴 0:x 1:y z:2
1.477114

注意

np.max 通常比 Python 内置的 max 函数更高效,特别是对于大型数组的处理。

4.5 np.argmin()获得最小值的点云值
>>>print(np.argmin(points, axis=0))
# x       y    z   的索引值
[30352  3366 17012]

# 获得索引项值
print(points[np.argmin(points, axis=0)])
[[-1.184253  0.776817  0.099082]     x 轴
 [ 0.458676 -0.531232  0.09961 ]     y 轴
 [ 0.14643  -0.246726 -1.116541]]    z 轴

原理

np.argmin()np.min()类似:np.min()返回指定轴的最小值,而np.argmin()返回指定轴的最小值对应的索引,指定哪个轴,就按哪个轴进行拆分。

4.5 np.argmax()获得最大值的点云值
>>>print(np.argmax(points, axis=0))
# x       y    z   的索引值
[30288 19303 19484]

>>>print(points[np.argmax(points, axis=0)])
[[1.477114 0.776817 0.099082]    x 轴
 [0.14643  1.075554 0.152837]    y
 [0.14643  0.37864  0.798498]]   z 

原理

np.argmax()np.max()类似:np.max()返回指定轴的最大值,而np.argmax()返回指定轴的最大值对应的索引,指定哪个轴,就按哪个轴进行拆分。

比较仔细的细节大家搜索一下吧。。。。

五、numpy转回点云数据

project_cloud = o3d.geometry.PointCloud()  # 使用numpy生成点云
project_cloud.points = o3d.utility.Vector3dVector(points)   # points numpy数组

六、np.mean()计算密度

import open3d as o3d
import numpy as np
if __name__ == '__main__':


    print("->正在加载点云... ")
    point_cloud = o3d.io.read_point_cloud("res/bunny.pcd")
    # 对于每个点,都计算了离他最近的点的距离,由此可以得知这堆点云的所有点之间的平均距离
    distances = point_cloud.compute_nearest_neighbor_distance()
    avg_dist = np.mean(distances)
    print("点云密度为=", avg_dist)

后期持续更新。。。

你可能感兴趣的:(open3d持续更新,numpy,3d,python,计算机视觉)