【PCL】Octree (八叉树) 模块介绍和代码示例

PCL中Octree模块介绍与代码示例

1、Octree模块说明

1.1 概述

Octree(八叉树)是一种树状数据结构,用于在三维空间中对点云数据进行高效的组织和管理。它将空间递归地划分为八个子空间(即八叉树节点),直到每个节点中的点云数据满足特定的条件(如点的数量或空间分辨率)。Octree广泛应用于点云的压缩、搜索、分割、聚类等任务。

1.2 Octree模块的主要功能

PCL中的Octree模块提供了以下主要功能:

  • 点云的压缩与解压缩:通过Octree结构对点云进行压缩存储,减少存储空间。
  • 近邻搜索:快速查找给定点附近的点。
  • 体素搜索:查找位于特定体素(空间立方体)内的点。
  • 空间变化检测:检测两个点云之间的空间变化。
  • 点云的分割与聚类:利用Octree结构对点云进行分割和聚类。

1.3 Octree模块的核心类

  • pcl::octree::OctreePointCloud<PointT, LeafContainerT, BranchContainerT>:这是Octree的核心类,用于管理点云的Octree结构。
    • PointT:点云中点的类型,如pcl::PointXYZ
    • LeafContainerT:叶子节点的容器类型。
    • BranchContainerT:分支节点的容器类型。

2、Octree模块主要功能代码示例


2.1 点云的压缩与解压缩

Octree可以用于压缩点云数据,通过减少点的数量或降低分辨率来节省存储空间。

#include <pcl/point_cloud.h>
#include <pcl/octree/octree_pointcloud_compression.h>
#include <pcl/io/pcd_io.h>
#include <iostream>

int main()
{
    // 创建一个点云对象
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

    // 生成一些随机点云数据
    cloud->width = 1000;
    cloud->height = 1;
    cloud->points.resize(cloud->width * cloud->height);
    for (size_t i = 0; i < cloud->points.size(); ++i)
    {
        cloud->points[i].x = 1024.0f * rand() / (RAND_MAX + 1.0f);
        cloud->points[i].y = 1024.0f * rand() / (RAND_MAX + 1.0f);
        cloud->points[i].z = 1024.0f * rand() / (RAND_MAX + 1.0f);
    }

    // 创建Octree压缩对象
    pcl::io::OctreePointCloudCompression<pcl::PointXYZ> octreeCompression;

    // 压缩点云
    std::stringstream compressedData;
    octreeCompression.encodePointCloud(cloud, compressedData);

    // 解压缩点云
    pcl::PointCloud<pcl::PointXYZ>::Ptr decompressedCloud(new pcl::PointCloud<pcl::PointXYZ>);
    octreeCompression.decodePointCloud(compressedData, decompressedCloud);

    // 输出压缩前后的点云大小
    std::cout << "Original cloud size: " << cloud->points.size() << " points" << std::endl;
    std::cout << "Decompressed cloud size: " << decompressedCloud->points.size() << " points" << std::endl;

    return 0;
}

2.2 近邻搜索

Octree可以快速查找给定点附近的点。

#include <pcl/point_cloud.h>
#include <pcl/octree/octree_search.h>
#include <pcl/io/pcd_io.h>
#include <iostream>
#include <vector>

int main()
{
    // 创建一个点云对象
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

    // 从PCD文件加载点云数据
    if (pcl::io::loadPCDFile<pcl::PointXYZ>("sample.pcd", *cloud) == -1)
    {
        PCL_ERROR("Couldn't read file sample.pcd \n");
        return -1;
    }

    // 创建Octree对象
    float resolution = 0.01f;
    pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> octree(resolution);
    octree.setInputCloud(cloud);
    octree.addPointsFromInputCloud();

    // 定义搜索点
    pcl::PointXYZ searchPoint;
    searchPoint.x = 0.1f;
    searchPoint.y = 0.1f;
    searchPoint.z = 0.1f;

    // 近邻搜索
    int K = 10; // 搜索最近的10个点
    std::vector<int> pointIdxNKNSearch(K);
    std::vector<float> pointNKNSquaredDistance(K);

    if (octree.nearestKSearch(searchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance) > 0)
    {
        std::cout << "Nearest neighbor search results:" << std::endl;
        for (size_t i = 0; i < pointIdxNKNSearch.size(); ++i)
        {
            std::cout << "    " << cloud->points[pointIdxNKNSearch[i]].x
                      << " " << cloud->points[pointIdxNKNSearch[i]].y
                      << " " << cloud->points[pointIdxNKNSearch[i]].z
                      << " (squared distance: " << pointNKNSquaredDistance[i] << ")" << std::endl;
        }
    }

    return 0;
}

2.3 体素搜索

Octree可以查找位于特定体素(空间立方体)内的点。

#include <pcl/point_cloud.h>
#include <pcl/octree/octree_search.h>
#include <pcl/io/pcd_io.h>
#include <iostream>
#include <vector>

int main()
{
    // 创建一个点云对象
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

    // 从PCD文件加载点云数据
    if (pcl::io::loadPCDFile<pcl::PointXYZ>("sample.pcd", *cloud) == -1)
    {
        PCL_ERROR("Couldn't read file sample.pcd \n");
        return -1;
    }

    // 创建Octree对象
    float resolution = 0.01f;
    pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> octree(resolution);
    octree.setInputCloud(cloud);
    octree.addPointsFromInputCloud();

    // 定义搜索点
    pcl::PointXYZ searchPoint;
    searchPoint.x = 0.1f;
    searchPoint.y = 0.1f;
    searchPoint.z = 0.1f;

    // 体素搜索
    std::vector<int> pointIdxVec;
    if (octree.voxelSearch(searchPoint, pointIdxVec))
    {
        std::cout << "Voxel search results:" << std::endl;
        for (size_t i = 0; i < pointIdxVec.size(); ++i)
        {
            std::cout << "    " << cloud->points[pointIdxVec[i]].x
                      << " " << cloud->points[pointIdxVec[i]].y
                      << " " << cloud->points[pointIdxVec[i]].z << std::endl;
        }
    }

    return 0;
}

2.4 空间变化检测

Octree可以检测两个点云之间的空间变化。

#include <pcl/point_cloud.h>
#include <pcl/octree/octree.h>
#include <pcl/io/pcd_io.h>
#include <iostream>

int main()
{
    // 创建两个点云对象
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloudA(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloudB(new pcl::PointCloud<pcl::PointXYZ>);

    // 加载点云数据
    pcl::io::loadPCDFile<pcl::PointXYZ>("cloudA.pcd", *cloudA);
    pcl::io::loadPCDFile<pcl::PointXYZ>("cloudB.pcd", *cloudB);

    // 创建Octree对象
    float resolution = 0.01f;
    pcl::octree::OctreePointCloudChangeDetector<pcl::PointXYZ> octree(resolution);

    // 添加第一个点云
    octree.setInputCloud(cloudA);
    octree.addPointsFromInputCloud();

    // 切换到变化检测模式
    octree.switchBuffers();

    // 添加第二个点云
    octree.setInputCloud(cloudB);
    octree.addPointsFromInputCloud();

    // 获取变化点索引
    std::vector<int> newPointIdxVector;
    octree.getPointIndicesFromNewVoxels(newPointIdxVector);

    // 输出变化点
    std::cout << "Detected changes: " << newPointIdxVector.size() << " points" << std::endl;
    for (size_t i = 0; i < newPointIdxVector.size(); ++i)
    {
        std::cout << "    " << cloudB->points[newPointIdxVector[i]].x
                  << " " << cloudB->points[newPointIdxVector[i]].y
                  << " " << cloudB->points[newPointIdxVector[i]].z << std::endl;
    }

    return 0;
}

2.5 点云的分割与聚类

Octree可以用于点云的分割和聚类。

#include <pcl/point_cloud.h>
#include <pcl/octree/octree.h>
#include <pcl/io/pcd_io.h>
#include <pcl/segmentation/extract_clusters.h>
#include <iostream>

int main()
{
    // 创建一个点云对象
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

    // 从PCD文件加载点云数据
    if (pcl::io::loadPCDFile<pcl::PointXYZ>("sample.pcd", *cloud) == -1)
    {
        PCL_ERROR("Couldn't read file sample.pcd \n");
        return -1;
    }

    // 创建Octree对象
    float resolution = 0.01f;
    pcl::octree::OctreePointCloud<pcl::PointXYZ> octree(resolution);
    octree.setInputCloud(cloud);
    octree.addPointsFromInputCloud();

    // 提取聚类
    std::vector<pcl::PointIndices> clusterIndices;
    pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;
    ec.setClusterTolerance(0.02f); // 设置聚类容差
    ec.setMinClusterSize(100);     // 设置最小聚类点数
    ec.setMaxClusterSize(25000);   // 设置最大聚类点数
    ec.setSearchMethod(octree.getSearchMethod());
    ec.setInputCloud(cloud);
    ec.extract(clusterIndices);

    // 输出聚类结果
    std::cout << "Number of clusters: " << clusterIndices.size() << std::endl;
    for (size_t i = 0; i < clusterIndices.size(); ++i)
    {
        std::cout << "Cluster " << i << " has " << clusterIndices[i].indices.size() << " points" << std::endl;
    }

    return 0;
}

2.6 总结

以上代码示例展示了PCL中Octree模块的五个主要功能:

  1. 点云的压缩与解压缩
  2. 近邻搜索
  3. 体素搜索
  4. 空间变化检测
  5. 点云的分割与聚类

通过这些功能,Octree可以高效地处理点云数据,适用于多种应用场景。

### 使用PCL 1.8.1 实现八叉树压缩 为了利用PCL库中的八叉树方法来实现点云数据的压缩与解压操作,在`usr/include/pcl/compression/compression_profiles.h`文件中定义了一系列用于配置不同压缩级别的参数选项[^1]。具体来说,这些配置项允许开发者指定诸如分辨率、体素大小以及是否启用颜色信息保存等细节。 对于希望基于PCL 1.8.1版本执行此功能的应用程序而言,除了确保正确设置了环境变量(例如将`%PCL_ROOT%`指向安装目录),还需要特别注意编译过程中的依赖关系管理[^2]。当遇到编译错误时,应当仔细检查并调整项目属性里有关外部库链接的部分,特别是确认已指定了正确的`.lib`文件位置及其对应的头文件路径[^4]。 下面给出一段简单的C++代码片段作为示范,展示了怎样创建一个八叉树结构并对给定点集应用该算法: ```cpp #include <pcl/io/pcd_io.h> #include <pcl/octree/octree_pointcloud_compression.h> int main(int argc, char** argv){ pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); // 加载原始PCD文件到内存中 if (pcl::io::loadPCDFile<pcl::PointXYZ>("input.pcd", *cloud) == -1){ PCL_ERROR ("Couldn't read file input.pcd \n"); return (-1); } // 创建octree对象实例化 pcl::octree::OctreePointCloudCompression<pcl::PointXYZ> octree(0.1f); // 设置输入点云数据 octree.setInputCloud(cloud); // 执行编码流程 std::stringstream compressedData; octree.compressPointCloud(compressedData); // 解码恢复原状 pcl::PointCloud<pcl::PointXYZ>::Ptr decompressedCloud(new pcl::PointCloud<pcl::PointXYZ>()); octree.decompressPointCloud(compressedData,*decompressedCloud); // 输出处理后的结果至新文件 pcl::io::savePCDFileASCII("output_decompressed.pcd",*decompressedCloud); return 0; } ``` 这段示例说明了如何加载点云数据、初始化八叉树类的对象、调用成员函数完成压缩动作并将得到的数据流传递回去以便后续解压还原成初始状态。值得注意的是,这里使用的构造器接受浮点型参数表示最大枝叶节点尺寸;实际应用场景下可根据需求灵活设定这一数值以平衡存储效率重建精度之间的权衡。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值