找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1686

积分

0

好友

220

主题
发表于 4 天前 | 查看: 15| 回复: 0

在之前的两篇文章中,我们介绍了VoxelGridApproximateVoxelGrid两种体素下采样方法。两者均采用质心近似策略——用体素内所有点的质心替代原始点。但某些场景下,我们需要保留原始点而非计算质心,此时均匀采样滤波器UniformSampling)便是不二之选。

1. 均匀采样

均匀采样滤波器同样基于体素网格实现,其核心原理与VoxelGrid相似——将三维空间划分为大小相等的体素网格。但两者在代表点选择策略上存在本质区别:

特性 VoxelGrid UniformSampling
代表点选择 体素内所有点的质心 距离体素中心最近的原始点
输出点类型 新计算的点(质心) 原始点云中的点
属性保留 需计算属性平均值 直接保留原始属性
计算复杂度 需累加求平均 仅需距离比较
适用场景 需要平滑效果 需保留原始点属性

UniformSampling的核心原理——用距离体素中心最近的原始点替代体素内所有点。算法的执行步骤如下:

  • 网格划分:根据设定的体素尺寸(搜索半径),将点云的包围盒空间划分为三维体素网格;
  • 点云分配:遍历点云中的每个点,根据其坐标计算所属体素索引,将点分配到对应体素中;
  • 代表点选择:对于每个非空体素,计算体素内每个点到体素中心的距离,选择距离最近的点作为代表点
  • 点云输出:输出所有代表点,形成下采样后的点云。

值得注意的是,UniformSampling输出的点是原始点云中的真实点,而非计算得到的新点。这一特性在需要保留原始点属性(如法向量、颜色、强度等)的场景中尤为重要。

2. UniformSampling

pcl::UniformSampling类继承自Filter基类,除基类方法外,仅新增了1个核心方法用于设置体素尺寸。

//设置体素尺寸(搜索半径)
//@param radius 体素尺寸,三个方向使用相同值
void setRadiusSearch(double radius);

VoxelGridsetLeafSize(lx, ly, lz)不同,UniformSampling仅支持各向同性的体素尺寸,即X、Y、Z三个方向使用相同的尺寸值。这一设计简化了参数设置,但也限制了在非均匀采样场景下的灵活性。

UniformSampling不同于VoxelGridstd::vector的实现方式,也不同于ApproximateVoxelGrid的固定尺寸的哈希表实现,它采用了 unordered_map 这种数据结构unordered_map内部其实也是采用哈希表实现。UniformSampling使用体素索引作为哈希键,将点分配到对应体素中。每个体素内仅存储距离体素中心最近的点的索引,而不是所有点的索引。这一设计显著减少了内存占用,同时保持了高效的代表点选择。

3. 参数调整建议

结合算法原理分析该如何调整核心参数,以获得最佳的下采样效果。

  • 体素尺寸(radius):该值决定了下采样的粒度,直接影响输出点云的密度和均匀程度。
    • 值越大,体素越大,下采样程度越高,点数减少越多,但空间分布越均匀;
    • 值越小,体素越小,下采样程度越低,点数保留越多,几何细节保留越好;
    • 一般建议设置为点云平均点间距的3-10倍,根据应用需求在点数与精度间权衡。

我常用的参数调整策略是:

  • 估算点云密度:计算点云包围盒体积,除以点数得到平均体积,再开立方得到平均点间距;
  • 确定初始值:将体素尺寸设为平均点间距的3-5倍作为初始值;
  • 迭代调整
    • 若下采样后点数仍然过多,适当增大体素尺寸;
    • 若几何细节丢失严重,适当减小体素尺寸;
    • 若点云分布不够均匀,检查是否存在密度差异过大的区域,可能需要分区处理。

4. 代码示例

为了更直观地展示UniformSampling的使用方法,整理示例代码如下:

4.1 基本示例:标准均匀采样

#include <pcl/filters/uniform_sampling.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>

int main() {
    // 加载点云数据
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::io::loadPCDFile("input.pcd", *cloud_in);

    // 1. 初始化均匀采样滤波器对象
    pcl::UniformSampling<pcl::PointXYZ> us;
    us.setInputCloud(cloud_in);
    us.setRadiusSearch(0.01);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out(new pcl::PointCloud<pcl::PointXYZ>);
    us.filter(*cloud_out);

    // 保存滤波结果
    pcl::io::savePCDFile("output.pcd", *cloud_out);

    return 0;
}

4.2 高级示例:获取被剔除点的索引

#include <pcl/filters/uniform_sampling.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>

int main() {
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::io::loadPCDFile("input.pcd", *cloud_in);

    // 初始化滤波器,启用被剔除索引提取
    pcl::UniformSampling<pcl::PointXYZ> us(true);  // 参数true表示提取被剔除索引
    us.setInputCloud(cloud_in);
    us.setRadiusSearch(0.01);

    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out(new pcl::PointCloud<pcl::PointXYZ>);
    us.filter(*cloud_out);

    // 获取被剔除点的索引
    std::vector<int> removed_indices;
    us.getRemovedIndices(removed_indices);

    std::cout << "Removed points: " << removed_indices.size() << std::endl;

    pcl::io::savePCDFile("output.pcd", *cloud_out);

    return 0;
}

5. 对比记忆

为了更清晰地理解UniformSampling的特点,将其与VoxelGridApproximateVoxelGrid进行全面对比:

对比维度 VoxelGrid ApproximateVoxelGrid UniformSampling
代表点类型 质心(新计算点) 质心(新计算点) 最近点(原始点)
体素尺寸设置 支持各向异性(lx, ly, lz) 支持各向异性(lx, ly, lz) 仅支持各向同性(radius)
属性处理 可选择平均值或首点值 可选择平均值或首点值 直接保留原始属性
数据结构 std::vector + 排序 固定大小哈希表 std::unordered_map
字段过滤 支持 不支持 不支持
最小点数阈值 支持 不支持 不支持
布局保存 支持 不支持 不支持
平滑效果 有(质心平滑) 有(质心平滑) 无(保留原始点)
计算效率 O(n log n) O(n) 平均 O(n) 平均
内存占用 O(n) 存储所有点索引 O(1) 固定大小缓冲区 O(m) 仅存储代表点索引
结果精度 精确(无冲突) 近似(可能哈希冲突) 精确(无冲突)

5.1 选择建议

  • 选择UniformSampling的场景
    • 需要保留原始点的精确属性(如法向量、颜色、标签等);
    • 后续处理依赖原始点索引(如点云配准、特征匹配);
    • 需要避免质心计算带来的属性模糊;
    • 点云属性不可平均(如分类标签)。
  • 选择VoxelGrid的场景
    • 需要精确的下采样结果;
    • 需要平滑效果以减少噪声影响;
    • 需要各向异性下采样(不同方向不同尺寸);
    • 需要字段过滤或最小点数阈值等高级功能;
    • 点云属性可以合理平均(如RGB颜色)。
  • 选择ApproximateVoxelGrid的场景
    • 追求处理效率且对精度要求不高;
    • 大规模点云处理,需要O(n)时间复杂度
    • 内存受限场景,需要固定内存占用;
    • 实时处理需求(如实时预览、流式处理)。

6. 总结

本文重点介绍了pcl::UniformSampling类的核心原理、主要参数及与VoxelGrid的差异,并提供了从基础到高级的示例代码。均匀采样滤波器的核心特点是保留原始点而非计算质心,这一特性使其在需要精确保留点属性的场景中具有独特优势。合理选择UniformSamplingVoxelGridApproximateVoxelGrid,可以更好地满足不同应用场景的下采样需求。想了解更多关于后端架构与底层算法的深度解析,欢迎关注云栈社区,共同探讨技术细节。




上一篇:MossCode腕部AI:无感采集与深度理解如何重塑运动健康体验
下一篇:Go 高性能时间处理指南:从 time.Now() 到序列化优化
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-23 09:03 , Processed in 0.603787 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表