3 PCL-octree

3.1  区别

kdtree只有k近领域搜索和半径搜索

octree可以体素内近邻搜索、k近领域搜索和半径搜索

3.2  定义

八叉树结构通过对三维空间的几何实体进行体元剖分,每个体元具有相同的时间和空间复杂度,通过循环递归的划分方法对大小为 (2n∗2n∗2n)的三维空间的几何对象进行剖分,从而构成一个具有根节点的方向图。在八叉树结构中如果被划分的体元具有相同的属性,则该体元构成一个叶节点;否则继续对该体元剖分成8个子立方体,依次递剖分,对于 (2n∗2n∗2n)大小的空间对象,最多剖分 n次,如下图所示。

3.3  代码

#include <pcl/point_cloud.h>
#include <pcl/octree/octree_search.h>

#include <iostream>
#include <vector>
#include <ctime>
using namespace pcl;
using namespace std;

int main(int argc, char** argv)
{
    srand((unsigned int)time(NULL));

    PointCloud<PointXYZ>::Ptr cloud(new PointCloud<PointXYZ>);//cloud指针

    // 创建点云数据,随机构造点云
    cloud->width = 1000;
    cloud->height = 1;
    cloud->points.resize(cloud->width * cloud->height);
    for (std::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);
    }

    // 创建八叉树流程
    float resolution = 128.0f;
// 分辨率,最小体素尺寸,不再单独往下分了:可以看作是八叉树的深度受分辨率和空间维度的影响

    octree::OctreePointCloudSearch<pcl::PointXYZ> octree(resolution); // 设置分辨率初始化
    // 设置输入点云
    octree.setInputCloud(cloud);
    // 定义Octree边界框(可选操作)
    //计算输入点云的边界框
   // octree.defineBoundingBox();
    //手动定义点云的边界框
    //octree.defineBoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
    // 输入点云添加到Octree,执行构建八叉树,上面只是把点云输进去,没实际执行
    octree.addPointsFromInputCloud();

    // 创建一个随机点
    PointXYZ searchPoint;
    searchPoint.x = 1024.0f * rand() / (RAND_MAX + 1.0f);
    searchPoint.y = 1024.0f * rand() / (RAND_MAX + 1.0f);
    searchPoint.z = 1024.0f * rand() / (RAND_MAX + 1.0f);

    // Neighbors within voxel search
    std::vector<int> pointIdxVec;// 存储索引,存储索引,对cloud点云的索引

    // 体素近邻搜索:把和查询点在同一体素中的点的索引返回
    if (octree.voxelSearch(searchPoint, pointIdxVec))
    {
        std::cout << "Neighbors within voxel search at (" << searchPoint.x
            << " " << searchPoint.y
            << " " << searchPoint.z << ")"
            << std::endl;

        for (std::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;
    }

    // K nearest neighbor search
    // k近邻搜索
    int K = 10;

    std::vector<int> pointIdxNKNSearch; // 搜索结果的索引
    std::vector<float> pointNKNSquaredDistance;// 对应的距离值

    std::cout << "K nearest neighbor search at (" << searchPoint.x
        << " " << searchPoint.y
        << " " << searchPoint.z
        << ") with K=" << K << std::endl;

    if (octree.nearestKSearch(searchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance) > 0)
    {
        for (std::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;
    }

    // Neighbors within radius search
    // 半径近邻搜索
    std::vector<int> pointIdxRadiusSearch;// 搜索结果的索引
    std::vector<float> pointRadiusSquaredDistance;// 对应的距离

    float radius = 256.0f * rand() / (RAND_MAX + 1.0f);

    std::cout << "Neighbors within radius search at (" << searchPoint.x
        << " " << searchPoint.y
        << " " << searchPoint.z
        << ") with radius=" << radius << std::endl;


    if (octree.radiusSearch(searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance) > 0)
    {
        for (std::size_t i = 0; i < pointIdxRadiusSearch.size(); ++i)
            std::cout << "    " << cloud->points[pointIdxRadiusSearch[i]].x
            << " " << cloud->points[pointIdxRadiusSearch[i]].y
            << " " << cloud->points[pointIdxRadiusSearch[i]].z
            << " (squared distance: " << pointRadiusSquaredDistance[i] << ")" << std::endl;
    }
    // 删除八叉树,释放内存
    octree.deleteTree();
}

3.4  结果

索引的结果是128分辨率时的(565.625  88.8125  342.062)这个点作为一个小体素块时里面包含的另外535.。。。和515.。。。的两个点在它体内

3.5  注意

如果需要高效内存管理,空间检测,需要使用八叉树双缓冲技术实现(Octree2BufBase类),该类可以同时保存两个类似的八叉树对象

3.6  八叉树的五种类型

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值