pcl::KdTreeFLANN对象radiusSearch和nearestKSearch接口的性能分析

测试demo(其中所用点云分辨率大致为0.02m, 点数2374612)
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <time.h>

using namespace std;

using PointT = pcl::PointXYZRGB;
using CloudT = pcl::PointCloud<PointT>;

int main (int argc, char** argv)
{
    if (argc != 2){
        cout<<"please appoint *.pcd file !!!"<<endl;
        return false;
    }

    // generate cloud
    CloudT::Ptr cloud(new CloudT);
    if (pcl::io::loadPCDFile(argv[1], *cloud) == -1){
        cout<<"cant load file : "<<argv[1]<<" !!!"<<endl;
        return 0;
    }
    CloudT::Ptr dev_cloud(new CloudT);
    dev_cloud->reserve(cloud->points.size());
    for (const auto& p : cloud->points)
    {
        PointT tp = p;
        tp.x += 5.0;
        tp.y += 5.0;
        tp.z += 5.0;
        dev_cloud->push_back( move(tp) );
    }

    /// test large overlap cloud (source and target is same) /
    /* demo0 */
    vector<float> diss;
    vector<int> indexs;
    pcl::KdTreeFLANN<PointT> kdtree;
    kdtree.setInputCloud(cloud);
    time_t t0 = clock();
    for (const auto& p : cloud->points){
        if (kdtree.nearestKSearch(p, 10, indexs, diss)){}
    }
    time_t t1 = clock();
    cout<<"nnk 10 points cost time "<<(t1-t0)/1000<<"[ms]"<<" in large overlap"<<endl;

    /* demo1 */
    time_t t2 = clock();
    int total_num = 0;
    for (const auto& p : cloud->points){
        if (kdtree.radiusSearch(p, 0.2, indexs, diss) > 0){
            total_num += indexs.size();
        }
    }
    int avg_num = total_num / cloud->points.size();
    time_t t3 = clock();
    cout<<"rnk 0.2cm cost time "<<(t3-t2)/1000<<"[ms]"<<" in large overlap, average searched points num "<<avg_num<<endl;

     test small overlap /
    /* demo2 */
    time_t t00 = clock();
    for (const auto& p : dev_cloud->points){
        if (kdtree.nearestKSearch(p, 10, indexs, diss)){}
    }
    time_t t11 = clock();
    cout<<"nnk 10 points cost time "<<(t11-t00)/1000<<"[ms]"<<" in small overlap"<<endl;

    /* demo3 */
    time_t t22 = clock();
    total_num = 0;
    for (const auto& p : dev_cloud->points){
        if (kdtree.radiusSearch(p, 0.2, indexs, diss) > 0){
            total_num += indexs.size();
        }
    }
    avg_num = total_num / cloud->points.size();
    time_t t33 = clock();
    cout<<"rnk 0.2cm cost time "<<(t33-t22)/1000<<"[ms]"<<" in small overlap, average searched points num "<<avg_num<<endl;

    return 0;
}

结果

nnk 10 points cost time 5963[ms] in large overlap
rnk 0.2cm cost time 66336[ms] in large overlap, average searched points num 477
nnk 10 points cost time 155772[ms] in small overlap
rnk 0.2cm cost time 5535[ms] in small overlap, average searched points num 6
分析:

从demo0和demo1的结果来看,在原点云和目标点云重叠区域较大的情况下,使用nearestKSearch性能更有优势,而radiusSearch性能较差,较差的原因是平均搜索点数达到了477个点,而nearestKSearch只搜索了10个点,如果限制搜索半径,搜索点数下降,radiusSearch接口的性能也会得到明显提升;
从demo2和demo3的结果来看,在原点云和目标点云重叠区域较小的情况下,使用radiusSearch性能更有优势,而nearestKSearch性能较差.但搜索点数并没有太大差异,那原因是什么呢? 从kdtree中可以发现原因,其中有说道Degradation in performance when the query point is far from points in the k-d tree,可见,当重叠区域较小时,原点云中的搜索点到目标点的距离都较远,从而出现退化问题,导致性能下降(有过icp使用经验的人应该都知道一个问题,当原点云与目标点云重叠区域较小时,icp的运行时间会大幅上升,原因就是因为pcl的icp对象使用的是nearestKSearch接口寻找最近邻,出现退化问题,导致搜索时间大幅上升).而radiusSearch接口就不存在这样的问题,因为一般的半径设置都会比较小,所以当目标点到搜索点距离较远时,直接会被丢弃,没有深入搜索其它的最近邻点,从而性能较好.

结论:

1. 当原点云与目标点云重叠区域较大时,优先选择nearestKSearch接口来寻找最近邻,如果点云较稀疏,并且搜索半径较小,也可以使用radiusSearch接口来寻找最近邻
2. 当原点云与目标点云重叠区域较小时,优先选择radiusSearch接口来寻找最近邻,避免退化问题

  • 14
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值