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

CloudCompare 中的 KDTree详解

CloudCompare 中的 KDTree 详解

1. 什么是 KDTree

KDTreeK 维空间划分树(K-Dimensional Tree),它是一种 用于高效查找最近邻点 的数据结构。
CloudCompare 中的 KDTree 主要用于:

  • 最近邻搜索(Nearest Neighbor Search)
  • 点云匹配和 ICP(Iterative Closest Point)配准
  • 点云去噪
  • 半径范围搜索
  • 点云加速索引

相比 DgmOctree(八叉树),KDTree高维数据查找 方面更高效,特别是在 点云数据较大 时。


2. KDTree 的核心数据结构

KDTree 主要由 KdCell 结构体和 KD 树递归构建、搜索等方法 组成。

class CC_CORE_LIB_API KDTree
{
public://! 默认构造函数KDTree();//! 析构函数virtual ~KDTree();//! 构建 KD 树bool buildFromCloud(GenericIndexedCloud* cloud, GenericProgressCallback* progressCb = nullptr);//! 获取构建 KD 树的点云GenericIndexedCloud* getAssociatedCloud() const { return m_associatedCloud; }//! 进行最近邻搜索bool findNearestNeighbour( const PointCoordinateType* queryPoint,unsigned& nearestPointIndex,ScalarType maxDist );//! 进行带最大距离约束的最近邻搜索bool findNearestNeighbourWithMaxDist( const PointCoordinateType* queryPoint,ScalarType maxDist );//! 在给定距离范围内查找点unsigned radiusSearch( const PointCoordinateType* queryPoint,ScalarType distance,ScalarType tolerance,std::vector<unsigned>& pointIndexes );protected:struct KdCell{unsigned cuttingDim;         // 划分维度(x/y/z)PointCoordinateType cuttingCoordinate;  // 划分位置struct KdCell* leSon;       // 左子节点struct KdCell* gSon;        // 右子节点struct KdCell* father;      // 父节点unsigned startingPointIndex; // 该单元格中的起始点索引unsigned nbPoints;           // 该单元格包含的点数CCVector3 inbbmax; // 内部包围盒最大坐标CCVector3 inbbmin; // 内部包围盒最小坐标CCVector3 outbbmax; // 外部包围盒最大坐标CCVector3 outbbmin; // 外部包围盒最小坐标};KdCell* m_root;                    // 根节点std::vector<unsigned> m_indexes;    // 点索引GenericIndexedCloud* m_associatedCloud; // 关联的点云数据unsigned m_cellCount;               // 树中的单元格数
};

3. KDTree 的主要功能

(1)构建 KD 树

CloudCompare 通过 KDTree::buildFromCloud() 方法来 构建 KD 树

CCCoreLib::KDTree kdTree;
kdTree.buildFromCloud(&cloud);

构建 KD 树后,点云数据被组织成 层级化的树结构,便于加速最近邻搜索。


(2)最近邻搜索

🔹 findNearestNeighbour() 方法

查找最近邻点

CCCoreLib::KDTree kdTree;
unsigned nearestPointIndex;
CCVector3 queryPoint(1.0, 2.0, 3.0);
bool found = kdTree.findNearestNeighbour(queryPoint.u, nearestPointIndex, 10.0);
  • queryPoint 是查询点
  • nearestPointIndex 返回找到的最近邻点索引
  • 10.0 是搜索的最大距离阈值

返回值

  • true:找到最近点,且其距离 ≤ maxDist
  • false:未找到

🔹 findNearestNeighbourWithMaxDist() 方法

优化的最近邻搜索,仅判断是否存在某个点在 maxDist 以内:

bool exists = kdTree.findNearestNeighbourWithMaxDist(queryPoint.u, 10.0);

findNearestNeighbour() 速度更快,因为它不需要返回最近点的具体索引。


(3)半径范围搜索

radiusSearch() 方法用于 查找所有位于给定半径范围内的点

std::vector<unsigned> neighbors;
float searchRadius = 5.0;
float tolerance = 0.1;
unsigned count = kdTree.radiusSearch(queryPoint.u, searchRadius, tolerance, neighbors);

返回 位于 [radius - tolerance, radius + tolerance] 之间的所有点的索引


(4)递归 KD 树操作

KD 树的搜索和索引操作涉及递归遍历:

🔹 计算点到单元格的距离
ScalarType distance = kdTree.pointToCellSquareDistance(queryPoint.u, kdCell);

计算点到 KD 树单元格的平方距离。


🔹 递归遍历 KD 树查找最近点
int closestIndex = kdTree.checkClosestPointInSubTree(queryPoint.u, maxDist, kdCell);
  • 递归遍历 KD 树
  • 仅返回 maxDist 更近的点
  • 用于优化搜索速度

4. KDTree vs DgmOctree

数据结构KDTreeDgmOctree
主要用途最近邻搜索点云索引、邻域搜索
适用数据任意维度的点云数据三维点云
构建复杂度O(n log n)O(n)
查询速度O(log n)O(log n)
适用场景ICP、点匹配、密集点云处理点云分割、降采样、大规模点云

5. KDTree 的应用

(1)ICP(迭代最近点)配准

CloudCompare 使用 KDTree加速 ICP 计算最近邻点

CCCoreLib::ICPRegistrationTools::Parameters params;
params.kdTree = &kdTree;  // 使用 KD 树加速
CCCoreLib::ICPRegistrationTools::Result result;
CCCoreLib::ICPRegistrationTools::Register(&sourceCloud, &targetCloud, params, result);

(2)点云去噪

在 CloudCompare 进行 统计滤波 时,可用 KDTree 进行 K 近邻搜索

std::vector<unsigned> neighbors;
unsigned k = 10;  // 查找最近的 10 个邻居
for (size_t i = 0; i < cloud.size(); ++i)
{kdTree.findNearestNeighbour(cloud.getPoint(i).u, k, neighbors);
}
  • 计算点周围的 均值和标准差
  • 过滤掉离群点(噪声)

(3)点云匹配

CloudCompare 进行 点云配准时,可以使用 KDTree 加速最近邻搜索,从而提高计算效率。


6. 总结

KDTree加速最近邻搜索 的核心数据结构
✅ 适用于 ICP、点云去噪、K 近邻搜索、半径范围查询
✅ 对于 大规模点云数据KDTreeDgmOctree 更高效
✅ CloudCompare 通过 KDTree 优化 ICP 配准、点云匹配和点云降噪

http://www.xdnf.cn/news/3512.html

相关文章:

  • 设计模式简述(十六)门面模式
  • DeepSeek构建非农预测模型:量化关税滞后效应与非线性经济冲击传导
  • cPanel 的 Let’s Encrypt™ 插件
  • 平台介绍-开放API接口-鉴权
  • 【C到Java的深度跃迁:从指针到对象,从过程到生态】第五模块·生态征服篇 —— 第二十章 项目实战:从C系统到Java架构的蜕变
  • MATLAB滤波工具箱演示——自定义维度、滤波方法的例程演示与绘图、数据输出
  • 详细说明StandardCopyOption.REPLACE_EXISTING参数的作用和使用方法
  • 虚幻引擎 IK Retargeter 编辑器界面解析
  • 上位机知识篇---PSRAM和RAM
  • 从零开始讲DDR(9)——AXI 接口MIG 使用(2)
  • n8n 键盘快捷键和控制键
  • 基于YOLOV5的目标检测识别
  • Expected SARSA算法详解:python 从零实现
  • 输入输出(python)
  • BBR 之 ProbeRTT 新改
  • DeepSeek-R1模型蒸馏
  • SALOME源码分析: ParaVis
  • C++11新特性_标准库_线程库_std::thread
  • 【Bootstrap V4系列】学习入门教程之 表格(Tables)和画像(Figure)
  • STM32复盘总结——芯片简介
  • 动态规划算法精解(Java实现):从入门到精通
  • Zephyr RTOS架构下的固件升级
  • MySQL数据库上篇
  • CPU:AMD的线程撕裂者(Threadripper)系列
  • 高等数学-第七版-下册 选做记录 习题10-1
  • Python爬虫实战:获取易车网最新特定车型销量数据并分析,为消费者购车做参考
  • 快速集成 Flutter Shorebird 热更新
  • Qt 中基于 QTableView + QSqlTableModel 的分页搜索与数据管理实现
  • 仙盟创梦IDE-智能编程,编程自动备份+编程审计
  • AI 驱动的智能交通系统:从拥堵到流畅的未来出行