【点云处理】点云法向量估计及其加速(2)

在上一篇文章【点云处理】点云法向量估计及其加速(1) 中我们为点云表面法线计算作了理论铺垫,从这一篇开始结合示例代码实际体验点云法线的计算过程,以及在加速方面进行一些尝试。

使用PCL自带NormalEstimation类计算点云法线

        pcl自带NormalEstimation的计算过程如下:

对点云P中的每个点p
  1.计算p点的最近邻K个元素;
  2.计算p点的表面法线n;
  3.检查n的方向是否一致指向视点,如果不是则翻转;

【示例代码】

#include <time.h>
#include <cmath>
#include <functional>
#include <ros/ros.h>
#include <sensor_msgs/PointCloud2.h>
#include <pcl/console/time.h>
#include <pcl/kdtree/kdtree.h>
#include <pcl/features/normal_3d_omp.h>        
#include <pcl_conversions/pcl_conversions.h>

int main(int argc, char** argv) {
    ros::init(argc, argv, "n_lidar_normal");
    ros::NodeHandle node;
    pcl::NormalEstimation<pcl::PointXYZ,pcl::Normal> normal_est;
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

    const boost::function<void (const boost::shared_ptr<sensor_msgs::PointCloud2 const>&)> callback =[&](sensor_msgs::PointCloud2::ConstPtr msg_pc_ptr) {
        pcl::fromROSMsg(*msg_pc_ptr, *cloud);
        typename pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree_ptr(new pcl::search::KdTree<pcl::PointXYZ>);
        pcl::PointCloud<pcl::Normal>::Ptr normal_ptr(new pcl::PointCloud<pcl::Normal>);
        
        clock_t t1,t2;
        t1 = clock();

        normal_est.setInputCloud(cloud);
        normal_est.setSearchMethod(kdtree_ptr);
        normal_est.setViewPoint(0,0,0);
        normal_est.setKSearch(10); //neighbour size
        normal_est.compute(*normal_ptr);
        t2 = clock();
        auto cost_time = (float)((t2-t1)*1000/CLOCKS_PER_SEC);
        printf("cloud size:%zu, cost time:%.2f ms\n", cloud->size(), cost_time);
    };
    ros::Subscriber pc_sub = node.subscribe<sensor_msgs::PointCloud2>("/BackLidar/lslidar_point_cloud", 1, callback);
    ros::spin();
    return 0;
}

【运行结果】

        以上示例代码中设置k近邻的大小为10, 运行结果如下。单帧点云的计算时间几乎都超过了1000ms,效率较低。所有计算集中在一个cpu核上,造成该核负载过高。

cloud size:23749, cost time:1348.00 ms
cloud size:26791, cost time:1494.00 ms
cloud size:17848, cost time:995.00 ms
cloud size:43233, cost time:2457.00 ms
cloud size:32185, cost time:1814.00 ms
cloud size:46526, cost time:2638.00 ms
cloud size:26791, cost time:1518.00 ms
cloud size:17848, cost time:996.00 ms
cloud size:43233, cost time:2470.00 ms
cloud size:56268, cost time:3229.00 ms
cloud size:36209, cost time:2043.00 ms

使用OpenMP加速法线估计

        pcl提供了一个点云表面法线的附加实现程序,它使用多核/多线程开发规范,利用OpenMP来提高计算速度。它的类名为pcl::NormalEstimationOMP,其接口100%兼容单线程的pcl::NormalEstimation。我们姑且一尝试一下。

【示例代码】

#include <time.h>
#include <cmath>
#include <functional>
#include <ros/ros.h>
#include <sensor_msgs/PointCloud2.h>
#include <pcl/console/time.h>
#include <pcl/kdtree/kdtree.h>
#include <pcl/features/normal_3d_omp.h>
#include <pcl_conversions/pcl_conversions.h>

int main(int argc, char** argv) {
    ros::init(argc, argv, "n_lidar_openmp_normal");
    ros::NodeHandle node;
    pcl::NormalEstimationOMP<pcl::PointXYZ,pcl::Normal> normal_est;
    normal_est.setNumberOfThreads(8);                                                   //设置OpenMP线程数
    normal_est.setViewPoint(0,0,0);                                                     //设置视点,默认就是(0,0,0)
    normal_est.setKSearch(10);                                                          //设置K近邻大小

    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

    const boost::function<void (const boost::shared_ptr<sensor_msgs::PointCloud2 const>&)> callback =[&](sensor_msgs::PointCloud2::ConstPtr msg_pc_ptr) {
        pcl::fromROSMsg(*msg_pc_ptr, *cloud);
        typename pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree_ptr(new pcl::search::KdTree<pcl::PointXYZ>);
        pcl::PointCloud<pcl::Normal>::Ptr normal_ptr(new pcl::PointCloud<pcl::Normal>);
        
        clock_t t1,t2;
        t1 = clock();

        normal_est.setInputCloud(cloud);
        normal_est.setSearchMethod(kdtree_ptr);
        normal_est.compute(*normal_ptr);
        t2 = clock();
        auto cost_time = (float)((t2-t1)*1000/CLOCKS_PER_SEC);
        printf("cloud size:%zu, cost time:%.2f ms\n", cloud->size(), cost_time);
    };
    ros::Subscriber pc_sub = node.subscribe<sensor_msgs::PointCloud2>("/BackLidar/lslidar_point_cloud", 1, callback);
    ros::spin();
    return 0;
}

【运行结果】

cloud size:34365, cost time:2043.00 ms
cloud size:17848, cost time:1125.00 ms
cloud size:21231, cost time:1285.00 ms
cloud size:32271, cost time:1956.00 ms
cloud size:46526, cost time:2723.00 ms
cloud size:43233, cost time:2541.00 ms
cloud size:19196, cost time:1156.00 ms
cloud size:20268, cost time:1254.00 ms
cloud size:20216, cost time:1258.00 ms
cloud size:47956, cost time:2834.00 ms
cloud size:19737, cost time:1246.00 ms

 多核确实被利用起来了,但是单帧处理速度并没有明显的提速。问题出在哪里?

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
点云向量重定向是指通过CGAL(Computational Geometry Algorithms Library)库中的算点云数据中的向量进行重新定向的过程。 在计算机图形学和计算几何学中,向量是表征一个平面、曲面或物体表面在某一点上垂直于该表面的向量。在点云数据中,每个点都有一个向量。但有时候,在某些应用中需要对向量进行重定向,以使它们在整个点云中更加一致和连续。 CGAL库为点云向量重定向提供了一些有用的算。其中一个重要的算法线初始估计,它可以估计点云中每个点的初始向量。该算使用了一些几何特征的计算方,例如曲率估计法线方向的一致性。 另一个重要的算法线重定向算。该算的目标是通过考虑点云的拓扑关系,使得点云中的向量更加一致和连续。法线重定向算使用了一种基于曲面平滑的优化方,通过最小化向量之间的角度差异来调整每个点的向量。 使用CGAL库进行点云向量重定向需要先将点云数据加载到CGAL的数据结构中,例如点云网格或点云三角化。然后,可以调用库中的函数来执行法线初始估计法线重定向算。 通过点云向量重定向,可以使得点云中的向量更加一致,从而提高了许多点云处理任务的效果,例如表面重建、模型拟合和物体识别等。 总而言之,CGAL库提供了一些有效的算来对点云数据中的向量进行重定向。通过这些算,可以使得点云中的向量更加一致和连续,提高了点云处理任务的效果和精度。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值