KdTree && Octree 原理学习对比以及可视化分析--"索引树"
1. Kdtree 原理
k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构。主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索);
索引结构中相似性查询有两种基本的方式:
(1). "范围查询" :给定查询点和查询距离的阈值,从数据集中找出所有与查询点距离小于阈值的数据;
(2). "K近邻查询" :K近邻查询是给定查询点及正整数K,从数据集中找到距离查询点最近的"K"个数据,当K=1,则为[最近邻查询];

Kdtree 算法原理(啰嗦,冗长,以下只分析伪码,想看完整的知识扫盲可以看百度百科。。)

Q1: 构建k-d树(createKDTree)
输入:数据点集Data-set和其所在的空间Range
输出:Kd,类型为k-d tree "核心算法流程"
1). 确定split域:对于所有描述子数据(特征矢量),统计它们在每个维上的数据方差。数据方差大表明沿该坐标轴方向上的数据分散得比较开,在这个方向上进行数据分割有较好的分辨率;
2). 确定Node-data域:数据点集Data-set按其第split域的值排序。位于正中间的那个数据点被选为Node-data,新的点集DataSets去除Node-data点;
3). 以中间点Node-data为标准,小于Node-data[split]化为左点集,大于Node-data[split]化为右点集;
4). 左右两边分别建立k-d tree, 即递归调用createKDTree; Q2: 数据查找,检索在k-d树中与查询点距离最近的数据点 1) 从root节点开始,DFS搜索直到叶子节点,同时在stack中顺序存储已经访问的节点。
2) 如果搜索到叶子节点,当前的叶子节点被设为最近邻节点。
3) 然后通过stack回溯:
4) 如果当前点的距离比最近邻点距离近,更新最近邻节点.
5) 然后检查以最近距离为半径的圆是否和父节点的超平面相交.
6) 如果相交,则必须到父节点的另外一侧,用同样的DFS搜索法,开始检查最近邻节点。
7) 如果不相交,则继续往上回溯,而父节点的另一侧子节点都被淘汰,不再考虑的范围中.
8) 当搜索回到root节点时,搜索完成,得到最近邻节点。
2.Octree原理
Octree即为八叉树,它的特性为树中的任一节点的子节点恰好只会有八个或零个。经常应用于3D场景管理,它可以迅速搜索物体在3D场景中的位置,或侦测到与其他物体是否有碰撞以及判断是否在可视范围内。
"算法原理简介"
八叉树是一种用于描述三维空间的树状数据结构。八叉树的每个节点表示一个正方体的体积元素,每个节点有八个子节点,将八个子节点所表示的体积元素加在一起就等于父节点的体积。
"算法流程"
(1). 设定最大递归深度
(2). 找出场景的最大尺寸,并以此尺寸建立第一个立方体
(3). 依序将单位元元素丢入能被包含且没有子节点的立方体
(4). 若没有达到最大递归深度,就进行细分八等份,再将该立方体所装的单位元元素全部分担给八个子立方体
(5). 若发现子立方体所分配到的单位元元素数量不为零且跟父立方体是一样的,则该子立方体停止细分,因为跟据空间分割理论,细分的空间所得到的分配必定较少,若是一样数目,则再怎么切数目还是一样,会造成无穷切割的情形。
(6). 重复3,直到达到最大递归深度。
3.PCL中源代码测试
"Kdtree"
/*
* kdtree:
* 是一种分割K维数据空间的数据结构,主要应用于多维空间关键数据的搜索
* (范围搜索 + 最近邻搜索)
* Author: Ian
*/
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char** argv)
{
string inputfile = argv[1];
pcl::PointCloud<pcl::PointXYZ> xyzCloud;
pcl::PointCloud<pcl::PointXYZRGBA> rgbCloud;
pcl::io::loadPCDFile<pcl::PointXYZ> (inputfile, xyzCloud);
cout<<"input cloud's size ="<<xyzCloud.points.size()<<endl;
pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;
kdtree.setInputCloud(xyzCloud.makeShared());
pcl::PointXYZ searchPoint;
// 取点云数据的中间点
searchPoint = xyzCloud.points[xyzCloud.points.size()/2];
// k nearest neighbor search
int K=10;
std::vector<int> pointIdxNKNSearch(K);
std::vector<float> pointNKNSquaredDistance(K);
if(kdtree.nearestKSearch (searchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance) > 0)
{
std::cout<<"pointIdxNKNSearch.size ="<<pointIdxNKNSearch.size()<<std::endl;
for (size_t i = 0; i < pointIdxNKNSearch.size(); ++i)
std::cout << " " << xyzCloud.points[ pointIdxNKNSearch[i] ].x
<< " " << xyzCloud.points[ pointIdxNKNSearch[i] ].y
<< " " << xyzCloud.points[ pointIdxNKNSearch[i] ].z
<< " (NKN-squared distance: " << pointNKNSquaredDistance[i] << ")" << std::endl;
}
// Neighbors within radius search
std::vector<int> pointIdxRadiusSearch;
std::vector<float> pointRadiusSquaredDistance;
float radius = 0.3f;
if (kdtree.radiusSearch(searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance) > 0)
{
std::cout<<"pointIdxRadiusSearch.size = "<<pointIdxRadiusSearch.size()<<std::endl;
for (size_t i = 0; i < pointIdxRadiusSearch.size(); ++i)
std::cout << " " << xyzCloud.points[ pointIdxRadiusSearch[i] ].x
<< " " << xyzCloud.points[ pointIdxRadiusSearch[i] ].y
<< " " << xyzCloud.points[ pointIdxRadiusSearch[i] ].z
<< " (Radius-squared distance: " << pointRadiusSquaredDistance[i] << ")" << std::endl;
}
return 0;
}
"Octree"
/*
* Octree --八叉树, 用于快速查询物体在3D场景中的位置,或侦测
* 与其他物体是否有碰撞以及是否在可视范围内。
* Author: Ian
*/
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/octree/octree_search.h>
#include <iostream>
#include <vector>
int main(int argc, char**argv)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr xyzCloud(new pcl::PointCloud<pcl::PointXYZ>);
std::string inputfile = argv[1];
pcl::io::loadPCDFile<pcl::PointXYZ> (inputfile, *xyzCloud);
std::cout<<"inputPCD's size ="<<xyzCloud->points.size()<<std::endl;
float resolution = 0.01f;
pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> octree(resolution);
octree.setInputCloud(xyzCloud);
octree.addPointsFromInputCloud();
pcl::PointXYZ searchPoint;
searchPoint = xyzCloud->points[xyzCloud->points.size()/2];
std::vector<int> pointIdxVec;
if(octree.voxelSearch (searchPoint, pointIdxVec))
{
std::cout << "Neighbors within voxel search at (" << searchPoint.x
<< " " << searchPoint.y
<< " " << searchPoint.z << ")"
<< std::endl;
std::cout<<"voxelSearch size = "<<pointIdxVec.size()<<std::endl;
for (size_t i = 0; i < pointIdxVec.size (); ++i)
std::cout << " " << xyzCloud->points[pointIdxVec[i]].x
<< " " << xyzCloud->points[pointIdxVec[i]].y
<< " " << xyzCloud->points[pointIdxVec[i]].z << std::endl;
}
// K nearest neighbor search
int K = 10;
std::vector<int> pointIdxNKNSearch;
std::vector<float> pointNKNSquaredDistance;
if(octree.nearestKSearch (searchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance) > 0)
{
for (size_t i = 0; i < pointIdxNKNSearch.size (); ++i)
std::cout << " " << xyzCloud->points[ pointIdxNKNSearch[i] ].x
<< " " << xyzCloud->points[ pointIdxNKNSearch[i] ].y
<< " " << xyzCloud->points[ pointIdxNKNSearch[i] ].z
<< " (NKN-squared distance: " << pointNKNSquaredDistance[i] << ")" << std::endl;
}
// Neighbors within radius search
std::vector<int> pointIdxRadiusSearch;
std::vector<float> pointRadiusSquaredDistance;
float radius = 0.3f;
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 << " " << xyzCloud->points[ pointIdxRadiusSearch[i] ].x
<< " " << xyzCloud->points[ pointIdxRadiusSearch[i] ].y
<< " " << xyzCloud->points[ pointIdxRadiusSearch[i] ].z
<< " (Radius-squared distance: " << pointRadiusSquaredDistance[i] << ")" << std::endl;
}
return 0;
}
4.Octree可视化分析
因为我想研究三维地图中的柱体图形怎么实时更新,但是我去用pcl_visualization和opengl实现画不同形状的柱体图时,无法满足其实时性能。然后我发现octree的立体分割有点相关的意思,在研究octree可视化案例之后,是否可以将一样大小的立方体改为针对不同障碍物具有不同高度的立方体。这样就能一眼看出障碍物的高度?
论文中的图形示例(我没在学校这篇论文下不下来...抱歉)

参考论文实现的pcl_octree可视化

以及刚开始靠自己理解用opengl画的柱体地图

参考链接
[1]. K-dtree 百度百科
[2]. Octree 百度百科
KdTree && Octree 原理学习对比以及可视化分析--"索引树"的更多相关文章
- python学习笔记(14):可视化分析
一.Matplotlib 1.用于创建出版质量图表的绘图工具库 2.目的的为Python构建一个Matlab式的绘图接口 3.import matplotlib.pyplot as plt:pyplo ...
- 并发编程原理学习-reentrantlock源码分析
ReentrantLock基本概念 ReentrantLock是一个可重入锁,顾名思义,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁,并且在获取锁时支持选择公平模式或者非公平模式 ...
- GIS原理学习目录
GIS原理学习目录 内容提要 本网络教程是教育部“新世纪网络课程建设工程”的实施课程.系统扼要地阐述地理信息系统的技术体系,重点突出地理信息系统的基本技术及方法. 本网络教程共分八章:第一章绪论,重点 ...
- Shader 学习工具篇 可视化公式工具ZGrapher
大家好,我是怒风,本篇介绍公式可视化公式工具ZGrapher,尝试通过可视化的方式分析一下Shader中应用的公式,以求帮助初学者快速理解Shader编程中的一些常用公式 本篇的目的两个, 第一,介绍 ...
- 计算机原理学习(1)-- 冯诺依曼体系和CPU工作原理
前言 对于我们80后来说,最早接触计算机应该是在95年左右,那个时候最流行的一个词语是多媒体. 依旧记得当时在同学家看同学输入几个DOS命令就成功的打开了一个游戏,当时实在是佩服的五体投地.因为对我来 ...
- 使用 QuickBI 搭建酷炫可视化分析
随着各行各业大数据的渗透,BI 类数据分析需求与日俱增,如何让可视化更好的展现数据的价值,是 BI 类产品一直努力的方向.对此国内外的BI产品都有自己的方法,如国外大牌的 PowerBI.Tablea ...
- IIS原理学习
IIS 原理学习 首先声明以下内容是我在网上搜索后整理的,在此只是进行记录,以备往后查阅只用. IIS 5.x介绍 IIS 5.x一个显著的特征就是Web Server和真正的ASP.NET Appl ...
- JAVA 可视化分析工具 第12节
JAVA 可视化分析工具 第12节 经过前几章对堆内存以及垃圾收集机制的学习,相信小伙伴们已经建立了一套比较完整的理论体系!那么这章我们就根据已有的理论知识,通过可视化工具来实践一番. 我们今天要讲 ...
- UML和模式应用学习笔记-1(面向对象分析和设计)
UML和模式应用学习笔记-1(面向对象分析和设计) 而只是对情节的记录:此处的用例场景为:游戏者请求掷骰子.系统展示结果:如果骰子的总点数是7,则游戏者赢得游戏,否则为输 (2)定义领域模型:在领域模 ...
随机推荐
- android中优雅实现recyclerview
在慕课网上看了Abner_泥阿布老师不一样的RecyclerView优雅实现复杂列表布局这个视频课程,本人在Ubuntu16.04LTS下使用android studio2.2.3按照老师讲解写的代码 ...
- 记一次ASP.NET MVC4 升级到MVC5的小问题解决
原文:记一次ASP.NET MVC4 升级到MVC5的小问题解决 .NET 4.0 MVC4版本,升级到.NET 4.6.1 MVC5: 1.使用nuget更新所有 与mvc相关的类库; 2.更改~/ ...
- 【Python】:拓展Queue实现有序不重复队列
最近手头有个需求是这样的,定期检查数据库获取失败任务并且进行重启.最早想到的是添加一个生产者&&消费者队列,但是发现很多棘手的问题. 1.重启任务是调用的一个shell脚本然后在脚本中 ...
- IDHTTP-HTTPS通讯方法(Indy10.2.3之前仅支持OpenSSL的0.9.8以前的版本)
加载https的站点页面内容的时候记得在窗体上加上“IdSSLIOHandlerSocketOpenSSL1” 以及idhttp里面IOHandler为“IdSSLIOHandlerSocketOpe ...
- 企业级架构 MVVM 模式指南 (WPF 和 Silverlight 实现) 译(2)
本书包含的章节内容 第一章:表现模式,以一个例子呈献给读者表现模式的发展历程,我们会用包括MVC和MVP在内的各种方式实现一个收费项目的例子.沿此方向,我们会发现每一种模式的问题所在,这也是触发设计模 ...
- QImage的浅拷贝与深拷贝
首先简单说说什么是浅拷贝和深拷贝:浅拷贝就比如像引用类型,而深拷贝就比如值类型,即浅拷贝是共用一块内存的,而深拷贝是复制一份内容. 我们再来看看QImage类的几个构造函数: // 浅拷贝 QI ...
- Laravel --- artisan创建表以及填充表数据流程总结
1.创建建表文件 php artisan make:migration create_comments_table 打开database/migrations/xxx_create_comments_ ...
- 01-pymysql模块的安装
1.从github 下载pymysql 安装包,下载地址为:https://github.com/PyMySQL/PyMySQL 2.解压下载文件,不用打开python交互界面,cd到解压文件所在目录 ...
- 自定义实现一个loghub(或kafka)的动态分片消费者负载均衡?
一般地,像kafka之类的消息中间件,作为一个可以保持历史消息的组件,其消费模型一般是主动拉取方式.这是为了给消费者足够的自由,回滚或者前进. 然而,也正是由于将消费消息的权力交给了消费者,所以,消费 ...
- vue history 模式打包部署在域名的二级目录的配置指南
最近在做项目,需要把项目部署在域名下的二级目录,并且是在用vue-router的history 模式. 我们都知道vue-router 的两种前端基本访问模式 hash 和history .hash ...