点云下采样2

摘要:
#step3计算每个volex的维度Dx=/size_r+1Dy=/size_r+1Dz=/size_r+1step4计算每个点在volexgrid内每一个维度的值,即计算每个点属于哪个体素,亦即计算每个点的体素的索引。

来源:https://blog.csdn.net/weixin_41281151/article/details/107125844

点云体素降采样(Voxel Filter Downsampling)
代码参考网址秦乐乐CSDN博客
理论参考知乎博主:WALL-E

1.方法
Centroid 均值采样
Random select 随机采样

2.伪代码流程

点云下采样2第1张

注解:

第4步是计算没一个点的体素索引。
3.代码编写
step1 计算边界值

#step1 计算边界点
x_max, y_max, z_max = np.amax(point_cloud,axis=0) #计算 x,y,z三个维度的最值
x_min, y_min, z_min = np.amin(point_cloud, axis=0)

step2 确定体素的尺寸

#step2 确定体素的尺寸
size_r = leaf_size

step3 计算每个 volex的维度,即在每个维度上的体素的个数。

#step3 计算每个 volex的维度
Dx = (x_max - x_min)/size_r +1Dy = (y_max - y_min)/size_r +1Dz = (z_max - z_min)/size_r +1

step4 计算每个点在volex grid内每一个维度的值,即计算每个点属于哪个体素,亦即计算每个点的体素的索引。

#step4 计算每个点在volex grid内每一个维度的值
h =list()
for i inrange(len(point_cloud)):
Dx = (x_max - x_min)/size_r
Dy = (y_max - y_min)/size_r
Dz = (z_max - z_min)/size_r
h.append(hx + hy*Dx + hz*Dx*Dy)

step5 对h值进行排序

h =np.array(h)
h_indice =np.argsort(h) #提取索引
h_sorted = h[h_indice] #升序

将h值相同的点放入到同一个grid中,并进行筛选,并区分random和centroid两种滤波方式

count = 0#用于维度的累计
#将h值相同的点放入到同一个grid中,并进行筛选
for i in range(len(h_sorted)-1): #0-19999个数据点
if h_sorted[i] == h_sorted[i+1]: #当前的点与后面的相同,放在同一个volex grid中
continue
else:
if(filter_mode == "centroid"): #均值滤波
point_idx = h_indice[count: i+1]
filtered_points.append(np.mean(point_cloud[point_idx],axis=0)) #取同一个grid的均值
count =i
elif(filter_mode == "random"): #随机滤波
point_idx = h_indice[count: i+1]
random_points =random.choice(point_cloud[point_idx])
filtered_points.append(random_points)
count = i

调用

# 调用voxel滤波函数,实现滤波
filtered_cloud = voxel_filter(points, 0.05, "random") #centroid or random
point_cloud_o3d_filter.points = o3d.utility.Vector3dVector(filtered_cloud)

效果图

原点云图在open3d中展示如下

random随机降采样效果如下

centroid随机降采样效果如下

整体对比

完整代码
注意:数据集放在相应运行的目录下

# 实现voxel滤波,并加载数据集中的文件进行验证

import open3d aso3d
import os
import numpy asnp
frompyntcloud import PyntCloud
import matplotlib.pyplot asplt
import random
frompandas import DataFrame

# matplotlib显示点云函数
def Point_Cloud_Show(points):
fig = plt.figure(dpi=150)
ax = fig.add_subplot(111, projection='3d')
ax.scatter(points[:, 0], points[:, 1], points[:, 2], cmap='spectral', s=2, linewidths=0, alpha=1, marker=".")
plt.title('Point Cloud')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
plt.show()

# 二维点云显示函数
def Point_Show(pca_point_cloud):
x =[]
y =[]
pca_point_cloud =np.asarray(pca_point_cloud)
for i in range(10000):
x.append(pca_point_cloud[i][0])
y.append(pca_point_cloud[i][1])
plt.scatter(x, y)
plt.show()

 

# 功能:对点云进行voxel滤波
# 输入:
# point_cloud:输入点云
# leaf_size: voxel尺寸
def voxel_filter(point_cloud, leaf_size,filter_mode):
filtered_points =[]
# 作业3
# 屏蔽开始
#step1 计算边界点
x_max, y_max, z_max = np.amax(point_cloud,axis=0) #计算 x,y,z三个维度的最值
x_min, y_min, z_min = np.amin(point_cloud, axis=0)
#step2 确定体素的尺寸
size_r =leaf_size
#step3 计算每个 volex的维度
Dx = (x_max - x_min)/size_r
Dy = (y_max - y_min)/size_r
Dz = (z_max - z_min)/size_r
#step4 计算每个点在volex grid内每一个维度的值
h =list()
for i inrange(len(point_cloud)):
hx = np.floor((point_cloud[i][0] - x_min)/size_r)
hy = np.floor((point_cloud[i][1] - y_min)/size_r)
hz = np.floor((point_cloud[i][2] - z_min)/size_r)
h.append(hx + hy*Dx + hz*Dx*Dy)
#step5 对h值进行排序
h =np.array(h)
h_indice =np.argsort(h) #提取索引
h_sorted =h[h_indice] #升序
count = 0#用于维度的累计
#将h值相同的点放入到同一个grid中,并进行筛选
for i in range(len(h_sorted)-1): #0-19999个数据点
if h_sorted[i] == h_sorted[i+1]: #当前的点与后面的相同,放在同一个volex grid中
continue
else:
if(filter_mode == "centroid"): #均值滤波
point_idx = h_indice[count: i+1]
filtered_points.append(np.mean(point_cloud[point_idx],axis=0)) #取同一个grid的均值
count =i
elif(filter_mode == "random"): #随机滤波
point_idx = h_indice[count: i+1]
random_points =random.choice(point_cloud[point_idx])
filtered_points.append(random_points)
count =i

# 屏蔽结束

# 把点云格式改成array,并对外返回
filtered_points = np.array(filtered_points, dtype=np.float64)
returnfiltered_points

def main():
# # 从ModelNet数据集文件夹中自动索引路径,加载点云
# cat_index = 10 # 物体编号,范围是0-39,即对应数据集中40个物体
# root_dir = '/Users/renqian/cloud_lesson/ModelNet40/ply_data_points'# 数据集路径
# cat =os.listdir(root_dir)
# filename = os.path.join(root_dir, cat[cat_index],'train', cat[cat_index]+'_0001.ply') # 默认使用第一个点云
# point_cloud_pynt =PyntCloud.from_file(file_name)

# 加载自己的点云文件
point_cloud_raw = np.genfromtxt(r"person_0001.txt", delimiter=",")
point_cloud_raw = DataFrame(point_cloud_raw[:,0:3]) # 为 xyz的 N*3矩阵
point_cloud_raw.columns = ['x', 'y', 'z'] # 给选取到的数据 附上标题
point_cloud_pynt =PyntCloud(point_cloud_raw) # 将points的数据 存到结构体中

point_cloud_o3d_orign = point_cloud_pynt.to_instance("open3d", mesh=False) # to_instance实例化
point_cloud_o3d_filter =o3d.geometry.PointCloud() #实例化

# o3d.visualization.draw_geometries([point_cloud_o3d]) # 显示原始点云

points =np.array(point_cloud_o3d_orign.points)

# 调用voxel滤波函数,实现滤波
filtered_cloud = voxel_filter(points, 0.05, "centroid") #centroid or random
point_cloud_o3d_filter.points =o3d.utility.Vector3dVector(filtered_cloud)
# 显示滤波前后的点云
o3d.visualization.draw_geometries([point_cloud_o3d_orign])
o3d.visualization.draw_geometries([point_cloud_o3d_filter])
if __name__ == '__main__':
main()

免责声明:文章转载自《点云下采样2》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇格式化hdfsLINQ中的Lambda表达式下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

numpy随机索引(不重复)和打乱元素

def getRandomIndex(n, x): # 索引范围为[0, n),随机选x个不重复,注意replace=False才是不重复,replace=True则有可能重复 index = np.random.choice(np.arange(n), size=x, replace=False) return index getRa...

C++ 之 伪随机数生成 <random>

C++ 标准库提供了生成随机和伪随机数的类。这些类包括: 随机数生成类:生成均匀分布整数序列的伪随机数生成器,包括随机数引擎、随机数引擎适配器以及预定义随机数生成器。 随机数分布类:将生成器生成的数字序列转换为遵循特定随机变量分布(如均匀分布、正态或泊松分布)的数字序列的对象。 随机数引擎 随机数引擎可以以种子数据为熵源生成伪随机数。 随机种子:初始化...

Java中生成随机数的4种方式!

在 Java 中,生成随机数的场景有很多,所以本文我们就来盘点一下 4 种生成随机数的方式,以及它们之间的区别和每种生成方式所对应的场景。 1.Random Random 类诞生于 JDK 1.0,它产生的随机数是伪随机数,也就是有规则的随机数。Random 使用的随机算法为 linear congruential pseudorandom number...

C# 中实现随机时间的获取

原理其实非常简单,取出两个时间差的秒数,再在0到该秒数之间随机获取一个整数,将其做为秒添加到较小的时间上,可以说实现上并没什么技术难点,可以在数据类型的边界条件上却需要格外的注意,比如将大于 System.Int32.MaxValue 或小于 System.Int32.MinValue 的值转成 int 时,如果直接在变量前加上类型名转换((int)d),...

如何查看Python内置模块的实现代码

方法1:使用help(random) >>> import random >>> help(random) Help on module random: NAME random - Random variable generators. FILE c:python27lib andom.py     ...

如何在ROS中使用PCL—数据格式(1)

在ROS中点云的数据类型 在ROS中表示点云的数据结构有: sensor_msgs::PointCloud      sensor_msgs::PointCloud2     pcl::PointCloud<T> 关于PCL在ros的数据的结构,具体的介绍可查 看            wiki.ros.org/pcl/Overview 关于s...