(十)OcTree教程二--OcTree在PCL中的应用-空间划分和近邻搜索
来源:互联网 发布:淘宝卖家电话在哪 编辑:程序博客网 时间:2024/06/16 06:25
OcTree在PCL中的应用
八叉树作为三维空间中点的重要数据结构在PCL中有很多应用,下面就分别从空间划分、近邻搜索、点云压缩和空间变化检测几个方面来介绍。
空间划分和近邻搜索
八叉树是将空间平均得分为8个部分,每个节点就是一个部分,我们假设三维空间是一个正立方体,每个节点就是一个小立方体。划分到最后,一个叶子结点代表一个最小的空间范围,我们称之为体素。八叉树的建立过程也就是空间划分的过程。
基于八叉树的近邻搜索可以分为三种:
- 范围搜索
- k最近邻搜索
- 体素内搜索
前两种搜索方式已经在k-d树种介绍过了,这里就不再赘述了,而体素内搜索是octree特有的。它是在给定查询点后,将其所在体素内的所有其他点作为搜索目标的搜索方式。
体素内搜索
头文件
#include <pcl/octree/octree.h>
步骤
- 初始化ocTree树
// 确定分辨率,即最小体素的边长float resolution = 1.0f;pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> octree (resolution);// 载入点云octree.setInputCloud (cloud);octree.addPointsFromInputCloud ();
载入点云后,八叉树会根据分辨率和点云的空间维度得到深度,并得到一个Bounding Box,即一个长方体盒子,它能将整个点云装在它的内部,也就相当于划分出来了点云的空间范围。如果点云的空间范围我们是知道的,那么可以通过defineBoundingBox函数可以直接设定
octree.defineBoundingBox(0, 0, 0, 1, 1, 1); // 参数分别为min_x,min_y,min_z,max_x,max_y,max_z
- 输入查询点进行搜索
octree.voxelSearch(searchPoint, pointIdxVec)
关键函数:
bool voxelSearch (const PointT& point, std::vector<int>& point_idx_data);
- 输入输出参数:
- point[in]:查询点,必须保证在一个最小体素内
- point_idx_data[out]:搜索到的相同体素内的点集,point_ind_data为它们在点云中的下标
- 返回值(bool):若返回true,证明这个最小体素存在,否则不存在。
示例
我们载入一个1mx1mx1m的立方体点云,立方体内点均匀分布,一共有100x100x100个点,最小距离1cm。
选择查询点为立方体中心点,八叉树分辨率为0.3m,得到的结果如下:
红色的点为搜索到的点
我们打印出了一些信息
程序
/* * 功能:octree体素内搜索介绍 */#include <pcl/point_cloud.h>#include <pcl/visualization/pcl_visualizer.h>#include <pcl/octree/octree.h>#include <pcl/io/pcd_io.h>#include <pcl/io/ply_io.h>#include <iostream>#include <vector>#include <ctime>intmain(int argc, char** argv){ if (argc<5) { std::cout << "Usage: " << "<Resolution> " << "<SearchPoint.x>" << "<SearchPoint.y>" << "<SearchPoint.z>" << std::endl; return -2; } else cout << "Resolution : " << argv[1] << endl; //// 构造一个1m X 1m X 1m立方体点云,每个点之间间隔1cm //pcl::PointCloud<pcl::PointXYZ>::Ptr pCubeCloud(new pcl::PointCloud<pcl::PointXYZ>); //for (int x = 0; x < 100; x++) //{ // for (int y = 0; y < 100; y++) // { // for (int z = 0; z < 100; z++) // { // // 注意这里是pCubeCloud->push_back,而不是pCubeCloud->points->push_back // pCubeCloud->push_back(pcl::PointXYZ((float)x/100.0f, (float)y/100.0f, (float)z/100.0f)); // } // } //} //// save //pcl::io::savePCDFile("cube.pcd", *pCubeCloud, true); // load pcl::PointCloud<pcl::PointXYZ>::Ptr pCube(new pcl::PointCloud<pcl::PointXYZ>); if (pcl::io::loadPCDFile("cube.pcd", *pCube) == -1) return -1; // 初始化八叉树 float resolution = atof(argv[1]); // 设置体素大小???? pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> octree(resolution); //octree.defineBoundingBox(0, 0, 0, 1, 1, 1); // 将点云载入八叉树 octree.setInputCloud(pCube); octree.addPointsFromInputCloud(); // 初始化查询点 pcl::PointXYZ searchPoint(atof(argv[2]), atof(argv[3]), atof(argv[4])); // 查询点 // 体素内搜索 std::vector<int> pointIdxVec; pcl::PointCloud<pcl::RGB>::Ptr pPointsRGB(new pcl::PointCloud<pcl::RGB>); pcl::PointCloud<pcl::PointXYZRGBA>::Ptr pCloudShow(new pcl::PointCloud<pcl::PointXYZRGBA>); if (octree.voxelSearch(searchPoint, pointIdxVec)) { std::cout << "Neighbors within voxel search at (" << searchPoint.x << " " << searchPoint.y << " " << searchPoint.z << ")" << std::endl; std::cout << "Searched Points Number : " << pointIdxVec.size() << endl; std::cout << "Leaf Count : " << octree.getLeafCount() << std::endl; // 叶子数 std::cout << "Tree Depth : " << octree.getTreeDepth() << std::endl; // 八叉树深度 std::cout << "Branch Count : " << octree.getBranchCount() << std::endl; // 非叶子结点数 std::cout << "Voxel Diameter : " << octree.getVoxelSquaredDiameter() << std::endl; // ???Voxel Side Length*3 std::cout << "Voxel Side Length : " << octree.getVoxelSquaredSideLen() << std::endl;// 分辨率的平方 double minx, miny, minz, maxx, maxy, maxz; octree.getBoundingBox(minx, miny, minz, maxx, maxy, maxz); std::cout << "BoundingBox: " << "(" << minx << " - " << maxx << ")" << " , " << "(" << miny << " - " << maxy << ")" << " , " << "(" << minz << " - " << maxz << ")" << std::endl; // 整个八叉树的范围 } // 给搜索到的点上色,原始点云中的点全为蓝色,搜索到的上为红色 pPointsRGB->width = pCube->size(); pPointsRGB->height = 1; pPointsRGB->resize(pPointsRGB->width*pPointsRGB->height); pCloudShow->width = pCube->size(); pCloudShow->height = 1; pCloudShow->resize(pPointsRGB->width*pPointsRGB->height); for (size_t i = 0; i < pPointsRGB->size(); i++) { pPointsRGB->points[i].b = 255; } for (size_t i = 0; i < pointIdxVec.size(); ++i) { pPointsRGB->points[pointIdxVec[i]].b = 0; pPointsRGB->points[pointIdxVec[i]].r = 255; } // 合并不同字段 pcl::concatenateFields(*pCube, *pPointsRGB, *pCloudShow); // 可视窗口初始化 pcl::visualization::PCLVisualizer viewer; viewer.setCameraFieldOfView(0.785398); // fov 大概45度 viewer.setBackgroundColor(0.5, 0.5, 0.5); // 背景设为灰色 viewer.setCameraPosition( 0, 0, 5, // camera位置 0, 0, -1, // view向量--相机朝向 0, 1, 0 // up向量 ); viewer.addPointCloud(pCloudShow,"Out"); viewer.addCoordinateSystem(1.0, "cloud", 0); while (!viewer.wasStopped()) { // 显示,直到‘q’键被按下 viewer.spinOnce(); } //pcl::io::savePLYFileBinary("voxelSearchResult.ply", *pCloudShow); // 用cloudcompare读入时rgba变为0 system("pause"); return 0;}
0 0
- (十)OcTree教程二--OcTree在PCL中的应用-空间划分和近邻搜索
- (十一)OcTree教程三--OcTree在PCL中的应用-无序点云在空间中的动态检测
- (十二)OcTree教程四--OcTree在PCL中的应用-点云压缩
- PCL:octree
- 基于octree的空间划分及搜索操作
- OCTREE 教程
- OCTREE 教程
- Octree
- Octree
- octree
- Octree
- Octree
- Octree
- (九)OcTree教程一--OcTree原理介绍
- OCTREE 简介
- OCTREE详解
- 八叉树 Octree
- 八叉树 Octree
- 史上最简单侧滑菜单,0耦合,支持任意ViewGroup。一步集成侧滑(删除)菜单,高仿QQ、IOS。~
- Treeset保证元素唯一且排序的代码示例
- c++primer学习笔记-----3.1命名空间的using 声明
- ECSHOP 数据库结构说明 (适用版本v2.7.3)
- 百度软件测试:一面
- (十)OcTree教程二--OcTree在PCL中的应用-空间划分和近邻搜索
- ZOJ 3870 Team Formation (二进制)
- 任务调度开源框架Quartz动态添加、修改和删除定时任务
- 【uva 11137】Ingenuous Cubrency
- VC中The symbol is "xxx" undefined解决办法
- (十二)OcTree教程四--OcTree在PCL中的应用-点云压缩
- 文章标题
- 陆游和唐婉
- hdu 2516 取石子游戏 (Fibonacci博弈)