当前位置: 首页 > news >正文

pcl学习之kd-tree

介绍

通过雷达、激光扫描、立体摄像机等三维测量设备获取的点云数据,具有数据量大、分布不均匀等特点。作为三维领域中一个重要的数据来源,点云数据主要是表征目标表面的海量点的集合,并不具备传统实体网格数据的几何拓扑信息。所以点云数据处理中最为核心的问题就是建立离散点间的拓扑关系,实现基于邻域关系的快速查找。

概念

KD-Tree 是一棵二叉搜索树。与普通的二叉搜索树一样,它具有左儿子比父亲小,右儿子比父亲大的特点。但是,比较点的大小是没有实际意义的,因此,KD-Tree并不是整体比较点的大小,而是比较某一维的大小。

如何构造一棵Kd-tree?

对于Kd-tree这样一棵二叉树,我们首先须要确定如何划分左子树和右子树。即一个K维数据是根据什么被划分到左子树或右子树的。

在构造1维BST树时,一个1维数据依据其与树的根结点和中间结点进行大小比較的结果来决定是划分到左子树还是右子树。同理。我们也能够依照这种方式,将一个K维数据与Kd-tree的根结点和中间结点进行比較。仅仅只是不是对K维数据进行总体的比較,而是选择某一个维度Di。然后比較两个K维数在该维度Di上的大小关系。即每次选择一个维度Di来对K维数据进行划分,相当于用一个垂直于该维度Di的超平面将K维数据空间一分为二。平面一边的全部K维数据在Di维度上的值小于平面还有一边的全部K维数据相应维度上的值。也就是说。我们每选择一个维度进行如上的划分,就会将K维数据空间划分为两个部分。假设我们继续分别对这两个子K维空间进行如上的划分。又会得到新的子空间,对新的子空间又继续划分,反复以上过程直到每一个子空间都不能再划分为止。以上就是构造Kd-Tree的过程,上述过程中涉及到两个重要的问题:1)每次对子空间的划分时。如何确定在哪个维度上进行划分;2)在某个维度上进行划分时,如何确保在这一维度上的划分得到的两个子集合的数量尽量相等。即左子树和右子树中的结点个数尽量相等。

每次对子空间的划分时,如何确定在哪个维度上进行划分?

最简单的方法就是轮着来,即假设这次选择了在第i维上进行数据划分,那下一次就在第j(j≠i)维上进行划分,比如:j = (i mod k) + 1。想象一下我们切豆腐时,先是竖着切一刀,切成两半后。再横着来一刀,就得到了非常小的方块豆腐。但是“轮着来”的方法能否够非常好地解决这个问题呢?再次想象一下,我们如今要切的是一根木条,依照“轮着来”的方法先是竖着切一刀,木条一分为二。干净利落,接下来就是再横着切一刀。这个时候就有点考验刀法了,假设木条的直径(横截面)较大,还能够下手,假设直径较小,就没法往下切了。

因此。假设K维数据的分布像上面的豆腐一样,“轮着来”的切分方法是能够奏效。但是假设K维度上数据的分布像木条一样。“轮着来”就不好用了。因此,还须要想想其它的切法。

假设一个K维数据集合的分布像木条一样。那就是说明这K维数据在木条较长方向代表的维度上。这些数据的分布散得比较开,数学上来说,就是这些数据在该维度上的方差(invariance)比较大。换句话说,正由于这些数据在该维度上分散的比较开,我们就更easy在这个维度上将它们划分开。因此,这就引出了我们选择维度的还有一种方法:最慷慨差法(max invarince)。即每次我们选择维度进行划分时,都选择具有最慷慨差维度。

在某个维度上进行划分时。如何确保在这一维度上的划分得到的两个子集合的数量尽量相等。即左子树和右子树中的结点个数尽量相等?

如果当前我们依照最慷慨差法选择了在维度i上进行K维数据集S的划分,此时我们须要在维度i上将K维数据集合S划分为两个子集合A和B,子集合A中的数据在维度i上的值都小于子集合B中。首先考虑最简单的划分法,即选择第一个数作为比较对象(即划分轴。pivot),S中剩余的其它全部K维数据都跟该pivot在维度i上进行比较。如果小于pivot则划A集合。大于则划入B集合。

把A集合和B集合分别看做是左子树和右子树,那么我们在构造一个二叉树的时候,当然是希望它是一棵尽量平衡的树,即左右子树中的结点个数相差不大。

而A集合和B集合中数据的个数显然跟pivot值有关。由于它们是跟pivot比较后才被划分到对应的集合中去的。好了。如今的问题就是确定pivot了。给定一个数组。如何才干得到两个子数组,这两个数组包括的元素个数差点儿相同且当中一个子数组中的元素值都小于还有一个子数组呢?方法非常easy,找到数组中的中值(即中位数。median)。然后将数组中全部元素与中值进行比较,就能够得到上述两个子数组。相同,在维度i上进行划分时,pivot就选择该维度i上全部数据的中值。这样得到的两个子集合数据个数就基本相同了。

Kd-Tree的构建算法

  1. 在K维数据集合中选择具有最慷慨差的维度k,然后在该维度上选择中值m为pivot对该数据集合进行划分。得到两个子集合;同一时候创建一个树结点node,用于存储;
  2. 对两个子集合反复(1)步骤的过程,直至全部子集合都不能再划分为止。假设某个子集合不能再划分时,则将该子集合中的数据保存到叶子结点(leaf node)。

http://www.taodudu.cc/news/show-1782131.html

相关文章:

  • 【physx/wasm】在physx中添加自定义接口并重新编译wasm
  • excel---常用操作
  • Lora训练Windows[笔记]
  • linux基础指令讲解(ls、pwd、cd、touch、mkdir)
  • InnoDB 事务处理机制
  • 启明云端ESP32 C3 模组WT32C3通过 MQTT 连接 AWS
  • PCL中的点云ICP配准(附源代码和数据)
  • PCL对点云进行滤波处理并进行颜色可视化
  • PCL中的关键点
  • PCL点云参数估计算法之RANSAC和LMEDS
  • PCL计算点云的法线
  • PCL中的点云分割算法
  • PCL中把点云拟合成曲面(附源代码)
  • 环形链表 II
  • C++调用caffe分类模型-Opencv3.4.3
  • C++调用SSD caffe模型进行物体检测-Opencv3.4.3
  • C++调用tensorflow训练好的SSD物体检测模型-opencv3.4.3
  • C++调用mask rcnn进行实时检测--opencv4.0
  • tensorflow线下训练SSD深度学习物体检测模型,C++线上调用模型进行识别定位(干货满满)
  • python训练Faster RCNNC++调用训练好的模型进行物体检测-基于opencv3.4.3(超详细)
  • mask rcnn数据转换为tfrecord数据
  • opencv3.4.2调用训练好的Openpose模型
  • python训练mask rcnn模型C++调用训练好的模型--基于opencv4.0(干货满满)
  • leetcode之移除链表的元素
  • leetcode之奇偶链表
  • leetcode之回文链表
  • ubuntu16.04下安装配置caffe2和detectron(亲测有效,非常简单)
  • leetcode之字符串中的第一个唯一字符
  • 哈希表中处理冲突的方法
  • SENet算法解析
  • SNIP物体检测算法理解
  • yolov3聚类自己数据的anchor box
  • Ubuntu下安装qt57creator-plugin-ros,在QT中进行ROS开发(亲测有效)
  • ROS下面调用自定义的头文件和.cpp/.so文件(亲测有效)
  • C++调用编译好的darknet来进行物体监测
  • hard-negative mining详细介绍