k-d tree与八叉树

1 k-d tree与八叉树

本文并不涉及具体原理的解释,文章着重在k-d树与八叉树在近邻搜索方面的API的使用

1.1 k-d tree

k-d tree算法及原理: https://www.cnblogs.com/flyinggod/p/8727584.html

实现功能

  • 使用k-d tree找到某个具体点的k近邻
  • 在指定半径内搜索其近邻

关键API

//k近邻搜索
int pcl::search::KdTree< PointT, Tree >::nearestKSearch (const PointT &point,                 //搜索点int k,                                 //搜索个数  std::vector<int> &k_indices,      //保存近邻的索引值std::vector<float> &k_distances     //保存近邻的平方距离
)const//半径radius内近邻搜索
int pcl::search::KdTree< PointT, Tree >::radiusSearch (const PointT &point,               //搜索点double radius,                     //搜索半径std::vector<int> &k_indices,        //保存近邻的索引值std::vector<float> &k_sqr_dists,    //保存近邻的平方距离unsigned int max_nn              //默认值0,如果给定一个数值,则将返回近邻的最大值限制在这个数值以下(包括该数值),如果给0或者高于输入点云中的个数,则返回半径中的所有近邻
)const

完整代码

    #include <pcl/point_cloud.h>#include <pcl/kdtree/kdtree_flann.h>#include <iostream>#include <vector>#include <ctime>intmain(int argc, char** argv){srand(time(NULL));  //初始化随机数种子pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);// Generate pointcloud data//随机点云生成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);}pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;     //创建KdTreeFLANN对象kdtree.setInputCloud(cloud);                //设置被搜索的点云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);// K nearest neighbor search/*--------------k近邻搜索----------------------*///近邻个数int K = 10;//这两个向量用来分别存储近邻的索引值、近邻的中心距std::vector<int> pointIdxNKNSearch(K);std::vector<float> pointNKNSquaredDistance(K);std::cout << "K nearest neighbor search at (" << searchPoint.x<< " " << searchPoint.y<< " " << searchPoint.z<< ") with K=" << K << std::endl;//核心函数nearestKSearch(),第三个参数的类型为pcl::Indices,进一步参看该类型可以发现为vector<int>,这也就是为什么前面pointIdxNKNSearch的类型声明为vector<int>if (kdtree.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;//radiusSearch最后一个参数,用于限制满足近邻条件后的结果的个数,默认值为0,代表全部输出if (kdtree.radiusSearch(searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance, 3) > 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;}return 0;}

运行结果

//k近邻搜索结果
K nearest neighbor search at (443.625 766.75 839.094) with K=10450.813 818.625 869.688 (squared distance: 3678.65)449.688 737.063 784.75 (squared distance: 3871.34)445.344 825.344 864.063 (squared distance: 4059.62)497.906 737.563 874.625 (squared distance: 5060.83)392.219 728.281 870.125 (squared distance: 5085.39)437.094 762.938 766.313 (squared distance: 5354.3)463.188 814.344 780.063 (squared distance: 6132.54)441.531 791.875 745.313 (squared distance: 9430.57)465.75 811.781 754.781 (squared distance: 9625.93)491.125 677.094 821 (squared distance: 10621.9)//指定半径内的搜索结果
Neighbors within radius search at (443.625 766.75 839.094) with radius=130.57450.813 818.625 869.688 (squared distance: 3678.65)449.688 737.063 784.75 (squared distance: 3871.34)445.344 825.344 864.063 (squared distance: 4059.62)497.906 737.563 874.625 (squared distance: 5060.83)392.219 728.281 870.125 (squared distance: 5085.39)437.094 762.938 766.313 (squared distance: 5354.3)463.188 814.344 780.063 (squared distance: 6132.54)441.531 791.875 745.313 (squared distance: 9430.57)465.75 811.781 754.781 (squared distance: 9625.93)491.125 677.094 821 (squared distance: 10621.9)395.406 670.344 847.875 (squared distance: 11696.3)513.594 749.344 930.344 (squared distance: 13525.2)447.656 660.813 898.438 (squared distance: 14760.7)449.969 763.281 961.281 (squared distance: 14982.1)419.344 869.75 776.75 (squared distance: 15085.3)380.563 866.75 886.688 (squared distance: 16242)492.063 684.906 925.594 (squared distance: 16526.8)//结果是由小到大依次排列

对最大的距离进行验证发现

对16526开平方==128 < 130.57 可以判断所得到的结果都是在规定的搜索半径内的

1.2 八叉树

八叉树相关解释见:https://blog.csdn.net/qq_37855507/article/details/90957798

实现功能

学习使用八叉树在点云数据中进行近邻搜索

  • 体素内近邻搜索
  • K近邻搜索
  • 半径内近邻搜搜

关键API

//[in]表示输入参数, [out]表示输出参数
bool pcl::octree::OctreePointCloudSearch< PointT, LeafContainerT, BranchContainerT >::voxelSearch(const PointT& point,                //[in]搜索点std::vector<int>& point_idx_data     //[out]搜索到的近邻带你索引
) //k近邻搜索
int pcl::search::Octree< PointT, LeafTWrap, BranchTWrap, OctreeT >::nearestKSearch(const PointT& point,           //[in]搜索点int k,                         //[in]近邻点个数std::vector<int>& k_indices,   //[out]搜索到的近邻带你索引std::vector<float>& k_sqr_distances  //[out]搜索到的紧邻点的平方距离
)const //半径搜搜
int pcl::search::Octree< PointT, LeafTWrap, BranchTWrap, OctreeT >::radiusSearch(const PointT& p_q,           //[in]搜索点double radius,                 //[in]搜索半径std::vector<int>& k_indices,    //[out]搜索到的近邻带你索引std::vector<float>& k_sqr_distances,  //[out]搜索到的紧邻点的平方距离unsigned int max_nn = 0        //[in]用来限制找到的结果的最大个数,默认为0,即报错所有结果
)const

完整代码

#include <pcl/point_cloud.h>
#include <pcl/octree/octree_search.h>#include <iostream>
#include <vector>
#include <ctime>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 (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 = 256.0f;  //八叉树的分辨率参数,用来描述最低一级八叉树的最小体素的尺寸pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> octree(resolution);  //初始化八叉树octree.setInputCloud(cloud);        //设置输入点云octree.addPointsFromInputCloud();   //构建八叉树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);// Neighbors within voxel search//体素内近邻搜索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 (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;             //存储k近邻搜索点的索引结果         std::vector<float> pointNKNSquaredDistance;     //存储k近邻搜索的平方距离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;}
}

运行结果

在指定的半径内没有搜索到满足条件的点

PCL点云库调库学习系列——k-d tree与八叉树相关推荐

  1. PCL点云库安装及学习(2021.7.28)

    PCL点云库学习 2021.7.28 1.PCL简介 2.Win10系统下PCL环境配置 2.1 前提环境(Win10 64位+Visual Studio 2015) 2.2 方式一:源码编译(过程繁 ...

  2. (学习笔记)PCL点云库的基本使用

    目录 前言 1.理解点云库 1.1.不同的点云类型 1.2.PCL中的算法 1.3.ROS的PCL接口 2.创建第一个PCL程序 2.1.创建点云 2.2.加载点云文件 2.3.创建点云文件 2.4. ...

  3. 《PCL点云库学习VS2010(X64)》Part 34 旋转平移矩阵用法

    <PCL点云库学习&VS2010(X64)>Part 34 旋转平移矩阵用法 1.变换与投影矩阵讲解: https://en.wikipedia.org/wiki/Transfor ...

  4. 《PCL点云库学习VS2010(X64)》Part 45 点云压缩算法—扫描线(DouglasPeuckerAlgorithm)

    <PCL点云库学习&VS2010(X64)>Part 45 点云压缩算法-扫描线(DouglasPeuckerAlgorithm) 道格拉斯-普克算法主要应用有点云滤波.点云压缩. ...

  5. 《PCL点云库学习VS2010(X64)》Part 51 PTDV0.2迭代加密三角网算法V0.2

    <PCL点云库学习&VS2010(X64)>Part 51 PTDV0.2迭代加密三角网算法V0.2 1.利用实际点云测试初级版本的渐进加密三角网算法: 1.获取最低点 2.构建初 ...

  6. 《PCL点云库学习VS2010(X64)》Part 41 图形学领域的关键算法及源码链接

    <PCL点云库学习&VS2010(X64)>Part 41 图形学领域的关键算法及源码链接 原文链接: Conference papers Graphics Conference ...

  7. 《PCL点云库学习VS2010(X64)》Part 37 FLANN——快速最近邻搜索库

    <PCL点云库学习&VS2010(X64)>Part 37 FLANN--快速最近邻搜索库 一.介绍 该算法库在OpenCV和PCL等开源库中应用较广,是PCL的默认安装库之一.与 ...

  8. PCL点云库学习(1):环境配置(Ubuntu16.04+QT5+VTK8.0)

    方式一:从公共软件源安装 sudo apt-get install libpcl-dev pcl-tools 直接输入上面代码安装,不保证一定能行.有一堆依赖的东西,保不准就报错了. 方式二:编译安装 ...

  9. 编译安装PCL点云库,Kinect2驱动,乐视Astra相机驱动

    编译安装PCL点云库 安装方法一 3d点云安装 apt-cache cearch pcl 安装 sudo apt install 上面查出来的 opencv不建议用以上方法因为需要 安装 opencv ...

最新文章

  1. 数据蒋堂 | “后半”有序的分组
  2. 初步了解Telerik for WPF 控件
  3. 玩转Mixly – 3、Arduino AVR编程 之 控制
  4. KnowIME: A System to Construct a Knowledge Graph for Intelligent Manufacturing Equipment-学习笔记
  5. Catalan卡塔兰数
  6. java 图片缓存工具,java缓存读取图片解决方案
  7. CVX学习笔记(转载
  8. 当浙江“十万企业上云“遇见中国软件生态大会
  9. 再见Activity!SpringBoot+flowable完美结合,快速实现工作流,so easy!
  10. 永磁同步电机转子磁链_采用冻结磁导率的瞬态场永磁同步电机交直轴电感计算...
  11. 苹果AirPlay浅析
  12. 论文阅读:Ultra Wide View Based Panoramic VR Streaming
  13. 品牌生命周期和产品生命周期之间的关系
  14. tableau ODBC驱动下载方法和链接(连接mysql的驱动)
  15. 解决Antimalware Service Executable(windows defender)占用过高CPU和内存的方法
  16. 【Hexo】Hexo搭建Butterfly主题并快速美化
  17. BT种子文件格式[ ]
  18. mongodb用户管理1
  19. 爱优腾火力聚焦耽改101,2021能否续写出圈神话?
  20. 【强化学习论文合集】十三.2018机器人与自动化国际会议论文(ICRA2018)

热门文章

  1. [Qt5] QGraphics图形视图框架概述(Item、Scene和View)
  2. ElasticSearch系列 - SpringBoot整合ES:实现分页搜索 from+size、search after、scroll
  3. Linux名词详解手册
  4. 和家亲摄像头sd卡内视频通过电脑播放读取方式
  5. 使用Arduino读取噪声传感器分贝值
  6. DSE200:Python for Data Science 学习笔记(三)
  7. Docker的架构与自制镜像的发布
  8. Android下Bonjour服务的使用
  9. 电脑软件超时、MOCK测试方案
  10. Laravel表格操作Laravel-Excel