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 百度百科

原文地址:https://www.cnblogs.com/ZuDame/p/11193179.html

时间: 2024-10-19 01:31:42

KdTree && Octree 原理学习对比以及可视化分析--"索引树"的相关文章

可对Python运行原理进行可视化分析的工具

Python Tutor Python Tutor是一个对Python运行原理进行可视化分析的工具,网址为: http://www.pythontutor.com 使用范例 参考链接 原文地址:https://www.cnblogs.com/jiangling500/p/8353607.html

55个最实用大数据可视化分析工具

该文转自[IT168 技术] 近年来,随着云和大数据时代的来临,数据可视化产品已经不再满足于使用传统的数据可视化工具来对数据仓库中的数据抽取.归纳并简单的展现.传统的数据可视化工具仅仅将数据加以组合,通过不同的展现方式提供给用户,用于发现数据之间的关联信息.新型的数据可视化产品必须满足互联网爆发的大数据需求,必须快速的收集.筛选.分析.归纳.展现决策者所需要的信息,并根据新增的数据进行实时更新.因此,在大数据时代,数据可视化工具必须具有以下特性: (1)实时性:数据可视化工具必须适应大数据时代数

编译原理学习导论

编译原理学习导论 大学课程为什么要开设编译原理呢?这门课程关注的是编译器方面的产生原理和技术问题,似乎和计算机的基础领域不沾边,但是编译原理却一直作为大学本科的必修课程,同一时候也成为了研究生入学考试的必考内容.编译原理及技术从本质上来讲就是一个算法问题而已,当然因为这个问题十分复杂,其解决算法也相对复杂.我们学的数据结构与算法分析也是讲算法的,只是讲的基础算法,换句话说讲的是算法导论,而编译原理这门课程讲的就是比較专注解决一种的算法了.在20世纪50年代,编译器的编写一直被觉得是十分困难的事情

计算机原理学习(7)-- x86-32 CPU和内存管理之分段管理

前言 前一篇我们介绍了内存管理中的分页试内存管理,分页的主要作用就是使得每个进程有一个独立的,完整的内存空间,通过虚拟内存技术,使得程序可以在较小的内存上运行,而进程之间内存空间相互独立,提高了安全性.这一篇将主要介绍内存管理中分段管理,以及两种的结合,也是目前计算机普遍采用的段页式内存管理.这也直接决定了的后面程序的编译,加载以及允许时的内存布局. 1. 内存分段 1.1 为什么分段? 在x86-16体系中,为了解决16位寄存器对20位地址线的寻址问题,引入了分段式内存管理.而CPU则使用CS

55个最实用的大数据可视化分析工具

俗话说的好:工欲善其事,必先利其器!一款好的工具可以让你事半功倍,尤其是在大数据时代,更需要强有力的工具通过使数据有意义的方式实现数据可视化,还有数据的可交互性:我们还需要跨学科的团队,而不是单个数据科学家.设计师或数据分析员:我们更需要重新思考我们所知道的数据可视化,图表和图形还只能在一个或两个维度上传递信息, 那么他们怎样才能与其他维度融合到一起深入挖掘大数据呢?此时就需要倚仗大数据可视化(BDV)工具,因此,笔者收集了适合各个平台各种行业的多个图表和报表工具,这些工具中不乏有适用于NET.

作业2——英语学习APP的案例分析

英语学习APP的案例分析 很多同学有误解,软件工程课是否就是理论课?或者是几个牛人拼命写代码,其他人打酱油的课?要不然就是学习一个程序语言,搞一个职业培训的课?都不对,软件工程有理论,有实践,更重要的是分析,思辨,总结.在课程中,自己组织团队写一个软件,然后分析,的确是学习软件工程的一个好方法:但我们也可以从别人的成功/失败中学到很多. 我们生活中很多时候要和软件打交道,大家上课开小差时候玩的手机游戏,买火车票的网站,互相联系用的微信.QQ,等等都是软件,都很值得分析.你为何成为它们的用户?它们

如何用FineReport报表进行数据可视化分析?

独立的数据毫无意义,能进行比较和分析的数据才是有价值的数据.在FineReport报表工具中,数据的录入和展示操作只是开始,之后的数据分析才是重头戏.那么在FineReport中经过怎样的配置才能进行数据分析?又怎么进行数据分析呢? 使用FineReport进行数据可视化分析非常简单,经过简单的配置,使用者只需在B/S端简单拖拽目标数据及相关维度,即可得到从不同维度分析的结果,提升数据可视化程度,帮助决策层做出准确的决策.同时降低了系统开发的定制化程度,极大地降低了系统开发者的维护成本. B/S

一周实现大数据可视化分析——敏捷BI助艾瑞咨询集团实现互联网的大数据分析

相对传统分析方法,通过敏捷BI和Hadoop的互补,艾瑞咨询集团的业务效率获得数倍的提升:线下报告交付周期从3至4周缩短至小于1周,软件交付从半年缩短至一个月. 当前,一提到大数据人们就会想Hadoop,它似乎成为大数据的"代言人".不可否认,Hadoop在集群扩展性和成本上都有巨大的优势,但是,Hadoop并不适合做实时分析系统. 因此,很多企业都会利用Hadoop实现数据存储,再通过其他工具实现对大数据的高速捕获和实时分析.这里,我们将通过艾瑞咨询集团的一个真实案例,解读一下敏捷B

R语言学习笔记 之 可视化地研究参议员相似性

基于相似性聚类 很多时候,我们想了解一群人中的一个成员与其他成员之间有多么相似.例如,假设我们是一家品牌营销公司,刚刚完成了一份挂怒有潜力新品牌的研究调查问卷.在这份调查问卷中,我们向一群人展示了新品牌的几个特征,并且要求他们对这个新品牌的每个特征按五分制打分.同时也收集了目标人群的社会经济特征,例如:年龄.性别.种族.住址的邮编以及大概的年收入. 通过这份调查问卷,我们想搞清楚品牌如何吸引不同社会经济特征的人群.最重要的是,我们想要知道这个品牌是否有很大的吸引力.换个角度想这个问题,我们想看看