用于抽取地形点点云的算法或命令行工具?

时间:2017-04-08 17:03:21

标签: algorithm point-cloud-library point-clouds lidar

我需要为地形定义采用比需要的激光雷达测量点(经度,纬度和高程)更大(更密集)的列表,并根据二维网格对其进行抽取。我们的想法是使用经度,纬度(x,y)值基于NxN(即1米x 1米)尺寸网格结束点,因此消除了超过所需的点数。目标是确定抽取后网格中每个点的高程,而不是使用高程作为抽取规则本身的一部分。

实际或精确结构化的网格不是必需的,也不是这里的目标,我只使用网格术语来最好地逼近我想象的点云的剩余部分,然后以我们一直有点的方式减少它在一定半径内(即1米)。有可能使用比网格更好的术语。

如果我可以从抽象算法开始,或者使用可能已经存在的可以在Ubuntu上运行的项目的命令行工具,我想用脚本或编程语言自己编写/编写脚本。从我们的应用程序调用为系统调用。该方法不应要求使用基于GUI的软件或工具来解决此问题。它需要成为一系列自动步骤的一部分。

数据当前存在于制表符分隔值文件中,但是如果使用数据库/ sql查询驱动算法会更好/更快,我可以将数据加载到sqlite数据库文件中。理想的脚本语言是ruby或python,但可以是任何真正的,如果已经存在C / C ++ / C#库,那么我们可以根据需要包装它们。

想法?

更新 澄清使用此抽取列表的结果:给定用户的位置(以纬度和经度表示),列表中最近的点是什么,反过来又是它的高程?我们当然可以做到这一点,但是我们有更多的数据,所以我们只想放松数据的密度,这样如果我们能够找到公差距离内的最近点(即1米),如果能够使用抽取列表与完整列表。列表中的纬度,经度值采用十进制GPS(即38.68616190027656,-121.11013105991036)

2 个答案:

答案 0 :(得分:1)

第1部分:抽取版本

  • 加载数据

从表格文件加载数据(根据您使用的分隔符更改sep):

# installed as dependency
import pandas as pd  
# https://github.com/daavoo/pyntcloud
from pyntcloud import PyntCloud  

dense = PyntCloud(pd.read_csv("example.tsv",
                     sep='\t',
                     names=["x","y","z"]))

这就是我创建的示例:

example

  • 构建VoxelGrid

假设文件中的纬度和经度以米为单位,您可以按如下方式生成网格:

grid_id = dense.add_structure("voxelgrid",
                           sizes=[1, 1,None],
                           bb_cuboid=False)
voxelgrid = dense.voxelgrids[grid_id]

此voxelgrid在x(纬度)和y(经度)尺寸上的大小为1。

  • 构建抽取版

    decimated = dense.get_sample(" voxelgrid_centroids",voxelgrid = grid_id)

decimated是一个numpy(N,3)数组。您可以将其存储以供以后在SQL数据库等中使用。

第2部分:查询

选项A:查询voxelgrid

  • 获取每个网格单元的平均高度

您可以知道为网格中的每个单元格获取具有平均z(海拔)值的向量:

z_mean = voxelgrid.get_feature_vector(mode="z_mean")
  • 使用用户的位置查询网格:

    users_location = np.random.rand(100000,2)

添加一列零,因为查询需要3D(这不会影响结果):

users_location = np.c_[ users_location, np.zeros(users_location.shape[0]) ]

每个用户都进入小区:

users_cell = voxelgrid.query(users_location)

最后,获得与每个用户相对应的高度:

users_altitude = z_mean[users_cell]

选项B:使用抽取版本进行查询

  • 构建一个被抽取的KDTree:

    来自scipy.spatial import cKDTree kdt = cKDTree(抽取)

  • 使用用户位置查询KDTree:

    users_location = np.random.rand(100000,2) users_location = np.c_ [users_location,np.zeros(users_location.shape [0])

    距离,指数= kdt.query(user_locations,k = 1,n_jobs = -1)

额外的,你可以用泡菜保存和填充体素网:

pickle.dump(voxelgrid, open("voxelgrid.pkl", "wb"))

voxelgrid = pickle.load(open("voxelgrid.pkl", "rb"))

答案 1 :(得分:0)

如果您有一个文本文件 (.xyz) 形式的点云,一个简单而快速的解决方案是使用 shuf 从文件中随机抽取样本。

xyz 文件中的 1000 万个点等于 1000 万行文本。你可以运行:

shuf input.xyz -l 5000000 -o out.xyz

您已将文件缩小为原始大小的一半。