【点云处理】点云法向量估计及其加速(5)-创新互联

  在上一篇文章【点云处理】点云法向量估计及其加速(4)中我们尝试对pcl自带的KDTree的k近邻搜索过程使用OpenMP加速,效果比较明显,有将近1倍的提速。在这篇文章中我们暂时放弃pcl自带的KDTree,转而使用另一大杀器nanflann库提供的KDTree。nanoflann是一个c++11标准库,用于构建具有不同拓扑(R2,R3(点云),SO(2)和SO(3)(2D和3D旋转组))的KD树。nanoflann 算法对fastann进行了改进,效率以及内存使用等方面都进行了优化,而且代码十分轻量级且开源。nanoflann不需要编译或安装,你只需要在你的代码中加入#include即可方便快捷地使用它。好了,下面使用nanoflann对我们的代码进行改写。

创新互联公司是一家集网站建设,华州企业网站建设,华州品牌网站建设,网站定制,华州网站建设报价,网络营销,网络优化,华州网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。
#include#include#include#include#include#include#include#include#include#include#include#include "KDTreeTableAdaptor.h"

int main(int argc, char** argv) {
    ros::init(argc, argv, "n_lidar_gpu_normal");
    ros::NodeHandle node;
    pcl::PointCloud::Ptr cloud(new pcl::PointCloud);
 
    const boost::function&)>callback =[&](sensor_msgs::PointCloud2::ConstPtr msg_pc_ptr) {
        pcl::fromROSMsg(*msg_pc_ptr, *cloud);
        size_t cloud_size = cloud->size();
        int dim=3,k=10; 
        float* points = new float[cloud_size*dim];
        for (int i=0; ipoints[i].x;
            p[1] = cloud->points[i].y;
            p[2] = cloud->points[i].z;
        }

        auto t1 = std::chrono::steady_clock::now();
        KDTreeTableAdaptorkdtree(cloud_size, dim, points, 64);
        kdtree.index->buildIndex();        
std::vector>neighbors_all(cloud_size,std::vector(k));
        std::vectorsizes(cloud_size,k);

        for (int i=0; iout_ids(k);
            std::vectorout_dists_sqr(k);
            nanoflann::KNNResultSetresult_set(k);
            result_set.init(&out_ids[0], &out_dists_sqr[0]);
            kdtree.index->findNeighbors(result_set, &points[i*dim], nanoflann::SearchParams(k));
            for (int j=0; jflatten_neighbors_all(k * cloud_size);
        pcl::gpu::PtrStepps(&flatten_neighbors_all[0], k * pcl::gpu::PtrStep::elem_size);
	    for (size_t i=0; ipoints);
        gpu_neighbor_indices.upload(flatten_neighbors_all, sizes, k);
 
        pcl::gpu::NormalEstimation::Normals gpu_normals;
	    pcl::gpu::NormalEstimation::computeNormals(gpu_cloud, gpu_neighbor_indices, gpu_normals);
	    pcl::gpu::NormalEstimation::flipNormalTowardsViewpoint(gpu_cloud, 0.f, 0.f, 0.f, gpu_normals);
        auto t3 = std::chrono::steady_clock::now();
        auto compute_normal_time = std::chrono::duration(t3 - t2);
 
	    std::vectornormals;
	    gpu_normals.download(normals);
        auto t4 = std::chrono::steady_clock::now();
        
        auto knn_time = std::chrono::duration(t2-t1);
        auto total_time = std::chrono::duration(t4-t1);
        spdlog::info("cloud size:{:d}, knn_time:{:.3f} ms,compute_normal_time:{:.3f} ms, total_time:{:.3f} ms", cloud->size(), knn_time.count(), compute_normal_time.count(), total_time.count());
    };
    ros::Subscriber pc_sub = node.subscribe("/BackLidar/lslidar_point_cloud", 1, callback);
    ros::spin();
    return 0;
}

对于for循环遍历查找k近邻索引部分我们先不加"# pragma omp parallel for",编译运行。

哇,加速效果明显,8w点云knn时间从400ms降到150ms左右。比pcl自带KDTree使用上OpenMP并行加速还要快。

要是能利用OpenMP做并行加速,岂不是要起飞??!!加上OpenMP加速试一试。

# pragma omp parallel for
        for (int i=0; iout_ids(k);
            std::vectorout_dists_sqr(k);
            nanoflann::KNNResultSetresult_set(k);
            result_set.init(&out_ids[0], &out_dists_sqr[0]);
            kdtree.index->findNeighbors(result_set, &points[i*dim], nanoflann::SearchParams(k));
            for (int j=0; j

编译运行,测试结果如下:

哇,虽然有波动,但常能在50ms左右徘徊,相比曾几何时的400ms提速了8倍。 多核算力分配也很均衡,完美!

所以,knn加速哪家强,nanoflann+OpenMP当称王!!!

【参考文献】

在C++中使用openmp进行多线程编程_线上幽灵的博客-博客_c++ omp

PCL GPU实现计算法线和曲率 - 知乎

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


网页名称:【点云处理】点云法向量估计及其加速(5)-创新互联
文章路径:http://cdiso.cn/article/cegiec.html