pcl基于八叉树进行空间划分和搜索操作

        建立空间索引在点云数据处理中已被广泛应用,常见空间索引一般是自顶向下逐级划分空间的各种空间索引结构,比较有代表性的包括 BSP 树、KD 树、KDB 树、 R树、R+树、CELL 树、四叉树和八叉树等索引结构,而在这些结构中 KD 树和八叉树在 3D点云数据排列中应用较为广泛。 PCL 对八叉树的数据结构建立和索引方法进行了实现,以方便在此基础上对点云进行处理操作 。

         八叉树(Octree)的定义是:若不为空树的话,树中任一节点的子节点恰好只会有八个,或零个,也就是子节点不会有0与8以外的数目。那么,这要用来做什么?想象一个立方体,我们最少可以切成多少个相同等分的小立方体?答案就是8个。再想象我们有一个房间,房间里某个角落藏着一枚金币,我们想很快的把金币找出来,聪明的你会怎么做?我们可以把房间当成一个立方体,先切成八个小立方体,然后排除掉没有放任何东西的小立方体,再把有可能藏金币的小立方体继续切八等份….如此下去,平均在log_{8} (n)(n表示房间内的所有物体数)的时间内就可找到金币。因此,八叉树就是用在3D空间中的场景管理,可以很快地知道物体在3D场景中的位置,或侦测与其它物体是否有碰撞以及是否在可视范围内。

这里引入了一个概念:Voxel翻译为体积元素,简称体素。描述了一个预设的最小单位的正方体

        pcl的octree库提供了从点云数据创建具有层次的数据结构的方法。这样就可以对点数据集进行空间分区,下采样和搜索操作。每个八叉树节点有八个子节点或没有子节点。根节点描述了一个包围所有点的3维包容盒子。
        pcl_octree实现提供了有效的最近邻居搜索(邻域搜索)API,例如“ 体素(Voxel)邻居搜索”,“ K最近邻居搜索”和“半径搜索邻居”。叶子节点类也提供其他功能,例如空间“占用率”和“每个体素(Voxel)的点密度”检查;序列化和反序列化功能可将八叉树结构有效地编码为二进制格式;此外,内存池实现减少了昂贵的内存分配和释放操作,以便快速创建八叉树。
        下图说明了最低树级别的八叉树节点的体素边界框。八叉树体素围绕着兔子表面的每个3D点。红点代表点数据。该图像是使用octree_viewer创建的(visualization/tools/octree_viewer

方式二:K 近邻搜索

        本例中K被设置成10, K 近邻搜索(K nearest neighbor search)方法把搜索结果写到两个分开的向量中, 第一个pointIdxNKNSearch 包含搜索结果〈结果点的索引的向量〉, 第二个pointNKNSquaredDistance 保存相应的搜索点和近邻之间的距离平方。 

#include <iostream>
#include <vector>
#include <ctime>
#include <pcl/point_cloud.h>
#include <pcl/octree/octree_search.h>
#include <pcl/visualization/cloud_viewer.h>int main(int argc, char** argv) {srand((unsigned int)time(NULL));pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);// Generate pointcloud datacloud->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);}float resolution = 128.0f;  // 设置分辨率为128// resolution该参数描述了octree叶子leaf节点的最小体素尺寸。pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> octree(resolution);octree.setInputCloud(cloud);  // 设置输入点云octree.addPointsFromInputCloud();  // 通过点云构建octreepcl::PointCloud<pcl::PointXYZ>::Ptr searchCloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::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);searchCloud->push_back(searchPoint);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 (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;}pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> originColorHandler(cloud, 255, 255, 255);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> searchColorHandler(searchCloud, 0, 255, 0);pcl::visualization::PCLVisualizer viewer("PCL Viewer");viewer.setBackgroundColor(0.1176, 0.1176, 0.2353);viewer.addPointCloud<pcl::PointXYZ>(cloud, originColorHandler, "cloud");viewer.addPointCloud<pcl::PointXYZ>(searchCloud, searchColorHandler, "search_cloud");viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "search_cloud");pcl::PointXYZ originPoint(0.0, 0.0, 0.0);viewer.addLine(originPoint, searchPoint, "line");  // 添加从原点到搜索点的线段viewer.setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 1, 0.2784, "line");viewer.addCoordinateSystem(200); // 指定坐标轴的长度,单位mmwhile (!viewer.wasStopped()) {viewer.spinOnce();}return 0;
}

 

octree.nearestKSearch(searchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance)

 pcl::octree::OctreePointCloudSearch<pcl::PointXYZ>::nearestKSearch()方法返回一个整数值,表示搜索操作是否成功并且找到了足够的最近邻点。如果搜索成功并且找到了至少K个最近邻点,则返回实际找到的最近邻点数量;否则,返回0。

该方法将给定的搜索点作为参数,并在八叉树中搜索最近的K个邻近点。找到的最近邻点的索引将存储在pointIdxNKNSearch向量中,而对应的欧氏距离平方将存储在pointNKNSquaredDistance向量中。


方式一:“体素近邻搜索”

        体素近邻搜索(Neighbors within voxel search):它把查询点所在的体素中其他点的索引作为查询结果返回,结果以点索引向量的形式保存,因此搜索点和搜索结果之间的距离取决于八叉树的分辨率参数。

#include <iostream>
#include <vector>
#include <ctime>
#include <pcl/point_cloud.h>
#include <pcl/octree/octree_search.h>
#include <pcl/visualization/cloud_viewer.h>int main(int argc, char** argv) {srand((unsigned int)time(NULL));pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);// Generate pointcloud datacloud->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);}float resolution = 128.0f;  // 设置分辨率为128// resolution该参数描述了octree叶子leaf节点的最小体素尺寸。pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> octree(resolution);octree.setInputCloud(cloud);  // 设置输入点云octree.addPointsFromInputCloud();  // 通过点云构建octreepcl::PointCloud<pcl::PointXYZ>::Ptr searchCloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::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);searchCloud->push_back(searchPoint);std::vector<int> pointIdxVec;if (octree.voxelSearch(searchPoint, pointIdxVec)) {std::cout << "Neighbors within voxel search at (" << searchPoint.x<< " " << searchPoint.y<< " " << searchPoint.z << ")"<< 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;}pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> originColorHandler(cloud, 255, 255, 255);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> searchColorHandler(searchCloud, 0, 255, 0);pcl::visualization::PCLVisualizer viewer("PCL Viewer");viewer.setBackgroundColor(0.1176, 0.1176, 0.2353);viewer.addPointCloud<pcl::PointXYZ>(cloud, originColorHandler, "cloud");viewer.addPointCloud<pcl::PointXYZ>(searchCloud, searchColorHandler, "search_cloud");viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "search_cloud");pcl::PointXYZ originPoint(0.0, 0.0, 0.0);viewer.addLine(originPoint, searchPoint, "line");  // 添加从原点到搜索点的线段viewer.setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 1, 0.2784, "line");viewer.addCoordinateSystem(200); // 指定坐标轴的长度,单位mmwhile (!viewer.wasStopped()) {viewer.spinOnce();}return 0;
}

 

octree.voxelSearch(searchPoint, pointIdxVec)

 ​​​​​​​pcl::octree::OctreePointCloudSearch<pcl::PointXYZ>::voxelSearch()方法返回一个bool类型的值,表示搜索操作是否成功。如果搜索成功并且找到了匹配的体素,则返回true;否则,返回false

该方法将给定的搜索点作为参数,并在八叉树中搜索包含该点的体素。如果找到匹配的体素,则会将体素内的点索引存储在pointIdxVec向量中,并返回true。如果没有找到匹配的体素,则pointIdxVec向量将为空,并返回false


 方式三:半径内近邻搜索

         半径内近邻搜索(Neighbors within radius search)原理和“K 近邻搜索”类似,它的搜索结果被写入两个分开的向量中, 这两个向量分别存储结果点的索引和对应的距离平方

#include <iostream>
#include <vector>
#include <ctime>
#include <pcl/point_cloud.h>
#include <pcl/octree/octree_search.h>
#include <pcl/visualization/cloud_viewer.h>int main(int argc, char** argv) {srand((unsigned int)time(NULL));pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);// Generate pointcloud datacloud->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);}float resolution = 128.0f;  // 设置分辨率为128// resolution该参数描述了octree叶子leaf节点的最小体素尺寸。pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> octree(resolution);octree.setInputCloud(cloud);  // 设置输入点云octree.addPointsFromInputCloud();  // 通过点云构建octreepcl::PointCloud<pcl::PointXYZ>::Ptr searchCloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::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);searchCloud->push_back(searchPoint);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 (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;}pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> originColorHandler(cloud, 255, 255, 255);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> searchColorHandler(searchCloud, 0, 255, 0);pcl::visualization::PCLVisualizer viewer("PCL Viewer");viewer.setBackgroundColor(0.1176, 0.1176, 0.2353);viewer.addPointCloud<pcl::PointXYZ>(cloud, originColorHandler, "cloud");viewer.addPointCloud<pcl::PointXYZ>(searchCloud, searchColorHandler, "search_cloud");viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "search_cloud");pcl::PointXYZ originPoint(0.0, 0.0, 0.0);viewer.addLine(originPoint, searchPoint, "line");  // 添加从原点到搜索点的线段viewer.setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 1, 0.2784, "line");viewer.addCoordinateSystem(200); // 指定坐标轴的长度,单位mmwhile (!viewer.wasStopped()) {viewer.spinOnce();}return 0;
}

 

octree.radiusSearch(searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance)

​​​​​​​pcl::octree::OctreePointCloudSearch<pcl::PointXYZ>::radiusSearch()​​​​​​​方法是用于在八叉树中执行半径搜索的函数。它根据给定的搜索点和半径,在八叉树中找到落在指定半径范围内的所有点。

以下是该方法的参数说明:

  1. searchPoint:要进行半径搜索的点,类型为pcl::PointXYZ。即你希望以这个点为中心进行半径搜索。
  2. radius:指定的搜索半径,类型为double。它定义了从搜索点出发的球体的半径,只有落在该球体内的点才会被搜索到。
  3. pointIdxRadiusSearch:存储在搜索半径范围内的点的索引的向量,类型为std::vector<int>
  4. pointRadiusSquaredDistance:存储在搜索半径范围内的点与搜索点之间的欧氏距离平方的向量,类型为std::vector<float>

使用radiusSearch()方法时,传递一个搜索点和半径作为输入参数,并提供两个向量作为输出参数。方法将填充pointIdxRadiusSearch向量以保存搜索半径范围内的点的索引,同时填充pointRadiusSquaredDistance向量以保存每个点与搜索点之间的欧氏距离平方。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/2126.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多元分类预测 | Matlab灰狼算法(GWO)优化混合核极限学习机(HKELM)分类预测,多特征输入模型,GWO-HKELM分类预测

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元分类预测 | Matlab灰狼算法(GWO)优化混合核极限学习机(HKELM)分类预测,多特征输入模型,GWO-HKELM分类预测 多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就可以用。程序语言为matlab…

【redis】redis集群

这里是redis系列文章之《redis集群》&#xff0c;上一篇文章链接&#xff1a;【redis基础】哨兵_努力努力再努力mlx的博客-CSDN博客 目录 概念 作用 集群算法-分片-槽位slot 槽位与分配的概念及两者的优势 官网介绍分析 槽位 分片 两者的优势 slot槽位映射的三种解决方…

mac 安装 aab android包

一、配置bundletool环境 1、下载最新版的bundletool 版本号要最新的 bundletool-all-1.15.1.jarhttps://github.com/google/bundletool/releases/download/1.15.1/bundletool-all-1.15.1.jar Releases google/bundletool GitHub​​​​​​​​​​ 2、把bundletool放在…

2-css-2

一 复合选择器 定义&#xff1a;由两个或多个基础选择器&#xff0c;通过不同的方式组合而成。 作用&#xff1a;更准确、更高效的选择目标元素&#xff08;标签&#xff09;。 1 后代选择器 后代选择器&#xff1a;选中某元素的后代元素。 选择器写法&#xff1a;父选择器…

个人git笔记,持续学习并补充填写

git --version //查看git版本信息 sudo yum remove git -y //卸载gitsudo yum install git -y//安装git 该文章仅仅是为了方便个人日常观看&#xff0c;有些地方没有做详细介绍 git init 创建本地仓库&#xff08;最好先创建一个目录&#xff0c;在该目录下输入指令创建git仓…

TI AM64x工业核心板规格书(双核ARM Cortex-A53 + 单/四核Cortex-R5F + 单核Cortex-M4F,主频1GHz)

1 核心板简介 创龙科技SOM-TL64x是一款基于TI Sitara系列AM64x双核ARM Cortex-A53 单/四核Cortex-R5F 单核Cortex-M4F设计的多核工业级核心板&#xff0c;通过工业级B2B连接器引出5x TSN Ethernet、9x UART、2x CAN-FD、GPMC、PCIe/USB 3.1等接口。核心板经过专业的PCB Layo…

行为型模式--备忘录模式

目录 概述 结构 案例实现 “白箱”备忘录模式 总结&#xff1a; “黑箱”备忘录模式 优缺点 优点&#xff1a; 缺点&#xff1a; 使用场景 概述 又叫快照模式&#xff0c;在不破坏封装性的前提下&#xff0c;捕获一个对象的内部状态&#xff0c;并在该对象之外保存这…

举例说明什么是卷积计算

卷积计算是一种数学运算&#xff0c;主要用于信号处理、图像处理等领域。它涉及到两个函数&#xff08;通常称为信号和核&#xff09;的互相关运算。在图像处理中&#xff0c;卷积计算通常用于实现图像的平滑、锐化、边缘检测等操作。 以图像处理为例&#xff0c;我们可以用一个…

C++数据结构笔记(4)企业链表的实现(Linux内核链表)

1.企业链表本质上是一种Linux内核链表。 2.最本质的区别在于&#xff0c;传统的结点类型中直接同时包含了指针域和数据域&#xff0c;用来实现和其他结点之间的串联&#xff1b;而在企业链表中&#xff0c;结点本身只含有指针域&#xff0c;而数据部分的具体实现则在测试文件中…

【云原生】k8s之pod基础(下)

1.pod的镜像拉取策略 1.1 镜像拉取说明 当你在创建容器时会针对指定的镜像来进行容器的创建&#xff0c;所以pod的创建是以镜像为基础。当你在拉取镜向不指定仓库的主机名&#xff0c;Kubernetes 认为你在使用 Docker 公共仓库。 在镜像名称之后&#xff0c;你可以添加一个…

Stage模型HarmonyOS服务卡片开发ArkTS卡片相关模块

图1 ArkTS卡片相关模块 FormExtensionAbility&#xff1a;卡片扩展模块&#xff0c;提供卡片创建、销毁、刷新等生命周期回调。 FormExtensionContext&#xff1a;FormExtensionAbility的上下文环境&#xff0c;提供FormExtensionAbility具有的接口和能力。 formProvider&…

自制游戏引擎

这是一个玩具 1. 引擎使用流程 SmallEngine是引擎的核心模块,封装渲染功能和场景管理功能等Editor是编辑器,类似unity和ue编辑器,能够动态添加对象和组件Sandbox是游戏播放器,能够运行游戏 2. SmallEngine 参考 https://www.bilibili.com/video/BV1KE41117BD/?spm_id_from333…