• PCL入门(四):kdtree简单介绍和使用


    参考博客《欧式聚类(KD-Tree)详解,保姆级教程》《(三分钟)学会kd-tree 激光SLAM点云搜索常见》

    1. kd树的意义
    • kd树是什么?

    kd树是一种空间划分的数据结构,对于多个维度的数据,按照某种规则选定某个维度,在该维度下进行排序,选择中间的数据作为划分节点,然后分别对划分节点左边和右边的数据进行上面的划分步骤。

    • 为什么需要kd树?

    三维点云的数据量较大,使用kd树进行搜索可以减少时间,可以确保点云的关联点寻找和匹配处于实时状态。总而言之,就是利用kd树,可以实现点云数据的快速搜索。

    2. kd树的使用

    使用kd树一般有两个任务,分别是k近邻搜索和半径内搜索。代码实现主要参考双愚的代码

    #include 
    #include 
    #include 
    #include 
    #include 
    
    int main(int argc, char** argv)
    {
    	srand(time(NULL));
    	//第一步:生成点云
    	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
    	cloud->width = 100;
    	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::PointXYZ 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);
    	
    	//第三步:定义kd树
    	pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;
    	kdtree.setInputCloud(cloud); //将点云cloud作为输入
    	
    	//第四步:采用kdtree.nearestKSearch方法,输出点searchPoint的最近10个点云
    	int K = 10;
    	std::cout << "K nearest neighbor search at (" << searchPoint.x 
                << " " << searchPoint.y 
                << " " << searchPoint.z
                << ") with K=" << K << std::endl;
    	std::vector<int> pointIdxNKNSearch(K);
    	std::vector<float> pointNKNSquaredDistance(K);
    	if (kdtree.nearestKSearch(searchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance) > 0)
    	{
    		for (size_t i=0; i<pointIdxNKNSearch.size(); ++i)
    		{
    			std::cout << "    "  <<   cloud->points[ pointIdxNKNSearch[i] ].x 
                    	<< " " << cloud->points[ pointIdxNKNSearch[i] ].y 
                    	<< " " << cloud->points[ pointIdxNKNSearch[i] ].z 
                    	<< " (squared distance: " << pointNKNSquaredDistance[i] << ")" << std::endl;
    		}
    	}
    	
    	//第五步:采用kdtree.radiusSearch方法,输出点searchPoint的给定半径距离内的其他点
    	float radius = 256.0f * rand() / (RAND_MAX + 1.0f);
    	std::cout << "Neighbors within radius search at (" << searchPoint.x 
                << " " << searchPoint.y 
                << " " << searchPoint.z
                << ") with radius=" << radius << std::endl;
            std::vector<int> pointIdxRadiusSearch;
            std::vector<float> pointRadiusSquaredDistance;
            if (kdtree.radiusSearch(searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance) > 0)
            {
            	for (size_t i = 0; i < pointIdxRadiusSearch.size (); ++i)
            	{
            		std::cout << "    "  <<   cloud->points[ pointIdxRadiusSearch[i] ].x 
    		        << " " << cloud->points[ pointIdxRadiusSearch[i] ].y 
    		        << " " << cloud->points[ pointIdxRadiusSearch[i] ].z 
    		        << " (squared distance: " << pointRadiusSquaredDistance[i] << ")" << std::endl;
            	}
            }
            
            return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • CMakeLists.txt
    cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
    
    project(kdtree_search)
    
    find_package(PCL)
    
    add_executable(kdtree_search kdtree_search.cpp)
    target_link_libraries(kdtree_search ${PCL_LIBRARIES})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 运行结果
      在这里插入图片描述
  • 相关阅读:
    『忘了再学』Shell基础 — 7、Bash基本功能(多命令顺序执行)
    【学习总结】激光雷达与相机外参标定:原理与代码
    Maven基础概念【仓库和坐标】这篇看完懂了
    python之列表介绍
    Aardio 第一天:使用虚表和适配器
    linux限权
    javaee springMVC session的使用
    flink的KeyedBroadcastProcessFunction测试
    医院药品管理系统丨医药商城系统(Java+Web+MySQL)
    多输入多输出 | MATLAB实现CNN-BiGRU-Attention卷积神经网络-双向门控循环单元结合SE注意力机制的多输入多输出预测
  • 原文地址:https://blog.csdn.net/qq_30841655/article/details/132758556