前情提要:PCL安装与测试
PCL文件读写
斯坦福兔子文件

kd,即k-dimension,kd树就是k维树,由于点云所在空间几乎都是三维的,所以最常见的也是3d树。

考虑到演示方便,所以用二维空间中的数据来做一点说明,假设现有六个数据点{(2,3),(5,4),(9,6),(4,7),(8,1),(7,2)},如何能够通过这六个点将空间分割,就如下图一样。

当然上面这个图只是一种方案,或许还有其他的划分方式。

对此例来说,其分割步骤为

  1. 计算x,y方向上数据的标准差,可得sx≈2.4,sy≈2.1s_x\approx2.4,s_y\approx2.1sx​≈2.4,sy​≈2.1,即sx>xys_x>x_ysx​>xy​,所以先分割x方向的数据。
  2. x轴方向的值为2,5,9,4,8,7,排序后为2,4,5,7,8,9,中值为7,所以先在x=7x=7x=7的位置画一条与y轴平行的线,这条线经过点(7,2),将平面分成左子空间和右子空间。
  3. x⩽7x\leqslant7x⩽7的左子空间,包含3个节点{(2,3), (5,4), (4,7)};x>7x>7x>7的右子空间,则包含2个节点{(9,6),(8,1)}。
  4. 对左子空间和右子空间重复1过程,直到所有的点都画了线,最终就得到上图了。

而这个生成分割图的过程,也是生成kd树的过程,其树图为

#mermaid-svg-yctr8yr9shmtqHDn {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-yctr8yr9shmtqHDn .error-icon{fill:#552222;}#mermaid-svg-yctr8yr9shmtqHDn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yctr8yr9shmtqHDn .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-yctr8yr9shmtqHDn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yctr8yr9shmtqHDn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yctr8yr9shmtqHDn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yctr8yr9shmtqHDn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yctr8yr9shmtqHDn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yctr8yr9shmtqHDn .marker.cross{stroke:#333333;}#mermaid-svg-yctr8yr9shmtqHDn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yctr8yr9shmtqHDn .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-yctr8yr9shmtqHDn .cluster-label text{fill:#333;}#mermaid-svg-yctr8yr9shmtqHDn .cluster-label span{color:#333;}#mermaid-svg-yctr8yr9shmtqHDn .label text,#mermaid-svg-yctr8yr9shmtqHDn span{fill:#333;color:#333;}#mermaid-svg-yctr8yr9shmtqHDn .node rect,#mermaid-svg-yctr8yr9shmtqHDn .node circle,#mermaid-svg-yctr8yr9shmtqHDn .node ellipse,#mermaid-svg-yctr8yr9shmtqHDn .node polygon,#mermaid-svg-yctr8yr9shmtqHDn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yctr8yr9shmtqHDn .node .label{text-align:center;}#mermaid-svg-yctr8yr9shmtqHDn .node.clickable{cursor:pointer;}#mermaid-svg-yctr8yr9shmtqHDn .arrowheadPath{fill:#333333;}#mermaid-svg-yctr8yr9shmtqHDn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yctr8yr9shmtqHDn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yctr8yr9shmtqHDn .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-yctr8yr9shmtqHDn .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-yctr8yr9shmtqHDn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yctr8yr9shmtqHDn .cluster text{fill:#333;}#mermaid-svg-yctr8yr9shmtqHDn .cluster span{color:#333;}#mermaid-svg-yctr8yr9shmtqHDn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-yctr8yr9shmtqHDn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

7,2
2,3
5,4
4,7
9,6
8,1

在算法导论中,树往往是和查找挂钩的,kd树亦然,可用于查找与目标点最近的点。

例如要查询点(3,3)(3,3)(3,3),则其步骤为

  1. 和点(7,2)(7,2)(7,2)比较xxx坐标大小,由于3<73<73<7,故在其左子节点;如果在平面图中看,则在x=7x=7x=7的左子区间。
  2. 进入左子节点后,和(5,4)(5,4)(5,4)比较yyy值大小,由于3<43<43<4,故继续比较左子节点;如果在平面图中比较,则在y=4y=4y=4的下子区间。
  3. 由于(5,4)(5,4)(5,4)的左子节点只有一个,所以距离(3,3)(3,3)(3,3)最近的点就是(2,3)(2,3)(2,3)。

PCL中生成kd-tree,只需通过setInputCloud建立搜索空间,便能借助kd树的速度来进行临近点索引,接下来仍然以兔子为例,试用一下PCL中的两个搜索函数nearestKSearchradiusSearch,前者指明最近的K个点;后者搜索出距离目标小于r的点。

#include<iostream>
#include<pcl/io/pcd_io.h>
#include<pcl/common/common.h>         //getMinMax3D函数需要用到
#include <pcl/kdtree/kdtree_flann.h>  //kdtree类定义头文件using namespace pcl;
using namespace std;void randomPoint(PointXYZ *pSearch, PointXYZ pMin, PointXYZ pMax) {pSearch->x = rand()/RAND_MAX * (pMax.x - pMin.x) + pMin.x;pSearch->y = rand()/ RAND_MAX * (pMax.x - pMin.x) + pMin.y;pSearch->z = rand()/ RAND_MAX * (pMax.x - pMin.x) + pMin.z;cout << "the point ("<< pSearch->x << " " << pSearch->y << " " << pSearch->z<< ") will be searched" <<endl;
}void kdTest() {PointCloud<PointXYZ>::Ptr cloud(new PointCloud<PointXYZ>);char strfilepath[256] = "rabbit.pcd";io::loadPCDFile(strfilepath, *cloud);KdTreeFLANN<PointXYZ> kdtree;       //建立kd treekdtree.setInputCloud(cloud);        //设置搜索空间PointXYZ pSearch, pMin, pMax;       //搜索点,三个轴的最大值和最小值getMinMax3D(*cloud, pMin, pMax);    //需要include<pcl/common/common.h>randomPoint(&pSearch, pMin, pMax);  //随机生成搜索点PointXYZ tmp;       //用于存储临时点int K = 2;std::vector<int> ptIdxByKNN(K);      //存储查询点近邻索引std::vector<float> ptKNN(K);         //存储近邻点对应距离平方kdtree.nearestKSearch(pSearch, K, ptIdxByKNN, ptKNN); //执行K近邻搜索cout << "KNN search with K=" << K << endl; for (size_t i = 0; i < ptIdxByKNN.size(); ++i) {tmp = cloud->points[ptIdxByKNN[i]];cout << tmp.x << " " << tmp.y << " " << tmp.z     //打印搜索到的点<< " (squared distance: " << ptKNN[i] << ")" << endl;}// 半径 R内近邻搜索方法float r = 2.5;std::vector<int> ptIdxByRadius;   //存储近邻索引std::vector<float> ptRadius;      //存储近邻对应距离的平方kdtree.radiusSearch(pSearch, r, ptIdxByRadius, ptRadius);std::cout << "search with radius=" << r << endl;for (size_t i = 0; i < ptIdxByRadius.size(); ++i) {tmp = cloud->points[ptIdxByRadius[i]];cout << tmp.x << " " << tmp.y << " " << tmp.z<< " (squared distance: " << ptRadius[i] << ")" << endl;}
}

其输出结果为

the point (-6.793 -6.22287 -7.08207) will be searched
KNN search with K=2
-3.55957 -6.14628 -1.86421 (squared distance: 37.687)
-3.99903 -6.1438 -1.59019 (squared distance: 37.9733)
search with radius=6.15
-3.55957 -6.14628 -1.86421 (squared distance: 37.687)

PCL之kd-tree详解相关推荐

  1. 机器学习算法(二十五):KD树详解及KD树最近邻算法

    目录 1 KD树 1.1 什么是KD树 1.2 KD树的构建 1.3 KD树的插入 1.4 KD树的删除 1.5 KD树的最近邻搜索算法 1.5.1 举例:查询点(2.1,3.1) 1.5.2 举例: ...

  2. BTree和B+Tree详解结构

    如果是复合索引: 关键字的排序先排左侧字段,在左侧字段相同的情况下,再排序右侧字段. BTree和B+Tree详解 B+树索引是B+树在数据库中的一种实现,是最常见也是数据库中使用最为频繁的一种索引. ...

  3. B-Tree 和 B+Tree详解

    B-Tree 和 B+Tree详解 一.什么是B-Tree 1.B-树插入 2.B-树删除 3.总结 二.什么是B+Tree 1.B+树插入 2.B+树删除 3.总结 一.什么是B-Tree B-Tr ...

  4. PCL:k-d tree 1 讲解

    1.简介 kd-tree简称k维树,是一种空间划分的数据结构.常被用于高维空间中的搜索,比如范围搜索和最近邻搜索.kd-tree是二进制空间划分树的一种特殊情况.(在激光雷达SLAM中,一般使用的是三 ...

  5. 数据库优化/Linux安装Mysql/B+Tree详解

    一.Linux安装MySQL yum安装 #下载安装源 wget http://repo.mysql.com/mysql57-community-release-el6-8.noarch.rpm #安 ...

  6. PCL :K-d tree 2 结构理解

    K-d tree 基础思路:(先看之前的KNN思想,更容易理解) 导语:kd 树是一种二叉树数据结构,可以用来进行高效的 kNN 计算.kd 树算法偏于复杂,本篇将先介绍以二叉树的形式来记录和索引空间 ...

  7. KD树详解及KD树最近邻算法

    参考:http://blog.csdn.net/app_12062011/article/details/51986805 http://www.cnblogs.com/snake-hand/arch ...

  8. 二叉查找树(binary search tree)详解

    二叉查找树(Binary Search Tree),也称二叉排序树(binary sorted tree),是指一棵空树或者具有下列性质的二叉树: 若任意节点的左子树不空,则左子树上所有结点的值均小于 ...

  9. 【转】.NET Core 可移植类库PCL Portable Class Library详解

    转自:https://www.kaifaxueyuan.com/server/dotnet-core/dotnet-core-portable-class-library.html 在这一章中,我们将 ...

  10. 关于索引的B tree B-tree B+tree B*tree 详解结构图

    2019独角兽企业重金招聘Python工程师标准>>> B树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结 ...

最新文章

  1. 使用最小堆优化Dijkstra算法
  2. php上传图文教程,PHP 上传图片、文件的方法
  3. fiddler使用AutoResponder更改请求的返回结果
  4. 如何将分表汇总到总表_轻松实现多表汇总数据(多表汇总成单表)
  5. jwt token长度限制_ASP.NET Core Web Api之JWT(一)
  6. python字典添加列表_【Python】对字典列表进行去重追加
  7. JavaScript深入浅出第1课:箭头函数中的this究竟是什么鬼?
  8. 7 种 JavaScript 技巧使你更聪明
  9. java学习(117):list迭代器和包含方法
  10. Docker初级选手(一)
  11. netty sync方法_netty是如何封装NIO的
  12. 从入门到入土:Python爬虫学习|实例练手|爬取百度翻译|Selenium出击|绕过反爬机制|
  13. python手写一个迭代器_搞清楚 Python 的迭代器、可迭代对象、生成器
  14. WPF:window设置单一开启
  15. 【hihocoder 1554】最短的 Nore0061
  16. pdffactory 打印字体_PdfFactory Pro(PDF虚拟打印软件) 中文版分享
  17. Mac电脑网页完整的长截图怎么截
  18. 梦幻西游默认服务器怎么修改器,梦幻西游古龙服务端安装教程
  19. 微信/QQ/TIM消息防撤回最新补丁
  20. CodeForces55A - Flea travel 解题报告

热门文章

  1. win10注册mscomm32.ocx失败
  2. 湖南工程学院CSDN高校俱乐部简介
  3. 【DASCTF2023】Misc mp3
  4. 理解CTP/XTP柜台对接
  5. BugkuCTF writeup
  6. XML解析及JSON解析
  7. JSP文件的运行过程
  8. 单目标跟踪CVPR 2018 ECO+
  9. Mybatis——注入执行sql查询、更新、新增以及建表语句
  10. 手机的耳机插电脑上可以录音吗 怎么录音