使用PCL库中PPF+ICP进行点云目标识别

这篇具有很好参考价值的文章主要介绍了使用PCL库中PPF+ICP进行点云目标识别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

#include <pcl/features/normal_3d.h>
#include <pcl/features/ppf.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/io/pcd_io.h>
#include <pcl/registration/ppf_registration.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <thread>
#include <pcl/registration/icp.h>

using namespace pcl;
using namespace std::chrono_literals;

const Eigen::Vector4f subsampling_leaf_size(1.5f,1.5f, 1.5f, 0.0f);//下采样立方体大小
constexpr float normal_estimation_search_radius = 5.0f;//法线计算搜索半径


int
main(int argc, char** argv)
{
    /// 读取点云文件
    PointCloud<PointXYZ>::Ptr cloud_scene(new PointCloud<PointXYZ>());
    if (pcl::io::loadPCDFile("screws_M8_40_ronghe.pcd", *cloud_scene) < 0)
    {
        std::cout << "Error loading scene cloud." << std::endl;
        return (-1);
    }
    else
    {
        cout << "cloud_scene 读取成功" << endl;
    }
   
    PointCloud<PointXYZ>::Ptr cloud_model(new PointCloud<PointXYZ>());
    if (pcl::io::loadPCDFile("screws_M8_40.pcd", *cloud_model) < 0)
    {
        std::cout << "Error loading model cloud." << std::endl;
        return (-1);
    }
    else
    {
        cout << "cloud_model 读取成功" << endl;
    }

    //背景部分处理
    PointCloud<PointNormal>::Ptr cloud_scene_input(new PointCloud<PointNormal>());
    PointCloud<PointXYZ>::Ptr cloud_scene_subsampled(new PointCloud<PointXYZ>());
    //下采样滤波
    VoxelGrid<PointXYZ> subsampling_filter;
    subsampling_filter.setInputCloud(cloud_scene);
    subsampling_filter.setLeafSize(subsampling_leaf_size);
    subsampling_filter.filter(*cloud_scene_subsampled);
    //计算背景法线
    PointCloud<Normal>::Ptr cloud_scene_normals(new PointCloud<Normal>());
    NormalEstimation<PointXYZ, Normal> normal_estimation_filter;
    normal_estimation_filter.setInputCloud(cloud_scene_subsampled);
    search::KdTree<PointXYZ>::Ptr search_tree(new search::KdTree<PointXYZ>);
    normal_estimation_filter.setSearchMethod(search_tree);
    normal_estimation_filter.setRadiusSearch(normal_estimation_search_radius);
    normal_estimation_filter.compute(*cloud_scene_normals);
    pcl::concatenateFields(*cloud_scene_subsampled, *cloud_scene_normals, *cloud_scene_input);
    cout << cloud_scene->size() << " down to" << cloud_scene_subsampled->size() << endl;
    //模型部分处理
    PointCloud<PointNormal>::Ptr cloud_model_input(new PointCloud<PointNormal>());
    PointCloud<PointXYZ>::Ptr cloud_model_subsampled(new PointCloud<PointXYZ>());
    //下采样滤波
    VoxelGrid<PointXYZ> subsampling_filter2;
    subsampling_filter2.setInputCloud(cloud_model);
    subsampling_filter2.setLeafSize(subsampling_leaf_size);
    subsampling_filter2.filter(*cloud_model_subsampled);
    //计算背景法线
    PointCloud<Normal>::Ptr cloud_model_normals(new PointCloud<Normal>());
    NormalEstimation<PointXYZ, Normal> normal_estimation_filter2;
    normal_estimation_filter2.setInputCloud(cloud_model_subsampled);
    search::KdTree<PointXYZ>::Ptr search_tree2(new search::KdTree<PointXYZ>);
    normal_estimation_filter2.setSearchMethod(search_tree2);
    normal_estimation_filter2.setRadiusSearch(normal_estimation_search_radius);
    normal_estimation_filter2.compute(*cloud_model_normals);
    pcl::concatenateFields(*cloud_model_subsampled, *cloud_model_normals, *cloud_model_input);

    cout << cloud_model->size() << " down to" << cloud_model_subsampled->size() << endl;

   // pcl::PointCloud<pcl::PPFSignature>::Ptr cloud_model_ppf = pcl::PointCloud<pcl::PPFSignature>::Ptr(new pcl::PointCloud<pcl::PPFSignature>());
    PointCloud<PPFSignature>::Ptr cloud_model_ppf(new PointCloud<PPFSignature>());
    PPFEstimation<PointNormal, PointNormal, PPFSignature> ppf_estimator;
    ppf_estimator.setInputCloud(cloud_model_input);
    ppf_estimator.setInputNormals(cloud_model_input);
    ppf_estimator.compute(*cloud_model_ppf);//之前一直出现指针报错???,加多维向量AGX后解决
    PPFHashMapSearch::Ptr hashmap_search(new PPFHashMapSearch( 2 * float(M_PI)/20 ,0.1f));
    hashmap_search->setInputFeatureCloud(cloud_model_ppf);
    

    visualization::PCLVisualizer viewer("PPF Object Recognition - Results");
    viewer.setBackgroundColor(0, 0, 0);
    viewer.addPointCloud(cloud_scene);
    viewer.spinOnce(10);
    PCL_INFO("Registering models to scene ...\n");

    将源点云和目标点云都转化为无序点云
    //cloud_model_input->height = 1;
    //cloud_model_input->is_dense = false;
    //cloud_scene_input->height = 1;
    //cloud_scene_input->is_dense = false;
    PPFRegistration<PointNormal, PointNormal> ppf_registration;
    // set parameters for the PPF registration procedure
    ppf_registration.setSceneReferencePointSamplingRate(10);
    ppf_registration.setPositionClusteringThreshold(2.0f);
    ppf_registration.setRotationClusteringThreshold(12.0f / 180.0f * float(M_PI));
    ppf_registration.setSearchMethod(hashmap_search);
    ppf_registration.setInputSource(cloud_model_input);
    ppf_registration.setInputTarget(cloud_scene_input);
    无序点云
    PointCloud<PointNormal>::Ptr cloud_output_subsampled(new PointCloud<PointNormal>());

    ppf_registration.align(*cloud_output_subsampled);
    //出现数组越界访问,无序点云OR有序点云,  //有疑问的地方?????????????????????????????
    //修改ppf_registration.hpp中的const auto aux_size = static_cast<std::size_t>(
        //   std::floor(2 * M_PI / search_method_->getAngleDiscretizationStep() + 1));

    //转换点云XYZ格式
    PointCloud<PointXYZ>::Ptr cloud_output_subsampled_xyz(new PointCloud<PointXYZ>());
    for (const auto& point : (* cloud_output_subsampled).points)
        cloud_output_subsampled_xyz->points.emplace_back(point.x, point.y, point.z);

    Eigen::Matrix4f mat = ppf_registration.getFinalTransformation();
    std::cout << "PPF 变换矩阵:" << endl<<mat << endl;
    std::cout << "PPF score:" << ppf_registration.getFitnessScore() << endl;
    Eigen::Affine3f final_transformation(mat);
    //进行精确配准,采用ICP算法
    PointCloud<PointXYZ>::Ptr icp_result(new PointCloud<PointXYZ>());
    pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp;
    //输入待配准点云和目标点云
    icp.setInputSource(cloud_model_subsampled);
    icp.setInputTarget(cloud_output_subsampled_xyz);
    //Set the max correspondence distance to 4cm (e.g., correspondences with higher distances will be ignored)
    icp.setMaxCorrespondenceDistance(10);//默认单位是米?
    //最大迭代次数
    icp.setMaximumIterations(1000);
    //两次变化矩阵之间的差值
    icp.setTransformationEpsilon(1e-10);
    // 均方误差
    icp.setEuclideanFitnessEpsilon(0.002);
    icp.align(*icp_result, mat);
    Eigen::Matrix4f icp_trans;
    icp_trans = icp.getFinalTransformation();
    std::cout << "icp变换矩阵:" << endl<<icp_trans << endl;
    std::cout << "icp score:" << icp.getFitnessScore() << endl;
    PointCloud<PointXYZ>::Ptr cloud_output(new PointCloud<PointXYZ>());
    pcl::transformPointCloud(
        *cloud_model, *cloud_output, icp_trans);

    pcl::visualization::PointCloudColorHandlerCustom<PointXYZ> output(cloud_output_subsampled_xyz, 255, 0, 0);
    pcl::visualization::PointCloudColorHandlerRandom<PointXYZ> random_color(cloud_output->makeShared());
    viewer.addPointCloud(cloud_output, random_color, "mode_name");
    //viewer.addPointCloud(cloud_output_subsampled_xyz, output, "dsd");
    while (!viewer.wasStopped()) {
        viewer.spinOnce(100);
        std::this_thread::sleep_for(100ms);
    }
    return 0;
}

在使用过程中踩到的坑:   

(1):PointCloud<PPFSignature>::Ptr cloud_model_ppf(new PointCloud<PPFSignature>());
    PPFEstimation<PointNormal, PointNormal, PPFSignature> ppf_estimator;
    ppf_estimator.setInputCloud(cloud_model_input);
    ppf_estimator.setInputNormals(cloud_model_input);
    ppf_estimator.compute(*cloud_model_ppf);

运行到ppf_estimator.compute(*cloud_model_ppf);一直报错,是指针问题,打开属性面板,选择高级矢量扩展即可

pcl点云识别,PCL点云识别,c++,算法,开发语言,3d

(2)ppf_registration.align(*cloud_output_subsampled);运行到这里时一致报错,弹出警告是vector越界访问。解决办法:

pcl点云识别,PCL点云识别,c++,算法,开发语言,3d

 修改这个库文件,在floor函数后加一即可解决,问题出在floor函数向下取整,aux_size应该等于20,floor括号中算出来的是19.999.。。。,向下取整就变成19了,所以会出现越界访问!!

附上最后运行效果:

pcl点云识别,PCL点云识别,c++,算法,开发语言,3d

 

 pcl点云识别,PCL点云识别,c++,算法,开发语言,3d

 绿色点云是找到的目标,加ICP是为了使位姿更准确文章来源地址https://www.toymoban.com/news/detail-557208.html

到了这里,关于使用PCL库中PPF+ICP进行点云目标识别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 学习PCL库:PCL库中surface模块

    公众号致力于点云处理,SLAM,三维视觉,高精地图等领域相关内容的干货分享,欢迎各位加入,有兴趣的可联系dianyunpcl@163.com。未经作者允许请勿转载,欢迎各位同学积极分享和交流。 surface模块介绍 PCL库中的surface模块提供了各种表面重建和拟合算法,根据任务的不同包含

    2024年01月22日
    浏览(27)
  • (学习笔记)PCL点云库的基本使用

    目录 前言 1、理解点云库 1.1、不同的点云类型 1.2、PCL中的算法 1.3、ROS的PCL接口 2、创建第一个PCL程序 2.1、创建点云 2.2、加载点云文件 2.3、创建点云文件 2.4、点云可视化 2.5、点云滤波和下采样 2.5.1、点云滤波  2.5.2、点云下采样 2.6、点云配准与匹配         点云是一种

    2023年04月08日
    浏览(25)
  • 使用PCL滤波器实现点云裁剪

    点云裁剪是根据提取划分或者说标注出来的点云区域(ROI区域),对点云进行区域分离(点云裁剪和点云分割还是有区别的,所以这里用分离而不是分割)。根据已知的ROI区域,对点云进行裁剪。要么留下点云ROI区域,要么去除。 ROI区域一般都是一个矩形,即(x,y,width,

    2024年02月15日
    浏览(35)
  • PCL 使用点云创建数字高程模型DEM

       数字高程模型(Digital Elevation Model),简称DEM,是通过有限的地形高程数据实现对地面地形的数字化模拟(即地形表面形态的数字化表达),它是用一组有序数值阵列形式表示地面高程的一种实体地面模型,是数字地形模型(Digital Terrain Model,简称DTM)的一个分支,其它各种

    2024年02月13日
    浏览(33)
  • 点云配准--gicp原理与其在pcl中的使用

    总结:gicp引入了概率信息(使用协方差阵),提出了icp的统一模型,既可以解释点到点和点到面的icp,也在新模型理论的基础上,提出了一种面到面的icp。 论文原文:《Generalized-ICP》 在概率模型中假设存在配准中两个点集, A ^ = { a i ^ } hat{A}=left{hat{a_{i}}right} A ^ = { a i ​

    2024年01月19日
    浏览(38)
  • PCL 点云变换

    一、原理简述 两片点云的刚体变换包含旋转和平移,变换矩阵的含义如下: 1、旋转矩阵 绕 x x

    2023年04月25日
    浏览(25)
  • pcl+vtk(三)QT中使用QVTKOpenGLNativeWidget的简单教程以及案例,利用PCLVisualizer显示点云

    先添加一个带有ui的QT应用程序。 先拖出来一个QOpenGLWidget控件 修改布局如下: 然后将QOpenGLWidget控件提升为QVTKOpenGLNativeWidget控件,步骤如下: 右击QOpenGLWidget窗口,选择【提示为...】  输入提升的类名称为QVTKOpenGLNativeWidget  此时需要把自动生成的qvtkopenglnativewidget.h修改为QV

    2024年01月25日
    浏览(26)
  • PCL 点云组件聚类

    该算法与欧式聚类、DBSCAN聚类很是类似,聚类过程如下所述: 1. 首先,我们需要提供一个种子点集合,对种子点集合进行初始的聚类操作,聚类的评估器(即聚类条件),可以指定为法向评估,也可以是距离评估,以此我们就可以提取出点云中各个位置的组件部分。 2. 合并

    2024年02月10日
    浏览(28)
  • PCL点云库(2) - IO模块

    目录 2.1 IO模块接口 2.2 PCD数据读写 (1) PCD数据解析 (2)PCD文件读写示例 2.3 PLY数据读写 (1)PLY数据解析 (2)PLY文件读写示例 2.4 OBJ数据读写 (1)OBJ数据解析 (2)OBJ文件读写示例 2.5 VTK数据读写 (1)VTK数据解析 (2)VTK文件读写示例 2.6 保存为PNG 参考文章:PCL函数库

    2023年04月22日
    浏览(30)
  • 点云分割-pcl区域生长算法

    1、本文内容 pcl的区域生长算法的使用和原理 2、平台/环境 cmake, pcl 3、转载请注明出处: https://blog.csdn.net/qq_41102371/article/details/131927376 参考:https://pcl.readthedocs.io/projects/tutorials/en/master/region_growing_segmentation.html#region-growing-segmentation https://blog.csdn.net/taifyang/article/details/124097186

    2024年02月15日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包