PCL-kdTree搜索

前言

在前两篇文章中,我们搭建起了PCL的开发环境以及和QT5相结合的环境。在本篇博客将在此基础上介绍kd-tree的搜索算法。相关基础环境代码下载

1.准备

1.1 kd-tree介绍

k-d树是一种分割k维数据空间的数据结构,在PCL分为两种搜索一种是范围查询,另一种是K近邻查询
范围查询:给定查询点和查询距离的阈值,从数据集中找出所有与查询点距离小于阈值的数据,
K近邻查询:给定查询点及正整数K,从数据集中找到距离查询点最近的K个数据,当K=1时,就是最近邻查询。
具体的理论结论我们可以不用太过于清楚,只要明白PCL提供两个API接口让我们去搜索最近点的数据。

1.2 增加相关逻辑

在上文中的UI_PclViewer.h里面添加两个按钮,如下并且进行初始化:

QPushButton *kdTreeBtn;
QPushButton *kdTreeRBtn;

// 初始化kd tree 按钮
kdTreeBtn = new QPushButton(PCLView);
kdTreeBtn ->setObjectName(QString::fromUtf8("kd tree"));
kdTreeBtn ->setGeometry(QRect(50,60,120,40));

kdTreeRBtn = new QPushButton(PCLView);
kdTreeRBtn ->setObjectName(QString::fromUtf8("kd Rtree"));
kdTreeRBtn ->setGeometry(QRect(50,110,120,40));

// 添加到数据到UI界面上去
kdTreeBtn->setText(QCoreApplication::translate("PCLView","Kd Tree", nullptr));
kdTreeRBtn->setText(QCoreApplication::translate("PCLView","Kd RTree", nullptr));

添加随机生成随机点函数:

// 随机生成点云图
void UI::PclViewer::randomPoint() {
    this->pointCloud->resize(10000);
    for (int i = 0; i < pointCloud->size(); ++i) {
        this->pointCloud->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
        this->pointCloud->points[i].y = 1024* rand() /(RAND_MAX + 1.0f);
        this->pointCloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
        pointCloud->points[i].r = 255 ;
        pointCloud->points[i].g = 0 ;
        pointCloud->points[i].b = 0 ;
    }
   updatePointCloud();
}

// 更新点云图
void UI::PclViewer::updatePointCloud() {
    auto result = this->visualizer->updatePointCloud(this->pointCloud);
    if (!result) this->visualizer->addPointCloud(pointCloud);
    this->visualizer->resetCamera();
    refreshView();
}

重新QT5的按键监听函数,使之点击空格可以重置点云图坐标系。

// 重写keyReleaseEvent 释放空格键的时候,重置坐标系
void UI::PclViewer::keyReleaseEvent(QKeyEvent *event) {
    if (event->key() == Qt::Key_Space){
        visualizer->initCameraParameters();
        updatePointCloud();
    }
}

运行代码如图:
随机点

2. Kd-Tree 最近K点搜索

在给点搜索点,以这个点位中心,搜索距离给定搜索点最近的K个点。给按钮添加相应的事件,如下:

void UI::PclViewer::kdTreePressed() {
    // 声明Kd搜索对象
    pcl::KdTreeFLANN<PointT> kdTree;
    // 设置点云
    kdTree.setInputCloud(pointCloud);
    // 设置搜索点信息
    PointT searchPoint;
    searchPoint.x = 1024 * rand() / (RAND_MAX + 1.0f);
    searchPoint.y = 1024* rand() /(RAND_MAX + 1.0f);
    searchPoint.z = 1024 * rand() / (RAND_MAX + 1.0f);
    searchPoint.r = 75 ;
    searchPoint.g = 0;
    searchPoint.b = 130;

    // 设置搜索点云数量的1/10
    int K = pointCloud->size() / 10;

    // 添加搜索点到点云里面去
    pointCloud->push_back(searchPoint);

    // 设置搜索点数组
    std::vector<int> pointIdxKNSearch(K);
    std::vector<float> pointNKNSquaredDistance(K);
    
    // 进行最近临近搜索K个点
    if (kdTree.nearestKSearch (searchPoint, K, pointIdxKNSearch, pointNKNSquaredDistance) > 0){
        for (int i: pointIdxKNSearch) {
            // 修改搜索后点的颜色
            pointCloud->points[i].r = 255 ;
            pointCloud->points[i].g = 255 ;
            pointCloud->points[i].b = 255 ;
        }
    }
    // 更新点云图
    updatePointCloud();
}

在按钮点击函数之后添加上面的K-D逻辑处理。搜索K个最近点。如下图:
请添加图片描述

3 K-d tree R半径内搜索

在给点搜索点,以这个点位中心,搜索距离给定搜索点距离为R的所有点。给按钮添加相应的事件,如下:

void UI::PclViewer::kdTreeRPressed() {
    // 声明Kd搜索对象
    pcl::KdTreeFLANN<PointT> kdTree;
    // 设置点云
    kdTree.setInputCloud(pointCloud);
    // 设置搜索点信息
    PointT searchPoint;
    searchPoint.x = 1024 * rand() / (RAND_MAX + 1.0f);
    searchPoint.y = 1024* rand() /(RAND_MAX + 1.0f);
    searchPoint.z = 1024 * rand() / (RAND_MAX + 1.0f);
    searchPoint.r = 75 ;
    searchPoint.g = 0;
    searchPoint.b = 130;

    //存储近邻索引
    std::vector<int> pointIdxRadiusSearch;
    //存储近邻对应距离的平方
    std::vector<float> pointRadiusSquaredDistance;
    //半径
    float radius = .5f;
    LOG(INFO) << radius;
    if ( kdTree.radiusSearch (searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance) > 0 ){
        for (int i: pointIdxRadiusSearch) {
            // 修改搜索后点的颜色
            pointCloud->points[i].r = 72 ;
            pointCloud->points[i].g = 61 ;
            pointCloud->points[i].b = 139 ;
        }
    }
    // 更新点云图
    updatePointCloud();
}

如上以某点为搜索点为起点,R为半径进行搜索。其结果如下:
请添加图片描述

4. 总结

本文以QT5为基础,结合相应的PCL库,进行对kd-tree的搜索,下文将继续基于此进行相关的PCL学习

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

myenjoy_1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值