PCL 中的 kd-tree ,使用的是 FLANN 项目中的数据结构,支持《快速最近邻搜索》。

kd-tree 简称k维树,它是一种空间划分数据结构,它将一组 k 维点存储在一个树结构中,可以理解是 k 维的二叉树。

kd-tree 可以实现有效的《范围搜索》和《最近邻搜索》。

《最近邻搜索》是处理点云数据的核心操作,可用于查找点组或特征描述符之间的对应关系,或者,定义一个或多个点周围的局部邻域。

PCL 中的 kd-tree 位于 common 模块(pcl_common.dll)。

使用时要引用以下头文件:

#include pcl/kdtree/kdtree_flann.h>

以下用一个例子练习一下如何使用 kd-tree 进行点云的《最近邻搜索》。

打开 QT Creator ,然后,新建 QT Application 项目。

在项目文件 .pro 文件中添加如下包含目录和引用的 lib 库

INCLUDEPATH += C:\PCL1.12.1\include\pcl-1.12 C:\PCL1.12.1\3rdParty\FLANN\include \C:\PCL1.12.1\3rdParty\Boost\include\boost-1_78 \C:\PCL1.12.1\3rdParty\Eigen\eigen3 \
win32:LIBS += $$quote(C:\PCL1.12.1\lib\pcl_commond.lib)
win32:LIBS += $$quote(C:\PCL1.12.1\3rdParty\FLANN\lib\flann_s.lib)
win32:LIBS += $$quote(C:\PCL1.12.1\3rdParty\FLANN\lib\flann_cpp_s.lib)

在 main.cpp 的顶部添加头文件引用:

#include <QApplication>
#include <pcl/point_cloud.h>
#include <pcl/kdtree/kdtree_flann.h>

在 main.cpp 的 main 函数中输入如下代码:

//创建6个点的点云
pcl::PointCloudpcl::PointXYZ::Ptr clound(new pcl::PointCloudpcl::PointXYZ());
clound->width = 6;
clound->height = 1;
clound->resize(clound->width *clound->height);
for(int i = 0; i < clound->points.size(); ++i)
{clound->points[i].x = (i * 3) + 1;clound->points[i].y = (i * 3) + 10;clound->points[i].z = (i * 3) + 100;
}
//打印点云
qDebug() << "Clound : ";
for(int i = 0; i < clound->points.size(); ++i)
{qDebug() << clound->points[i].x << "," << clound->points[i].y << "," << clound->points[i].z;
}//创建kd-tree对象,并将点云对象赋值给它
pcl::KdTreeFLANNpcl::PointXYZ tree;
tree.setInputCloud(clound);//最近邻搜索//要搜索的点
pcl::PointXYZ pt;
pt.x = 1.5;
pt.y = 10.5;
pt.z = 100.5;//k近邻搜索
int K = 3;//最近的3个点
std::vector<int> indices;//最近的点的索引
std::vector<float> sqr_distance;//最近的点离搜索点的平方距离
//执行k近邻搜索
tree.nearestKSearch(pt, K, indices, sqr_distance);
//打印搜索结果
qDebug() << "Indices : ";
for(int i = 0; i < indices.size(); ++i)
{qDebug() << indices[i];
}
qDebug() << "sqr_distance : ";
for(int i = 0; i < sqr_distance.size(); ++i)
{qDebug() << sqr_distance[i];
}//半径近邻搜索
double raius = 5;//距离为5
indices.clear();//最近的点的索引
sqr_distance.clear();//最近的点离搜索点的平方距离
//执行半径近邻搜索
tree.radiusSearch(pt, raius, indices, sqr_distance);
//打印搜索结果
qDebug() << "Indices : ";
for(int i = 0; i < indices.size(); ++i)
{qDebug() << indices[i];
}
qDebug() << "sqr_distance : ";
for(int i = 0; i < sqr_distance.size(); ++i)
{qDebug() << sqr_distance[i];
}

我使用的是编译器是MSC++Compiler16(VS2019):

用该编译器时,PCL中有1个位置有一个bug,对vs的编译器漏写了一个变量,编译项目时,会提示错误,这时,需要修改后才能通过编译:

(1)修改 dist.h 文件

文件路径:C:\PCL1.12.1\3rdParty\FLANN\include\flann\algorithms\dist.h。

另外,QT6.3 创建的项目,默认使用 C++17,.pro文件中有如下行:

PCL1.12.1 使用的 FLANN 项目代码中有2处被C++17弃用的STL函数,项目编译时也会提示错误,这时,需要手动修改:

(1)std::binary_function 函数

调用该函数的文件是:

C:\PCL1.12.1\3rdParty\FLANN\include\flann\util\heap.h

直接注释掉即可:

(2)std::random_shuffle 函数

调用该函数的文件有3个:

C:\PCL1.12.1\3rdParty\FLANN\include\flann\util\random.h

C:\PCL1.12.1\3rdParty\FLANN\include\flann\algorithms\kdtree_index.h

C:\PCL1.12.1\3rdParty\FLANN\include\flann\util\lsh_table.h

三个文件中都把 std::random_shuffle 函数调用改为 std::shuffle 函数调用即可,如下:

(2.1)修改 random.h

第一步,头文件添加 #include :

第二步,把 std::random_shuffle 函数调用改为 std::shuffle 函数调用:

(2.2)修改 kdtree_index.h

第一步,头文件添加 #include :

第二步,把 std::random_shuffle 函数调用改为 std::shuffle 函数调用:

(2.3)修改 lsh_table.h

第一步,头文件添加 #include :

第二步,把 std::random_shuffle 函数调用改为 std::shuffle 函数调用:

以上的例子编译成功后,运行可以得到如下输出:

Clound :
1 , 10 , 100
4 , 13 , 103
7 , 16 , 106
10 , 19 , 109
13 , 22 , 112
16 , 25 , 115
Indices :
0
1
2
sqr_distance :
0.75
18.75
90.75
Indices :
0
1
sqr_distance :
0.75
18.75

如上所示,K近邻搜索得到,离搜索点最近的3个点的平方距离是 0.75、18.75、90.75 ,可见之后的半径为 5 的半径搜索只能搜索到最大 5*5=25 距离的点,因此,结果就是如图所示的 0.75 和 18.75 这 2 个点。

PCL中 的 kd-tree相关推荐

  1. k-d tree树 近邻算法

    k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点匹配的时候就会利用到k ...

  2. k-d tree算法

    k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点匹配的时候就会利用到k ...

  3. K-D Tree 算法详解及Python实现

    K-D Tree 算法 k−d treek−dtree\mathrm{k-d\ tree}即k−dimensional treek−dimensionaltree\mathrm{k-dimension ...

  4. KD tree and Bbf

    k-d tree算法 k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点 ...

  5. PCL:k-d tree 1 讲解

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

  6. PCL点云库调库学习系列——k-d tree与八叉树

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

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

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

  8. kd-tree理论以及在PCL 中的代码的实现

    (小技巧记录:博客园编辑的网页界面变小了使用Ctrl  ++来变大网页字体) 通过雷达,激光扫描,立体摄像机等三维测量设备获取的点云数据,具有数据量大,分布不均匀等特点,作为三维领域中一个重要的数据来 ...

  9. k-d tree算法的研究

    By RaySaint 2011/10/12 动机 先前写了一篇文章<SIFT算法研究>讲了讲SIFT特征具体是如何检测和描述的,其中也提到了SIFT常见的一个用途就是物体识别,物体识别的 ...

  10. 如何利用 C# 实现 K-D Tree 结构?

    我的朋友海伦一直使用在线约会网站寻找适合自己的约会对象.尽管约会网站会推荐不同的人选,但她没有从中找到喜欢的人.经过一番总结,她发现曾交往过三种类型的人: 不喜欢的人 魅力一般的人 极具魅力的人 尽管 ...

最新文章

  1. LeetCode 300. Longest Increasing Subsequence--O(n log n)--Java,C++,Python解法
  2. python画函数曲线-python画蝴蝶曲线图的实例
  3. 原价买了二手机,我是如何做到的?
  4. Programming Computer Vision with Python (学习笔记三)
  5. 凝血酶分子机器人_了不得!这个机器人可以拟制癌细胞生长
  6. JavaScript DOM编程艺术第二版学习(1/4)
  7. Java--Mybatis万字长文经典面试题王者笔记《收藏版》
  8. C#socket通信时,怎样判断socket双方是否断开连接
  9. 20145235李涛《网络对抗》逆向及Bof基础
  10. 开发者如何谈判才能获得更高的薪水?
  11. (六)WebRTC手记之WebRtcVideoEngine2模块
  12. Facebook 开源 React Native - iOS移动开发周报
  13. centos npm最新版 安装_Docker安装基本命令操作,带你了解镜像和容器的概念!
  14. ThinkPHP5旅游管理系统
  15. 转载:肖知兴:管理到底是个什么鬼,以及怎么破
  16. Unity模拟鼠标点击
  17. ANSYS 有限元分析 加载/求解/输出
  18. 越狱相关三:OpenSSH
  19. WORD打印出现错误,未定义书签.
  20. cocos2dx3.17-lua的csb文件使用方法

热门文章

  1. 筑梦数字时代,城链科技战略峰会西安站顺利落幕
  2. 【学习笔记】无限极分类学习
  3. 国耀明医互联网医院: 白露吃什么好 白露食疗方
  4. python函数做菜单_学不会的Python函数——函数小案例(名片管理器)
  5. 俞敏洪老师谈英语单词记忆方法——转
  6. 备婚倒数日或纪念日记录的提醒APP
  7. 网络计算机抗震计算阻尼比,抗震结构设计经典计算题及答案.doc
  8. 双眼皮疤痕增生期一般是多久会消失
  9. python语言进行生日悖论分析--随机试验方法
  10. 游戏服务器内三类线程池的划分与使用