Ubuntu 18.04.06 PCL C++学习记录(五)

@[TOC]PCL中K-Dtree模块的学习

学习背景

参考书籍:《点云库PCL从入门到精通》以及官方代码PCL官方代码链接,PCL版本为1.8.1,CMake版本为3.10.2

学习内容

使用PCL库进行点云数据的八叉树搜索,包括体素近邻搜索、K近邻搜索和半径内近邻搜索

源代码及所用函数

源代码

#include<iostream>//C++标准输入输出流
#include<vector>//容器
#include<ctime>//时间相关函数和类型的头文件
#include<pcl/point_cloud.h>//点云类定义头文件
#include<pcl/octree/octree_search.h>//定义了八叉树数据结构和相关的搜索操作。

int main()
{
    srand((unsigned)time(NULL));初始化随机数生成器的种子,注意只需执行一次
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    //给点云赋值
    cloud->width=1000;//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);
    }
    float Resolution = 128.0f;
    pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> Octree(Resolution);//初始化八叉树
    Octree.setInputCloud(cloud);//设置输入点云
    Octree.addPointsFromInputCloud();//构建八叉树

    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);

    std::vector<int> PointIdxVec;//存储体素近邻搜索
    if (Octree.voxelSearch(SearchPoint,PointIdxVec))
    {
        std::cout<<"搜索体素内的邻域("<<SearchPoint.x<<"  "<<SearchPoint.y <<"  "<<SearchPoint.z << ")"<<std::endl;
        for (size_t i = 0; i < PointIdxVec.size(); i++)//打印搜索结果坐标
        {
            std::cout<<"  "<<cloud->points[PointIdxVec[i]].x<<"  "<<cloud->points[PointIdxVec[i]].y<<"  "<<cloud->points[PointIdxVec[i]].z<<std::endl;
        }
        
    }
    //K邻近搜索
    int K =10;
    std::vector<int> PointTdxNKNSearch;//存储K邻近搜索点结果
    std::vector<float> PointNKNSquareDistence;//存储搜索点和近邻之间的平方距离
    std::cout<< "K邻近搜索点(" <<SearchPoint.x <<"  "<<SearchPoint.y<<"  "<<SearchPoint.z<<" ) with K ="<< K <<std::endl;
    if(Octree.nearestKSearch(SearchPoint,K,PointTdxNKNSearch,PointNKNSquareDistence)>0)
    {
        for (size_t i = 0; i < PointTdxNKNSearch.size(); i++)//打印搜索结果坐标
        {
            std::cout <<"  "<<cloud->points[PointTdxNKNSearch[i]].x<< " " <<cloud->points[PointTdxNKNSearch[i]].y<<"  "<<cloud->points[PointTdxNKNSearch[i]].z<<"(平方距离:" << PointNKNSquareDistence[i] <<")"<<std::endl;

        }

        
    }
    //半径内近邻搜索
    std::vector<int> PointIdxRadiusSearch;
    std::vector<float> PointRadiusSquaredDistance;
    float Radius = 256.0f*rand()/(RAND_MAX +1.0f);
    std::cout<< "半径内搜索点(" <<SearchPoint.x <<"  "<<SearchPoint.y<<"  "<<SearchPoint.z<<" ) 以及半径 ="<< Radius <<std::endl;
    if (Octree.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<<"(平方距离:"<<PointRadiusSquaredDistance[i]<<")"<<std::endl;
        }
        
    }
    
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.1 FATAL_ERROR)#指定CMake的最低版本要求为3.1
project(octree_search)#设置项目名称
set(CMAKE_CXX_STANDARD 11)#设置C++编译器版本为C++11
find_package(PCL 1.7 REQUIRED)#查找PCL库,要求版本为1.7或更高。
include_directories(${PCL_INCLUDE_DIRS})#将PCL库的头文件目录添加到包含路径中
link_directories(${PCL_LIBRARY_DIRS})#将PCL库的库文件目录添加到链接器搜索路径中。
add_definitions(${PCL_DEFINITIONS})#添加PCL库的编译器定义
add_executable (octree_search octree_search.cpp)#需要修改
target_link_libraries (octree_search ${PCL_LIBRARIES})#将PCL库链接到可执行文件目标。

结果

在这里插入图片描述

函数

  • pcl::octree::OctreePointCloudSearch<pcl::PointXYZ>这是一个模板类,表示用于搜索的八叉树。
pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> Octree(Resolution);//初始化八叉树
//Resolution是一个浮点数,表示八叉树的分辨率或体素大小。它决定了八叉树如何划分三维空间。
//较小的分辨率值会导致更细粒度的空间划分,八叉树的深度会更大,占用更多内存,但搜索更精确。较大的分辨率值会导致更粗粒度的空间划分,八叉树的深度会更小,占用更少内存,但搜索可能不够精确。

这个类包含以下方法
方法一
八叉树体素搜索,体素搜索是指在八叉树中查找包含给定搜索点的体素,并返回该体素内的所有点的索引。

void setInputCloud(const PointCloudConstPtr &cloud, const IndicesConstPtr &indices = IndicesConstPtr())
//cloud:一个指向输入点云对象的常量共享指针(PointCloudConstPtr)。它表示要与八叉树关联的点云数据。
//indices:一个指向点云索引的常量共享指针(IndicesConstPtr),默认为空指针。如果提供了索引,则只有指定索引的点会被添加到八叉树中。如果为空指针,则整个点云都会被添加到八叉树中。

在该函数结束之后需要使用

void addPointsFromInputCloud()

来构建八叉树。如果修改了输入点云的数据,则需要重新调用 setInputCloud 并重建八叉树,以确保搜索结果的正确性。
方法二

voxelSearchOctreePointCloudSearch类的一个成员函数,用于在八叉树中执行体素搜索。体素搜索是指在八叉树中查找包含给定搜索点的体素,并返回该体素内的所有点的索引。如果搜索成功,即找到了包含目标点的体素,则返回true;否则返回false。

bool voxelSearch(const PointT &point, std::vector<int> &point_idx)
// point:要搜索的目标点,类型为PointT(与创建八叉树时指定的点类型相同)。
//point_idx:一个整数向量的引用,用于存储搜索结果,即包含目标点的体素内的所有点的索引。

方法三
八叉树K近邻搜索,K近邻搜索是指在点云中查找与给定搜索点最近的K个点,并返回这些点的索引以及它们与搜索点之间的平方距离。

int nearestKSearch(const PointT &point, int k, std::vector<int> &k_indices, std::vector<float> &k_sqr_distances) const
//point:要搜索的目标点,类型为PointT(与创建八叉树时指定的点类型相同)。
//k:要查找的最近邻点的数量,即K值。
//k_indices:一个整数向量的引用,用于存储搜索结果,即最近邻点的索引。
//k_sqr_distances:一个浮点数向量的引用,用于存储搜索结果,即最近邻点与目标点之间的平方距离。

方法四
八叉树半径搜索,半径搜索是指在点云中查找与给定搜索点距离小于等于指定半径的所有点,并返回这些点的索引以及它们与搜索点之间的平方距离

int radiusSearch(const PointT &point, double radius, std::vector<int> &k_indices, std::vector<float> &k_sqr_distances, unsigned int max_nn = 0) const
//point:要搜索的目标点,类型为PointT(与创建八叉树时指定的点类型相同)。
//radius:搜索半径,表示以目标点为中心的球体半径。
//k_indices:一个整数向量的引用,用于存储搜索结果,即落在搜索半径内的点的索引。
//k_sqr_distances:一个浮点数向量的引用,用于存储搜索结果,即落在搜索半径内的点与目标点之间的平方距离。
//max_nn:最大近邻点数量的上限,默认为0,表示没有上限。如果指定了上限,则搜索结果中的点数量不会超过该值。

补充

  • 体素(Voxel)是三维空间中的一个立方体单元或体元素。它是"体积元素"(Volume Element)的缩写。在三维空间中,像素(Pixel)是二维图像的基本单元,而体素则是三维数据(如点云、体数据等)的基本单元。体素可以看作是三维空间中的一个立方体小块,用于表示和存储该空间中的数据值。在八叉树(Octree)数据结构中,每个节点对应一个体素,用于组织和索引该区域内的点云数据。通过递归地将空间划分为八个子体素,八叉树可以高效地表示和搜索三维点云数据。体素的大小(分辨率)是一个重要参数,它决定了空间细节的分辨率。较大的体素尺寸可以减少内存占用和计算开销,但会损失细节;而较小的体素尺寸则能保留更多细节,但代价是更大的内存和计算开销。因此,在实际应用中需要根据具体需求选择合适的体素大小。
  • 15
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值