【点云抽稀】一种基于均匀分布随机数的点云抽稀算法

文章介绍了针对大数据点云存储中的空间分区问题,提出了一种基于随机数的抽稀算法。由于点云数据量大,无法全部加载到内存,常规抽稀方法效率低。该算法利用伪随机数的均匀分布,根据LAS文件的逐点读取特性,实现了一次读取即可得到抽稀结果的高效方法。算法局限性包括内存占用和随机数生成效率的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 背景

在大数据点云的存储中,常常要进行空间分区,一般的策略是构建四叉树或者八叉树。在构建树的过程中,一个不可避免的点就是点云的快速抽稀。

不同层级之间,下一层的数据永远比上一层的数据更加精细,即:上一层数据是从下一层通过某种抽稀算法筛选出来的。常规意义上的抽稀算法,是在内存中进行筛选,但由于大数据点云的特殊性(无法全部读进内存),这些抽稀算法均不满足要求,存在一下问题:

  1. 无法全部读进内存,因此抽稀之后不同分块(分块策略是前提)的效果不一;
  2. 抽稀效率比较低,需要预先将数据读进内存,再进行分层筛选;

某项目中,需要将*.las转换成自定义格式,其转换速率要求很高。而由于las文件在使用LASTools读写时,只能逐点读取,因此需要一种既能解决上述问题,又能保证效率的抽稀算法。

本文介绍的抽稀算法,原理上是利用伪随机数的均匀分布来实现,但同时能兼顾效率和效果。其局限性如下:

  1. 随机数表是存储在内存中,因此数据量过大的情况下,内存占用可能会很高;
  2. 抽稀效率随C++标准库的随机数生成算法影响;
  3. 数据量很小的时候,存在某层数据为空的可能;

2. 原理

基于以下出发点:

  1. 每读一个点,能立即得到该点所属层级——las的逐点读限制;
  2. las文件只需读一次,就能得到抽稀结果——O(n),n为点数;
  3. 保证抽稀结果均匀——加入随机数;

对于第一点,将las文件中的顶点数据,类比成一个存储了顶点的数组:

vvvvvvvvvvvvvvvv

LASTools的读操作器每一次读取的时候,都会将游标移到下一个点。对每一个点来说,本身并没有层级信息,因此需要人为地赋予其层级。

计算层级可以类比分类游戏:一堆小球从入口进入,中间穿插阻碍棒,最终落到容器内:
分类游戏
而将红色小球理解为点云的顶点,将下面的容器理解为结果,则中间的蓝色小球是我们的抽稀算法。

核心原理就是,每次获取一个随机数,这个随机数的值就是当前点所在的层级。而随机数的范围,就是按照n叉树的层级点数比例,计算出来的一个值。具体实现见后文。

3. 实现

3.1 定义Utils类

class Utils
{
private:
    Utils(int lvl);
    ~Utils();

public:
    static Utils &instance();
    int getLayer();

protected:
    char *m_lvl;
    int m_l;
};

3.2 加入预定义宏,确定层级

#ifndef DEFAULT_LEVEL_COUNT
#define DEFAULT_LEVEL_COUNT 7
#endif

3.3 函数实现

const std::size_t g_num[10] = {
    1, 4, 16, 64, 256, 1024, 4096, 16384, 65536, 262144};
const std::size_t g_sum[10] = {
    1,
    1 + 4,
    1 + 4 + 16,
    1 + 4 + 16 + 64,
    1 + 4 + 16 + 64 + 256,
    1 + 4 + 16 + 64 + 256 + 1024,
    1 + 4 + 16 + 64 + 256 + 1024 + 4096,
    1 + 4 + 16 + 64 + 256 + 1024 + 4096 + 16384,
    1 + 4 + 16 + 64 + 256 + 1024 + 4096 + 16384 + 65536,
    1 + 4 + 16 + 64 + 256 + 1024 + 4096 + 16384 + 65536 + 262144,
};

Utils::Utils(int lvl)
{
    m_lvl = new char[g_sum[lvl - 1]];

    std::size_t idx = 0;
    for (int i = 0; i < lvl; ++i)
    {
        std::size_t tms = g_num[i];
        // for (int j = 0; j < tms; ++j)
        // {
        //     m_lvl[idx + j] = (char)i;
        // }
        std::fill_n(m_lvl + idx, tms, (char)i);
        idx += tms;
    }
    m_l = lvl;
}

Utils::~Utils()
{
    delete[] m_lvl;
}

Utils &Utils::instance()
{
    static Utils s_ret(DEFAULT_LEVEL_COUNT);
    return s_ret;
}

int Utils::getLayer()
{
    static std::default_random_engine s_dre;
    static std::uniform_int_distribution<unsigned long> s_uid(g_sum[0], g_sum[m_l - 1]);

    return (int)(m_lvl[s_uid(s_dre)]);
}
### 回答1: 生成一组pts格式的点云的步骤如下: 1. 导入所需库:numpy和os。 ```python import numpy as np import os ``` 2. 定义点云的数量和每个点的坐标数。 ```python num_points = 1000 num_dimensions = 3 ``` 3. 生成点云的坐标数据。 ```python point_cloud_data = np.random.rand(num_points, num_dimensions) ``` 4. 将点云数据保存为pts格式文件。 ```python file_path = 'point_cloud.pts' with open(file_path, 'w') as f: for point in point_cloud_data: line = ' '.join([str(x) for x in point]) f.write(line + '\n') ``` 完整代码如下: ```python import numpy as np import os num_points = 1000 num_dimensions = 3 point_cloud_data = np.random.rand(num_points, num_dimensions) file_path = 'point_cloud.pts' with open(file_path, 'w') as f: for point in point_cloud_data: line = ' '.join([str(x) for x in point]) f.write(line + '\n') ``` 运行该代码后,将在当前目录下生成名为point_cloud.pts的点云文件。 ### 回答2: 生成一组pts格式的点云可以通过以下步骤进行。 1. 首先,确定需要生成的点云的数量和密度。可以根据具体应用场景和需求来确定生成的点云类型和参数。 2. 然后,确定点云的坐标系。pts格式的点云通常采用笛卡尔坐标系,其中点的坐标由x、y和z值表示。可以根据实际需要选择合适的坐标系。 3. 接下来,确定点云中每个点的属性。一个点的属性可以包括坐标、颜色、法向量等。根据应用需求,可以选择添加或忽略某些属性。例如,在生成地形点云时可以只包括坐标信息,但在生成建筑物点云时可以同时包括坐标和颜色信息。 4. 然后,使用合适的算法生成点云。根据具体应用和需求,可以选择不同的算法来生成点云,例如均匀分布算法、高斯分布算法或其他形状生成算法。这些算法可以生成合适数量和分布的点。 5. 最后,将生成的点云保存为pts格式。pts格式通常以文本文件形式保存,每个点的属性值在一行中按顺序排列。可以根据需要选择合适的分隔符。 ### 回答3: 生成一组pts格式的点云可以通过以下步骤完成。 首先,我们需要确定点云的坐标系和尺度单位。一般情况下,点云的坐标系可以选择笛卡尔坐标系。尺度单位可以根据实际应用选择,例如米或毫米。 接下来,我们可以选择使用编程语言(如Python)和相关库(如numpy)来生成点云数据。我们可以定义一个空的点云对象,并为其添加每个点的坐标信息。 首先,我们可以定义点云的点数(假设为n)和维度(假设为3维)。然后,我们可以使用循环来生成每个点的坐标。可以通过随机数生成器或具体的坐标计算公式来确定每个点的坐标值。生成的点坐标可以存储在一个numpy数组中。 完成点坐标的生成后,我们可以将点坐标存储为pts格式的文件。pts格式文件是一种常见的点云数据存储格式,它可以包含点坐标、RGB颜色信息等。我们可以遍历每个点的坐标,并按照pts格式规定的格式将数据写入文件。 在写入文件之后,我们可以进行点云的可视化,用于检查生成的点云是否符合预期。可以使用可视化工具和库(如open3d)加载和显示生成的pts格式点云文件。 需要注意的是,生成点云前需要确定点云的生成规则和要达到的目标,这样才能更好地控制生成的点云的质量和特性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

geocat

球球大佬们赏赐点吃喝!

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

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

打赏作者

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

抵扣说明:

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

余额充值