PCL点云库学习:点云的欧式聚类

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_40335930/article/details/91982640
初学者笔记:
点云欧式聚类算法流程
(1)点云读入;
(2)体素化下采样(方便处理);
(3)去离散点;PCL点云库学习笔记(3):点云的欧式聚类
(4)RANSAC算法检测平面,并剔除平面点云;
(5)欧式聚类;
(6)结果的输出和可视化;

点云数据链接:
链接:https://pan.baidu.com/s/1VTVxn3BntbAr9tGHv6L-HA
提取码:u81q

代码:

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL)
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/segmentation/extract_clusters.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/ModelCoefficients.h>
#include <pcl/filters/extract_indices.h>
#include<ctime>
#include<cstdlib>
#include <windows.h>

using namespace pcl;
using namespace std;
typedef PointXYZ PoinT;

int *rand_rgb(){//随机产生颜色
    int *rgb = new int[3];    
    rgb[0] = rand() % 255;
    rgb[1] = rand() % 255;
    rgb[2] = rand() % 255;
    return rgb;
}
int main(){
    //点云的读取*********************************************************
    PointCloud<PoinT>::Ptr cloud(new PointCloud<PoinT>);
    if (io::loadPCDFile("C:\\Users\\Administrator\\Desktop\\desk.pcd", *cloud) == -1)
    {
        PCL_ERROR("read false");
        return 0;
    }
    //体素化下采样******************************************************
    VoxelGrid<PoinT> vox;
    PointCloud<PoinT>::Ptr vox_cloud(new PointCloud<PoinT>);
    vox.setInputCloud(cloud);
    vox.setLeafSize(0.01, 0.01, 0.01);
    vox.filter(*vox_cloud);
    //去除噪声点********************************************************
    StatisticalOutlierRemoval<PoinT>sor;
    PointCloud<PoinT>::Ptr sor_cloud(new PointCloud<PoinT>);
    sor.setMeanK(10);
    sor.setInputCloud(vox_cloud);
    sor.setStddevMulThresh(0.2);
    sor.filter(*sor_cloud);
    //平面分割(RANSAC)********************************************************
    SACSegmentation<PoinT> sac;
    PointIndices::Ptr inliner(new PointIndices);
    ModelCoefficients::Ptr coefficients(new ModelCoefficients);
    PointCloud<PoinT>::Ptr sac_cloud(new PointCloud<PoinT>);
    sac.setInputCloud(sor_cloud);
    sac.setMethodType(SAC_RANSAC);
    sac.setModelType(SACMODEL_PLANE);
    sac.setMaxIterations(100);
    sac.setDistanceThreshold(0.02);
    //提取平面(展示并输出)******************************************************
    PointCloud<PoinT>::Ptr ext_cloud(new PointCloud<PoinT>);
    PointCloud<PoinT>::Ptr ext_cloud_rest(new PointCloud<PoinT>);
    visualization::PCLVisualizer::Ptr viewer(new visualization::PCLVisualizer("3d view"));

    int i = sor_cloud->size(), j = 0;
    ExtractIndices<PoinT>ext;
    srand((unsigned)time(NULL));//刷新时间的种子节点需要放在循环体外面
    while (sor_cloud->size()>i*0.3)//当提取的点数小于总数的3/10时,跳出循环
    {
        ext.setInputCloud(sor_cloud);
        sac.segment(*inliner, *coefficients);
        if (inliner->indices.size()==0)
        {
            break;
        }
        //按照索引提取点云*************
        ext.setIndices(inliner);
        ext.setNegative(false);
        ext.filter(*ext_cloud);
        ext.setNegative(true);
        ext.filter(*ext_cloud_rest);
        //*****************************
        *sor_cloud = *ext_cloud_rest;
        stringstream ss;
        ss <<"C:\\Users\\Administrator\\Desktop\\"<<"ext_plane_clouds" << j << ".pcd";//路径加文件名和后缀
        io::savePCDFileASCII(ss.str(), *ext_cloud);//提取的平面点云写出
        int *rgb = rand_rgb();//随机生成0-255的颜色值
        visualization::PointCloudColorHandlerCustom<PoinT>rgb1(ext_cloud,rgb[0],rgb[1],rgb[2]);//提取的平面不同彩色展示
        delete[]rgb;
        viewer->addPointCloud(ext_cloud, rgb1,ss.str());
        j++;
    }
    viewer->spinOnce(1000);
    //欧式聚类*******************************************************
    vector<PointIndices>ece_inlier;
    search::KdTree<PoinT>::Ptr tree(new search::KdTree<PoinT>);
    EuclideanClusterExtraction<PoinT> ece;
    ece.setInputCloud(sor_cloud);
    ece.setClusterTolerance(0.02);
    ece.setMinClusterSize(100);
    ece.setMaxClusterSize(20000);
    ece.setSearchMethod(tree);
    ece.extract(ece_inlier);
    //聚类结果展示***************************************************
    ext.setInputCloud(sor_cloud);
    visualization::PCLVisualizer::Ptr viewer2(new visualization::PCLVisualizer("Result of EuclideanCluster"));
    srand((unsigned)time(NULL));
    for (int i = 0; i < ece_inlier.size();i++)
    {
        PointCloud<PoinT>::Ptr cloud_copy(new PointCloud<PoinT>);
        vector<int> ece_inlier_ext = ece_inlier[i].indices;
        copyPointCloud(*sor_cloud, ece_inlier_ext, *cloud_copy);//按照索引提取点云数据
        stringstream ss1;
        ss1 <<"C:\\Users\\Administrator\\Desktop\\"<< "EuclideanCluster_clouds" << j<<".pcd";
        io::savePCDFileASCII(ss1.str(), *ext_cloud);//欧式聚类结果写出
        int *rgb1 = rand_rgb();
        visualization::PointCloudColorHandlerCustom<PoinT>rgb2(ext_cloud, rgb1[0], rgb1[1], rgb1[2]);
        delete[]rgb1;
        viewer2->addPointCloud(cloud_copy, rgb2,ss1.str());
        j++;
    }
    viewer2->spin();
    return 0;
}

可视化结果展示:
提取的平面(颜色随机):
欧式聚类的结果(颜色随机):

写出的点云数据(平面2个,欧式聚类结果5个):

遇到过error C4996: 'pcl::SAC_SAMPLE_SIZE’编译错误的问题
解决方法参考链接:https://blog.csdn.net/lizhengze1117/article/details/86565100


#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/segmentation/extract_clusters.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/ModelCoefficients.h>
#include <pcl/filters/extract_indices.h>
#include<ctime>
#include<cstdlib>
#include <windows.h>

using namespace pcl;
using namespace std;
typedef PointXYZ PoinT;

int main(){
    //点云的读取*********************************************************
    PointCloud<PoinT>::Ptr cloud(new PointCloud<PoinT>);
    if (io::loadPCDFile("C:\\Users\\admin\\Desktop\\保留的结果.pcd", *cloud) == -1)
    {
        PCL_ERROR("read false");
        return 0;
    }
    //欧式聚类*******************************************************
    vector<PointIndices>ece_inlier;
    search::KdTree<PoinT>::Ptr tree(new search::KdTree<PoinT>);
    EuclideanClusterExtraction<PoinT> ece;
    ece.setInputCloud(cloud);
    ece.setClusterTolerance(1);
    ece.setMinClusterSize(100);
    ece.setMaxClusterSize(20000000000000);
    ece.setSearchMethod(tree);
    ece.extract(ece_inlier);
    //聚类结果展示***************************************************
    PointCloud<PoinT>::Ptr ext_cloud(new PointCloud<PoinT>);
    ExtractIndices<PoinT>ext;
    ext.setInputCloud(cloud);
    visualization::PCLVisualizer::Ptr viewer2(new visualization::PCLVisualizer("Result of EuclideanCluster"));
    srand((unsigned)time(NULL));
    int j = 0;
    vector<unsigned char>color;
    for (int i_segment = 0; i_segment < ece_inlier.size(); i_segment++)
    {
        color.push_back(static_cast<unsigned char>(rand() % 256));
        color.push_back(static_cast<unsigned char>(rand() % 256));
        color.push_back(static_cast<unsigned char>(rand() % 256));
    }
    int color_index = 0;
    PointCloud<PointXYZRGB>::Ptr color_point(new PointCloud<PointXYZRGB>);
    for (int i_seg = 0; i_seg < ece_inlier.size(); i_seg++)
    {
        int clusters_size = ece_inlier[i_seg].indices.size();
        for (int i_idx = 0; i_idx < clusters_size; i_idx++)
        {
            PointXYZRGB point;
            point.x = cloud->points[ece_inlier[i_seg].indices[i_idx]].x;
            point.y = cloud->points[ece_inlier[i_seg].indices[i_idx]].y;
            point.z = cloud->points[ece_inlier[i_seg].indices[i_idx]].z;
            point.r = color[3 * color_index];
            point.g = color[3 * color_index + 1];
            point.b = color[3 * color_index + 2];
            color_point->push_back(point);
        }
        color_index++;
    }
    viewer2->addPointCloud(color_point);
    viewer2->spin();
    return 0;
}

————————————————
版权声明:本文为CSDN博主「起个名字费劲死了」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_40335930/article/details/91982640

PCL点云中的欧式聚类分割是一种通过计算点云中点之间的欧氏距离来将点云分割成不同的聚类的方法。在这种方法中,首先对点云进行预处理,包括去除离群点和平面模型分割。然后,使用pcl::EuclideanClusterExtraction类对点云进行欧式聚类分割。该类通过设置聚类的最小和最大尺寸,以及聚类的距离阈值来提取聚类。 在使用欧式聚类分割的过程中,首先对点云进行预处理,包括去除离群点和平面模型分割。然后,根据设定的距离阈值,将点云中的点分成不同的聚类聚类的最小和最大尺寸可以用来控制聚类的大小。最后,可以通过获取每个聚类中的点的数量,进一步分析和处理聚类。 通过使用PCL点云中的欧式聚类分割方法,可以对点云数据进行有效的分割和聚类,从而实现对点云数据的进一步分析和应用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [PCL点云-欧式聚类分割-麦粒](https://download.csdn.net/download/fei_12138/87570560)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [PCL教程-点云分割之欧式聚类分割](https://blog.csdn.net/luolaihua2018/article/details/120184539)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值