kd树理解——特征匹配、机器学习

本文介绍了kd树的基础知识及构建方法,通过实例讲解如何选择分割维度和节点数据,适用于特征点匹配等场景。

本文为在阅读了多篇博客与学习之后总结自己的理解,所以尽量以个人理解过程书写,希望能够对需要学习的朋友有所帮助!(PS:鉴于时间有限,文章会不断更新,如有不当之处,希望能够指出,共同进步!)

引入

在学习SIFT、SURF特征提取和匹配算法时,提取了图像特征点并构建特征描述子后,一般可以根据欧式距离计算特征点描述子的相似程度,从而判定两幅图像中匹配的特征点对。在特征点数量较少时,直接使用穷举的方法,计算俩图像中每一对特征点之间的欧氏距离,然后找每一特征点对应欧氏距离最小的特征点即可。然而,当特征点数量较多时,暴力搜索方法会使得匹配消耗的时间变得巨大,而是用kd树方法可以又想降低耗时。

kd树的基本知识

kd树(k-dimensional树),是一种分割k维数据空间的数据结构。主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索)。首先,直观了解一下kd树的表现形式,如以下给定二维数据集合:(2,3), (5,4), (9,6), (4,7), (8,1), (7,2),可以得到kd树的形式如下:
树状形式 二维空间划分
图1 kd树构建形式
数据集为二维数据,即x和y,左图中从上往下三行分别为根节点、子节点和叶;右图中为二维平面被kd树分割成几个部分,每个叶在不同的部分中。接下来,我们具体学习kd树的构建及其应用。
kd树的基本操作有4点:
1、kd树的构建
2、kd树的插入
3、kd树的删除
4、kd树的最邻近搜索算法
以下,我们将分别介绍这几个部分的操作。

1、kd树的构建

如同二叉树一般,kd树的构建主要是对数据集以节点的位置往下延伸,每个节点下最多两个枝叶,直到数据集全部在树中,即完成kd树的构建。问题在于当你拿到一个数据集之后,应该如何确定每个节点的数据?接下来,我们来从根节点往下,确定每个节点的选定。因为kd树的建立一般是在特征分类与匹配中使用,所以对节点两侧的数据应当具有尽量大的区别。
首先,根节点由哪一维数据来确定是依据数据集中每一维数据的方差决定的,例子中的数据是二维的(x,y),分别计算x维与y维数据的方差,结果分别为34.83和26.14,因此以x维数据作为分割依据,将数据以x维排序:(2,3), (4,7), (5,4), (7,2), (8,1), (9,6),以x维数据中值数据作为根节点,即为(7,2),于是,根据x维>=7和<7数据可以分为(2,3), (4,7), (5,4)和(8,1), (9,6);接着<7的三个数据由y维数据中值数据作为左侧子节点判断依据,即(5,4);然后叶部分根据y维>=4和<4又可以分开,即左侧的树已经建立;
右侧树的建立方法同左侧树的建立一样,因为只有两个数据,无中值选取y维数据大的(9,6)作为子节点,叶为(8,1),即右侧树也建立完成;
注意:因为树的每个节点是对空间的划分,二维数据即对二维平面不断切割,为使切割平面得到的每个部分区分度最高,在选则某维数据作为判断节点数据是应遵循x-y-x-y…的循环顺序!
(未完待续…)

03-08
### KD概述 KD(k-dimension tree)是一种用于分割 k 维数据空间的数据结构,主要用于多维空间关键数据的搜索[^2]。这种数据结构通过递归地沿各个维度切分空间来组织点集,使得查询操作如最近邻查找变得更为高效。 ### 算法原理 构建 KD 的过程涉及交替选择不同的坐标轴作为划分标准,并选取中位数节点作为当前层次上的根节点或子节点。对于给定的一组二维平面内的点 (2,3),(5,4),(9,6),(4,7),(8,1),(7,2),可以按照 x 或 y 坐标的顺序依次排列并取中间位置的点作为分支点,从而形成一棵平衡二叉[^3]。 当执行搜索任务时,比如寻找最接近目标点 P 的邻居,会先沿着路径找到叶节点对应的区域;接着回溯至父级节点处评估其他可能更近的候选者所在分区,直到遍历完所有潜在的最佳匹配为止[^1]。 ### 实现方法 以下是基于 C++ 和 Point Cloud Library(PCL) 库的一个简单例子展示如何创建 KDTree 并完成一次 K 近邻(KNN) 查询: ```cpp #include <pcl/kdtree/kdtree_flann.h> #include <pcl/point_cloud.h> #include <pcl/point_types.h> int main () { pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); // Fill in the cloud data cloud->width = 5; cloud->height = 1; cloud->points.resize(cloud->width * cloud->height); for (size_t i = 0; i < cloud->points.size (); ++i){ cloud->points[i].x = 1024 * rand () / (RAND_MAX + 1.0f); cloud->points[i].y = 1024 * rand () / (RAND_MAX + 1.0f); cloud->points[i].z = 1024 * rand () / (RAND_MAX + 1.0f); } // Create a KDTreeFLANN object and pass it the pointer to your input dataset. pcl::KdTreeFLANN<pcl::PointXYZ> kdtree; kdtree.setInputCloud (cloud); // Perform nearest neighbor search using kd-tree structure } ``` 上述代码片段展示了初始化一个点云对象 `cloud` 后填充随机生成的空间点集合,并利用这些点建立了一个 KD 实例 `kdtree` 来准备后续的各种快速检索操作。 ### 应用场景 KD 因其高效的索引机制,在多个领域内得到了广泛应用,尤其是在处理大规模高维数据的情况下表现优异。具体来说,在机器学习和计算机视觉等领域中,它被用来加速相似度计算、模式识别以及图像配准等工作流程。另外,在三维重建与机器人导航等实际工程项目里也经常能看到其身影——例如在激光雷达点云处理过程中辅助完成诸如点云聚类、地面分割及特征提取的任务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值