PCL笔记四:k-d tree和八叉树;近邻搜索;半径搜索;体素内搜索;空间变化检测;

点云数据主要是表征目标表面的海量点集合,并不具备传统实体网格数据的几何拓扑信息

点云数据处理中最为核心的问题就是建立离散点间的拓扑关系,实现基于邻域关系的快速查找

建立空间索引在点云数据处理中已被广泛应用,常见空间索引一般是自顶向下逐级划分空间的各种空间索引结构:BSP树、k-d tree、KDB树、R树、R+树、CELL树、四叉树、八叉树等。


k-d tree对于区间和近邻搜索十分有用。

PCL中k-d tree 库提供了k-d tree数据结构,基于FLANN进行快速最近邻检索最近邻检索匹配特征描述子计算领域特征提取中是非常基础的核心操作。


一:近邻搜索

  • KNN算法:用k-d tree 树找到具体点或空间位置的k近邻
  • R半径搜索:找到用户指定的某一半径内的所有近邻。

近邻搜索需要用的kdtree头文件,kdtree是依赖于FLANN实现的。

#include<iostream>
#include<vector>
#include<ctime>
#include<pcl/point_cloud.h>
#include<pcl/kdtree/kdtree_flann.h>
using namespace std;

int main()
{
	srand(time(NULL));  // 利用系统时间初始化rand()函数的种子。
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

	// 点云生成
	cloud->width = 1000;
	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.0f * rand() / (RAND_MAX + 1.0f);
		cloud->points[i].y = 1024.0f * rand() / (RAND_MAX + 1.0f);
		cloud->points[i].z = 1024.0f * rand() / (RAND_MAX + 1.0f);
	}
	pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;  // 创建一个KdTreeFLANN对象,输入点云。
	kdtree.setInputCloud(cloud);

	pcl::PointXYZ searchPoint;   // 创建一个searchPoint变量作为查询点,并且为它分配随机坐标值。
	searchPoint.x = 1024.0f * rand() / (RAND_MAX + 1.0f);
	searchPoint.y = 1024.0f * rand() / (RAND_MAX + 1.0f);
	searchPoint.z = 1024.0f * rand() / (RAND_MAX + 1.0f);

	// k近邻搜索
	int K = 10;    // 10个近邻点。
	vector<int>pointIdxNKNSearch(K);    // 存储搜索到查询点近邻的索引。
	vector<float>pointNKNSquaredDistance(K);   // 存储对应近邻的平方距离。
	cout << "K nearest neighbor search at (" << searchPoint.x << " " << searchPoint.y
		<< " " << searchPoint.z << ") with K = " << K << endl;

	// kdtree.nearestKSearch函数搜索距离索引点最近的K个点,搜到后返回搜到的点数。
	int res = kdtree.nearestKSearch(searchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance);
	cout << "nearestKSearch返回值为:" << res << endl;
	if (kdtree.nearestKSearch(searchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance) > 0)
	{
		// 打印输出。
		for (size_t i = 0; i < pointIdxNKNSearch.size(); i++)
		{
			cout << " " << cloud->points[pointIdxNKNSearch[i]].x << " " << cloud->points[pointIdxNKNSearch[i]].y
				 << " " << cloud->points[pointIdxNKNSearch[i]].z << " " << "(squared distance:"
				 << pointNKNSquaredDistance[i] << ")" << endl;
		}
	}

	cout << endl;

	// R半径搜索:在半径r内搜索近邻。
	vector<int> pointIdxRadiusSearch;  // 存储近邻索引。
	vector<float> pointRadiusSquaredDistance;   // 存储近邻对应的平均距离。
	float radius = 256.0f * rand() / (RAND_MAX + 1.0f);
	cout << "Neighbors within radius search at (" << searchPoint.x << " " << searchPoint.y << " " << searchPoint.z
		 << ") with radius=" << radius << endl;
	int b = kdtree.radiusSearch(searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance);
	cout << "R半径搜索方法:kdtree.radiusSearch返回值为:" << b << endl;
	if (b > 0)
	{
		for (size_t i = 0; i < pointIdxRadiusSearch.size(); i++)
		{
			cout << " " << cloud->points[pointIdxRadiusSearch[i]].x << " "
				<< cloud->points[pointIdxRadiusSearch[i]].y << " "
				<< cloud->points[pointIdxRadiusSearch[i]].z << " "
				<< "(squared distance: " << pointRadiusSquaredDistance[i] << ")" &
### PCL 中基于八叉树空间变化检测 PCL(Point Cloud Library)提供了 `OCTree_OctreePointCloudChangeDetector` 类来实现点云之间的空间变化检测。该功能的核心在于利用八叉树结构对点云数据进行分层划分,并通过比较不同时间戳下的点云分布情况,识别新增或移除的。 #### 构建 CMake 工程 为了使用 PCL八叉树模块,需配置 CMake 文件以支持编译环境。以下是标准的 CMake 配置文件示例[^2]: ```cmake cmake_minimum_required(VERSION 3.5 FATAL_ERROR) project(octree_change_detection) find_package(PCL 1.2 REQUIRED) include_directories(${PCL_INCLUDE_DIRS}) link_directories(${PCL_LIBRARY_DIRS}) add_definitions(${PCL_DEFINITIONS}) add_executable(octree_change_detection octree_change_detection.cpp) target_link_libraries(octree_change_detection ${PCL_LIBRARIES}) ``` 此配置确保项目能够正确链接到 PCL 库并加载必要的头文件定义。 --- #### 八叉树初始化与设置参数 在实际应用中,可以通过以下方式创建并初始化八叉树对象: ```cpp #include <pcl/point_cloud.h> #include <pcl/octree/octree_pointcloud_changedetector.h> // 定义点类型 typedef pcl::PointXYZ PointT; int main() { // 创建点云实例 pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>); // 设置分辨率(即每个的边长) double resolution = 0.1; // 初始化八叉树对象 pcl::octree::OctreePointCloudChangeDetector<PointT> octree(resolution); } ``` 上述代码片段展示了如何指定八叉树的分辨率以及初始化过程[^1]。 --- #### 添加点云八叉树 将初始点云添加到八叉树中以便后续对比操作: ```cpp // 将点云插入到八叉树 octree.setInputCloud(cloud); octree.addPointsFromInputCloud(); // 更新当前状态作为参考帧 octree.switchBuffers(); ``` 这里的关键步骤是调用 `switchBuffers()` 方法保存当前点云的状态,从而允许未来的新点云与其进行差异分析。 --- #### 对比新旧点云 当有新的点云到达时,可以将其加入同一棵八叉树并与之前的记录做对比: ```cpp // 假设 new_cloud 是更新后的点云pcl::PointCloud<PointT>::Ptr new_cloud(new pcl::PointCloud<PointT>()); new_cloud->points.push_back(PointT(x, y, z)); // 示例点坐标填充逻辑省略 // 清空现有缓存并将新点集载入 octree.setInputCloud(new_cloud); octree.addPointsFromInputCloud(); // 获取发生变化的位置集合 std::vector<int> added_indices; std::vector<int> removed_indices; octree.getAddedPointsIndices(added_indices); // 新增点索引列表 octree.getDeletedPointsIndices(removed_indices); // 移除点索引列表 ``` 以上部分实现了动态监测场景中的物移动或消失现象的功能。 --- #### 可选扩展:查询特定区域信息 如果需要进一步探索某一的具属性,则可通过如下接口完成: - **检查某个位置是否有对应存在** - **获取整棵树的最大深度** - **提取任意选定中心的世界坐标** 这些辅助工具均已在官方文档第六章节有所描述。 --- ### 总结 综上所述,借助于 PCL 提供的强大 API 支持,开发者仅需少量代码即可高效达成复杂任务目标——实时追踪三维环境中发生的细微变动状况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值