当前位置:   article > 正文

Ubuntu 20.04.06 PCL C++学习记录(十八)

Ubuntu 20.04.06 PCL C++学习记录(十八)

@[TOC]PCL中点云分割模块的学习

学习背景

参考书籍:《点云库PCL从入门到精通》以及官方代码PCL官方代码链接,,PCL版本为1.10.0,CMake版本为3.16

学习内容

PCL中实现欧式聚类提取。在点云处理中,聚类是一种常见的任务,它将点云数据划分为多个独立的簇或集群。每个簇代表点云中的一个独立物体或区域。聚类可以帮助我们从复杂的点云场景中识别出单独的物体,为后续的物体识别、分类和其他处理任务奠定基础。

源代码及所用函数

源代码

#include<pcl/ModelCoefficients.h>//定义名为 pcl::ModelCoefficients 的类,用于存储模型的系数
#include<pcl/point_types.h>
#include<pcl/io/pcd_io.h>
#include<pcl/filters/extract_indices.h>
#include<pcl/filters/voxel_grid.h>
#include<pcl/kdtree/kdtree.h>
#include<pcl/sample_consensus/method_types.h>//随机参数估计方法头文件
#include<pcl/sample_consensus/model_types.h>//定义 PCL 中用于随机采样一致性 (SAC) 方法的枚举类型
#include<pcl/segmentation/sac_segmentation.h>//提供 PCL 中用于基于随机采样一致性 (SAC) 方法进行点云分割的类和函数
#include<pcl/segmentation/extract_clusters.h>//包含 PCL (Point Cloud Library) 中用于点云聚类的头文件

/******************************************************************************
 打开点云数据,并对点云进行滤波重采样预处理,然后采用平面分割模型对点云进行分割处理
 提取出点云中所有在平面上的点集,并将其存盘
******************************************************************************/
int main(int argc,char** argv)
{
    /*********************************************************读取点云数据***************************/
    pcl::PCDReader reader;
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    reader.read("/home/jojo/PointCloud/table_400.pcd",*cloud);
    std::cout << "滤波之前有" << cloud->points.size() << "个点" << std::endl;
    /*************************************创建过滤对象:使用 1 厘米大小的叶片对数据集进行下采样************/
    //使用体素化网格方法实现下采样,即减少点的数量 减少点云数据,并同时保存点云的形状特征   
    pcl::VoxelGrid<pcl::PointXYZ> vg;
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_f(new pcl::PointCloud<pcl::PointXYZ>);
    vg.setInputCloud(cloud);//设置需要过滤的点云给滤波对象
    vg.setLeafSize(0.01f,0.01f,0.01f);//设置滤波时创建的体素体积为1cm的立方体
    vg.filter(*cloud_filtered); //执行滤波处理,存储输出
    std::cout << "滤波之后有" << cloud_filtered->points.size() << "个点" << std::endl;
    /****************************创建平面模型分割的对象并设置参数************************************/
    pcl::SACSegmentation<pcl::PointXYZ> seg;
    pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
    pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane(new pcl::PointCloud<pcl::PointXYZ>());
    pcl::PCDWriter writer;
    seg.setOptimizeCoefficients(true);
    seg.setModelType(pcl::SACMODEL_PLANE);//分割模型
    seg.setMethodType(pcl::SAC_RANSAC);//随机参数估计方法
    seg.setMaxIterations(100);//最大的迭代次数
    seg.setDistanceThreshold(0.02);//设置阈值

    int i = 0,nr_points = (int)cloud_filtered->points.size();
    while (cloud_filtered->points.size() > 0.3 * nr_points)
    {
        /**********************************从剩余云中分离出最大的平面***************************/
        seg.setInputCloud(cloud_filtered);
        seg.segment(*inliers,*coefficients);
        if(inliers->indices.size() == 0)
        {
            std::cout << "找不到平面对象" << std::endl;
            break;
        }
        pcl::ExtractIndices<pcl::PointXYZ> extract;
        extract.setInputCloud(cloud_filtered);
        extract.setIndices(inliers);
        extract.setNegative(false);
        /********************************获取与平面相关的点**********************************/
        extract.filter(*cloud_plane);
        std::cout << "代表平面组件的点云有:" << cloud_plane->points.size() << "个" << std::endl;
        /******************************移去平面局内点,提取剩余点云****************************/
        extract.setNegative(true);
        extract.filter(*cloud_f);
        *cloud_filtered = *cloud_f;
    }
    /******************************创建KD树对象****************************************/
    pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree(new pcl::search::KdTree<pcl::PointXYZ>);
    kdtree->setInputCloud(cloud_filtered);

    std::vector<pcl::PointIndices> cluster_indices;
    pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;//欧式聚类对象
    ec.setClusterTolerance(0.02);// 设置近邻搜索的搜索半径为2cm
    ec.setMinClusterSize(100);//设置一个聚类需要的最少的点数目为100
    ec.setMaxClusterSize(25000);//设置一个聚类需要的最大点数目为25000
    ec.setSearchMethod(kdtree);//设置点云的搜索机制
    ec.setInputCloud(cloud_filtered);
    ec.extract(cluster_indices);//从点云中提取聚类,并将点云索引保存在cluster_indices中
    //迭代访问点云索引cluster_indices,直到分割处所有聚类
    int j = 0;
    for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin();it != cluster_indices.end();++it)
    {
        pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster(new pcl::PointCloud<pcl::PointXYZ>);
        for (std::vector<int>::const_iterator pit = it->indices.begin();pit != it->indices.end();pit++)
        {
            cloud_cluster->points.push_back(cloud_filtered->points[*pit]);
        }
        cloud_cluster->width = cloud_cluster->points.size();
        cloud_cluster->height = 1;
        cloud_cluster->is_dense = true;
        std::cout << "代表集群的点云:" << cloud_cluster->points.size() << "个" << std::endl;
        std::stringstream ss;
        ss << "cloud_cluster_" << j << ".pcd";
        writer.write<pcl::PointXYZ>(ss.str(),*cloud_cluster,false);
        j++;
        
    }
    return 0;
    
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101

CMakeLists.txt

cmake_minimum_required(VERSION 3.16 FATAL_ERROR)#指定CMake的最低版本要求为3.16
project(project)#设置项目名称
find_package(PCL 1.10 REQUIRED)#查找PCL库,要求版本为1.10或更高。
include_directories(${PCL_INCLUDE_DIRS})#将PCL库的头文件目录添加到包含路径中
link_directories(${PCL_LIBRARY_DIRS})#将PCL库的库文件目录添加到链接器搜索路径中。
add_definitions(${PCL_DEFINITIONS})#添加PCL库的编译器定义
add_executable (cluster_extraction cluster_extraction.cpp)
target_link_libraries (cluster_extraction ${PCL_LIBRARIES})#将PCL库链接到可执行文件目标。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

运行结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

函数

  • pcl/segmentation/extract_clusters.h包含 PCL (Point Cloud Library) 中用于点云聚类的头文件

补充内容

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号