C++ PCL三维点云物体目标识别

简介: C++ PCL三维点云物体目标识别
程序示例精选
C++ PCL三维点云物体目标识别
如需安装运行环境或远程调试,可点击
博主头像进入个人主页查看博主联系方式,由专业技术人员远程协助!

前言

这篇博客针对《C++ PCL三维点云物体目标识别》编写代码,代码整洁,规则,易读。 学习与应用推荐首选。

运行结果

文章目录

一、所需工具软件
二、使用步骤
1. 主要代码
2. 运行结果

三、在线协助

一、所需工具软件

1. VS2019, C++
2. C++

二、使用步骤

代码如下(示例):

void
parseCommandLine(int argc, char *argv[])
{
   
   
    //Show help
    if (pcl::console::find_switch(argc, argv, "-h"))
    {
   
   
        showHelp(argv[0]);
        exit(0);
    }

    //Model & scene filenames
    std::vector<int> filenames;
    filenames = pcl::console::parse_file_extension_argument(argc, argv, ".pcd");
    if (filenames.size() != 2)
    {
   
   
        std::cout << "Filenames missing.\n";
        showHelp(argv[0]);
        exit(-1);
    }

    model_filename_ = argv[filenames[0]];
    scene_filename_ = argv[filenames[1]];

    //Program behavior
    if (pcl::console::find_switch(argc, argv, "-k"))//可视化构造对应点时用到的关键点
    {
   
   
        show_keypoints_ = true;
    }
    if (pcl::console::find_switch(argc, argv, "-c"))//可视化支持实例假设的对应点对
    {
   
   
        show_correspondences_ = true;
    }
    if (pcl::console::find_switch(argc, argv, "-r"))//计算点云的分辨率和多样性
    {
   
   
        use_cloud_resolution_ = true;
    }

    std::string used_algorithm;
    if (pcl::console::parse_argument(argc, argv, "--algorithm", used_algorithm) != -1)
    {
   
   
        if (used_algorithm.compare("Hough") == 0)
        {
   
   
            use_hough_ = true;
        }
        else if (used_algorithm.compare("GC") == 0)
        {
   
   
            use_hough_ = false;
        }
        else
        {
   
   
            std::cout << "Wrong algorithm name.\n";
            showHelp(argv[0]);
            exit(-1);
        }
    }

    //General parameters
    pcl::console::parse_argument(argc, argv, "--model_ss", model_ss_);
    pcl::console::parse_argument(argc, argv, "--scene_ss", scene_ss_);
    pcl::console::parse_argument(argc, argv, "--rf_rad", rf_rad_);
    pcl::console::parse_argument(argc, argv, "--descr_rad", descr_rad_);
    pcl::console::parse_argument(argc, argv, "--cg_size", cg_size_);
    pcl::console::parse_argument(argc, argv, "--cg_thresh", cg_thresh_);
}


int
main(int argc, char *argv[])
{
   
   
    parseCommandLine(argc, argv);

    pcl::PointCloud<PointType>::Ptr model(new pcl::PointCloud<PointType>());           //模型点云
    pcl::PointCloud<PointType>::Ptr model_keypoints(new pcl::PointCloud<PointType>()); //模型角点
    pcl::PointCloud<PointType>::Ptr scene(new pcl::PointCloud<PointType>());           //目标点云
    pcl::PointCloud<PointType>::Ptr scene_keypoints(new pcl::PointCloud<PointType>()); //目标角点
    pcl::PointCloud<NormalType>::Ptr model_normals(new pcl::PointCloud<NormalType>()); //法线
    pcl::PointCloud<NormalType>::Ptr scene_normals(new pcl::PointCloud<NormalType>()); //
    pcl::PointCloud<DescriptorType>::Ptr model_descriptors(new pcl::PointCloud<DescriptorType>()); //描述子
    pcl::PointCloud<DescriptorType>::Ptr scene_descriptors(new pcl::PointCloud<DescriptorType>());

    //
    //  Load clouds
    //
    if (pcl::io::loadPCDFile(model_filename_, *model) < 0)
    {
   
   
        std::cout << "Error loading model cloud." << std::endl;
        showHelp(argv[0]);
        return (-1);
    }
    if (pcl::io::loadPCDFile(scene_filename_, *scene) < 0)
    {
   
   
        std::cout << "Error loading scene cloud." << std::endl;
        showHelp(argv[0]);
        return (-1);
    }

    //
    //  Set up resolution invariance
    //
    if (use_cloud_resolution_)
    {
   
   
        float resolution = static_cast<float> (computeCloudResolution(model));
        if (resolution != 0.0f)
        {
   
   
            model_ss_ *= resolution;
            scene_ss_ *= resolution;
            rf_rad_ *= resolution;
            descr_rad_ *= resolution;
            cg_size_ *= resolution;
        }

        std::cout << "Model resolution:       " << resolution << std::endl;
        std::cout << "Model sampling size:    " << model_ss_ << std::endl;
        std::cout << "Scene sampling size:    " << scene_ss_ << std::endl;
        std::cout << "LRF support radius:     " << rf_rad_ << std::endl;
        std::cout << "SHOT descriptor radius: " << descr_rad_ << std::endl;
        std::cout << "Clustering bin size:    " << cg_size_ << std::endl << std::endl;
    }



    std::cout << "Model total points: " << model->size() << "; Selected Keypoints: " << model_keypoints->size() << std::endl;

    uniform_sampling.setInputCloud(scene);
    uniform_sampling.setRadiusSearch(scene_ss_);
    //uniform_sampling.compute (sampled_indices);
    //pcl::copyPointCloud (*scene, sampled_indices.points, *scene_keypoints);
    uniform_sampling.filter(*scene_keypoints);
    std::cout << "Scene total points: " << scene->size() << "; Selected Keypoints: " << scene_keypoints->size() << std::endl;

    //
    //  Compute Descriptor for keypoints:为关键点计算描述子
    //
    pcl::SHOTEstimationOMP<PointType, NormalType, DescriptorType> descr_est;
    descr_est.setNumberOfThreads(4);
    descr_est.setRadiusSearch(descr_rad_);     //设置搜索半径

    descr_est.setInputCloud(model_keypoints);  //模型点云的关键点
    descr_est.setInputNormals(model_normals);  //模型点云的法线 
    descr_est.setSearchSurface(model);         //模型点云       
    descr_est.compute(*model_descriptors);     //计算描述子

    descr_est.setInputCloud(scene_keypoints);
    descr_est.setInputNormals(scene_normals);
    descr_est.setSearchSurface(scene);
    descr_est.compute(*scene_descriptors);

    //
    //  Find Model-Scene Correspondences with KdTree:使用Kdtree找出 Model-Scene 匹配点
    //
    pcl::CorrespondencesPtr model_scene_corrs(new pcl::Correspondences());

    pcl::KdTreeFLANN<DescriptorType> match_search; //设置配准方式
    match_search.setInputCloud(model_descriptors);//模型点云的描述子




        //  Clustering
        pcl::Hough3DGrouping<PointType, PointType, RFType, RFType> clusterer;
        clusterer.setHoughBinSize(cg_size_);     //hough空间的采样间隔:0.01
        clusterer.setHoughThreshold(cg_thresh_); //在hough空间确定是否有实例存在的最少票数阈值:5
        clusterer.setUseInterpolation(true);     //设置是否对投票在hough空间进行插值计算
        clusterer.setUseDistanceWeight(false);   //设置在投票时是否将对应点之间的距离作为权重参与计算

        clusterer.setInputCloud(model_keypoints); //设置模型点云的关键点
        clusterer.setInputRf(model_rf);           //设置模型对应的局部坐标系
        clusterer.setSceneCloud(scene_keypoints);
        clusterer.setSceneRf(scene_rf);
        clusterer.setModelSceneCorrespondences(model_scene_corrs);//设置模型与场景的对应点的集合

        //clusterer.cluster (clustered_corrs);
        clusterer.recognize(rototranslations, clustered_corrs); //结果包含变换矩阵和对应点聚类结果
    }
    else // Using GeometricConsistency:使用几何一致性性质
    {
   
   
        pcl::GeometricConsistencyGrouping<PointType, PointType> gc_clusterer;
        gc_clusterer.setGCSize(cg_size_);        //设置几何一致性的大小
        gc_clusterer.setGCThreshold(cg_thresh_); //阈值

        gc_clusterer.setInputCloud(model_keypoints);
        gc_clusterer.setSceneCloud(scene_keypoints);
        gc_clusterer.setModelSceneCorrespondences(model_scene_corrs);

        //gc_clusterer.cluster (clustered_corrs);
        gc_clusterer.recognize(rototranslations, clustered_corrs);
    }

    //
    //  Output results:找出输入模型是否在场景中出现
    //
    std::cout << "Model instances found: " << rototranslations.size() << std::endl;
    for (size_t i = 0; i < rototranslations.size(); ++i)
    {
   
   
        std::cout << "\n    Instance " << i + 1 << ":" << std::endl;
        std::cout << "        Correspondences belonging to this instance: " << clustered_corrs[i].size() << std::endl;

        //打印处相对于输入模型的旋转矩阵与平移矩阵
        Eigen::Matrix3f rotation = rototranslations[i].block<3, 3>(0, 0);
        Eigen::Vector3f translation = rototranslations[i].block<3, 1>(0, 3);

        printf("\n");
        printf("            | %6.3f %6.3f %6.3f | \n", rotation(0, 0), rotation(0, 1), rotation(0, 2));
        printf("        R = | %6.3f %6.3f %6.3f | \n", rotation(1, 0), rotation(1, 1), rotation(1, 2));
        printf("            | %6.3f %6.3f %6.3f | \n", rotation(2, 0), rotation(2, 1), rotation(2, 2));
        printf("\n");
        printf("        t = < %0.3f, %0.3f, %0.3f >\n", translation(0), translation(1), translation(2));
    }

    //
    //  Visualization
    //
    pcl::visualization::PCLVisualizer viewer("点云库PCL学习教程第二版-基于对应点聚类的3D模型识别");
    viewer.addPointCloud(scene, "scene_cloud");//可视化场景点云
    viewer.setBackgroundColor(0, 0, 0);
    pcl::PointCloud<PointType>::Ptr off_scene_model(new pcl::PointCloud<PointType>());
    pcl::PointCloud<PointType>::Ptr off_scene_model_keypoints(new pcl::PointCloud<PointType>());

    if (show_correspondences_ || show_keypoints_)//可视化配准点
    {
   
   
        //We are translating the model so that it doesn't end in the middle of the scene representation
        //对输入的模型进行旋转与平移,使其在可视化界面的中间位置
        pcl::transformPointCloud(*model, *off_scene_model, Eigen::Vector3f(0, 0, 0), Eigen::Quaternionf(1, 0, 0, 0));
        pcl::transformPointCloud(*model_keypoints, *off_scene_model_keypoints, Eigen::Vector3f(-1, 0, 0), Eigen::Quaternionf(1, 0, 0, 0));
        pcl::visualization::PointCloudColorHandlerCustom<PointType> off_scene_model_color_handler(off_scene_model, 0, 255, 0);
        viewer.addPointCloud(off_scene_model, off_scene_model_color_handler, "off_scene_model");
    }
    if (show_keypoints_)//可视化关键点:蓝色
    {
   
   
        pcl::visualization::PointCloudColorHandlerCustom<PointType> scene_keypoints_color_handler(scene_keypoints, 0, 0, 255);
        viewer.addPointCloud(scene_keypoints, scene_keypoints_color_handler, "scene_keypoints");
        viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "scene_keypoints");
        pcl::visualization::PointCloudColorHandlerCustom<PointType> off_scene_model_keypoints_color_handler(off_scene_model_keypoints, 0, 0, 255);
        viewer.addPointCloud(off_scene_model_keypoints, off_scene_model_keypoints_color_handler, "off_scene_model_keypoints");
        viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "off_scene_model_keypoints");
    }
    for (size_t i = 0; i < rototranslations.size(); ++i)
    {
   
   
        pcl::PointCloud<PointType>::Ptr rotated_model(new pcl::PointCloud<PointType>());
        pcl::transformPointCloud(*model, *rotated_model, rototranslations[i]);//把model转化为rotated_model
        std::stringstream ss_cloud;
        ss_cloud << "instance" << i;
        pcl::visualization::PointCloudColorHandlerCustom<PointType> rotated_model_color_handler(rotated_model, 255, 0, 0);
        viewer.addPointCloud(rotated_model, rotated_model_color_handler, ss_cloud.str());
                //  We are drawing a line for each pair of clustered correspondences found between the model and the scene
                viewer.addLine<PointType, PointType>(model_point, scene_point, 0, 255, 0, ss_line.str());
            }
        }
    }
    while (!viewer.wasStopped())
    {
   
   
        viewer.spinOnce();
    }
    return (0);
}

运行结果

三、在线协助:

如需安装运行环境或远程调试,可点击博主头像,进入个人主页查看博主联系方式,由专业技术人员远程协助!

1)远程安装运行环境,代码调试
2)Visual Studio, Qt, C++, Python编程语言入门指导
3)界面美化
4)软件制作

博主个人主页:https://developer.aliyun.com/profile/expert/rfnzgp3sk3ahc
博主所有文章点这里:https://developer.aliyun.com/profile/expert/rfnzgp3sk3ahc
博主联系方式点这里:https://developer.aliyun.com/profile/expert/rfnzgp3sk3ahc
相关文章
|
4月前
|
C++
C++ PCL 沿着自定义的平面做横截面(直通滤波)
C++ PCL 沿着自定义的平面做横截面(直通滤波)
49 0
|
4月前
|
C++
C++ PCL SACSegmentationFromNormals setAxis 轴向的选择
C++ PCL SACSegmentationFromNormals setAxis 轴向的选择
80 2
|
4月前
|
C++
C++ PCL 求两个平面的交线
C++ PCL 求两个平面的交线
56 0
|
4月前
|
C++
C++ PCL 将一个点云投影到一个由法向量和点确定的平面
C++ PCL 将一个点云投影到一个由法向量和点确定的平面
127 0
|
4月前
|
C++
C++ PCL 计算多个RT矩阵变换后的变换矩阵
C++ PCL 计算多个RT矩阵变换后的变换矩阵
56 0
|
4月前
|
传感器 算法 C++
C++ PCL 设置法向量的方向
C++ PCL 设置法向量的方向
92 0
|
7月前
|
存储 安全 固态存储
【C++医学影像】支持三维影像后处理PACS系统源码
【C++医学影像】支持三维影像后处理PACS系统源码
138 0
|
7月前
|
存储 数据采集 数据库
【C++】医学影像PACS管理系统源码支持三维图像后处理和重建
【C++】医学影像PACS管理系统源码支持三维图像后处理和重建
137 0
|
C++ 计算机视觉 Python
C++ VS OpenGL绘制教室三维立体旋转图像
C++ VS OpenGL绘制教室三维立体旋转图像
166 0
C++ VS OpenGL绘制教室三维立体旋转图像
|
C++ Python
C++ VS Open3D点云显示颜色渲染滤波
C++ VS Open3D点云显示颜色渲染滤波
161 0