numpy中的点云操作

一、点云数据转换为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博客

在这里插入图片描述

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的条件同时满足。

在这里插入图片描述

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` 的条件同时满足。

在这里插入图片描述

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个点的距离即可,为了更加清晰,增添了一个阈值。
点云上色参考:基础点云学习:点云上色、大小改变、窗口背景改变、绘制常用类型图形
在这里插入图片描述

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数组中的每一行都表示了三维空间中一个网格点的坐标。
在这里插入图片描述

四、获得点云最大最小值

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)

七、生成随机点云

import numpy as np
import open3d as o3d

if __name__ == '__main__':
    # 加载点云
    size_a, size_b = 100, 70  # 设置生成数目的大小
    a = np.random.ranf(size_a * 3).reshape(-1, 3)  # 生成一个大小为size_a*3的一维数组,然后使用reshape函数将其重新排列为一个二维数组
    cloud1 = o3d.geometry.PointCloud()  # 使用numpy生成点云
    cloud1.points = o3d.utility.Vector3dVector(a)  # points numpy数组
    # 转换为点云格式

    b = np.random.ranf(size_b * 3).reshape(-1, 3)  # 生成一个大小为size_b*3的一维数组,然后使用reshape函数将其重新排列为一个二维数组

    cloud2 = o3d.geometry.PointCloud()  # 使用numpy生成点云
    cloud2.points = o3d.utility.Vector3dVector(b + 1)  # points numpy数组 # 将2维数组的xyz轴都进行+1

    # 连接点
    cloud = cloud2 + cloud1

在这里插入图片描述

后期持续更新。。。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云杂项

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值