当前位置: 首页 > news >正文

PCL 基于欧几里得聚类的点云分割

这个程序可以提取出PCL点云里的欧式聚类,从而分割点云。

先看一下输入点云,是一张桌子:

程序运行后会提取出欧几里得聚类,如下图所示:

桌子本来是立体的,现在只有个截面了:

下面是同时显示输入点云和输出点云的结果,作为对比:

粉色的是输入点云,其他颜色的是输出点云。

输入:table_scene_lms400.pcd PCL点云

输出:cloud_cluster_000X.pcd X个 PCL点云

代码:

#include <pcl/ModelCoefficients.h> #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/features/normal_3d.h> #include <pcl/search/kdtree.h> #include <pcl/sample_consensus/method_types.h> #include <pcl/sample_consensus/model_types.h> #include <pcl/segmentation/sac_segmentation.h> #include <pcl/segmentation/extract_clusters.h> #include <iomanip> // for setw, setfill int main () { // Read in the cloud data pcl::PCDReader reader; pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>), cloud_f (new pcl::PointCloud<pcl::PointXYZ>); reader.read ("table_scene_lms400.pcd", *cloud); std::cout << "PointCloud before filtering has: " << cloud->size () << " data points." << std::endl; //* // Create the filtering object: downsample the dataset using a leaf size of 1cm pcl::VoxelGrid<pcl::PointXYZ> vg; pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>); vg.setInputCloud (cloud); vg.setLeafSize (0.01f, 0.01f, 0.01f); vg.filter (*cloud_filtered); std::cout << "PointCloud after filtering has: " << cloud_filtered->size () << " data points." << std::endl; //* // Create the segmentation object for the planar model and set all the parameters 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 nr_points = (int) cloud_filtered->size (); while (cloud_filtered->size () > 0.3 * nr_points) { // Segment the largest planar component from the remaining cloud seg.setInputCloud (cloud_filtered); seg.segment (*inliers, *coefficients); if (inliers->indices.size () == 0) { std::cout << "Could not estimate a planar model for the given dataset." << std::endl; break; } // Extract the planar inliers from the input cloud pcl::ExtractIndices<pcl::PointXYZ> extract; extract.setInputCloud (cloud_filtered); extract.setIndices (inliers); extract.setNegative (false); // Get the points associated with the planar surface extract.filter (*cloud_plane); std::cout << "PointCloud representing the planar component: " << cloud_plane->size () << " data points." << std::endl; // Remove the planar inliers, extract the rest extract.setNegative (true); extract.filter (*cloud_f); *cloud_filtered = *cloud_f; } // Creating the KdTree object for the search method of the extraction pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>); tree->setInputCloud (cloud_filtered); std::vector<pcl::PointIndices> cluster_indices; pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec; ec.setClusterTolerance (0.02); // 2cm ec.setMinClusterSize (100); ec.setMaxClusterSize (25000); ec.setSearchMethod (tree); ec.setInputCloud (cloud_filtered); ec.extract (cluster_indices); int j = 0; for (const auto& cluster : cluster_indices) { pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZ>); for (const auto& idx : cluster.indices) { cloud_cluster->push_back((*cloud_filtered)[idx]); } //* cloud_cluster->width = cloud_cluster->size (); cloud_cluster->height = 1; cloud_cluster->is_dense = true; std::cout << "PointCloud representing the Cluster: " << cloud_cluster->size () << " data points." << std::endl; std::stringstream ss; ss << std::setw(4) << std::setfill('0') << j; writer.write<pcl::PointXYZ> ("cloud_cluster_" + ss.str () + ".pcd", *cloud_cluster, false); //* j++; } return (0); }

参考:Euclidean Cluster Extraction — Point Cloud Library 0.0 documentation

http://www.jsqmd.com/news/1177738/

相关文章:

  • Winhance:免费开源Windows系统优化工具的安全使用指南
  • Typora 跨版本(0.9.x-1.x)界面适配:解决4K宽屏下编辑区域过窄问题
  • 2026重庆黄金回收白银回收铂金回收靠谱临街实体公安备案支持到店核验门店联系方式推荐
  • Centos7配置国内yum源
  • ArcGIS Pro 3.2 三维地质建模实战:7步从钻孔数据生成MultiPatch地质体
  • AI医疗应用的技术边界与伦理实践:从视觉刺激到真实疗效
  • 金融数据分析入门:先学财报、指标还是工具?
  • BiliRoamingX:解锁B站完整观影体验的三大核心解决方案
  • 2026年7月最新江诗丹顿深圳罗湖万象城维修保养服务电话 - 江诗丹顿官方服务中心
  • 从Swagger手写到AI秒生成:ChatGPT驱动API文档升级(附GitHub高星开源工具链+校验脚本)
  • 社区居家养老服务平台开题报告
  • 从源码编译完整版Qt:包含QtWebEngine与QDoc的实战指南
  • PyInstaller 与 Nuitka 打包 EXE 逆向对比:2 种工具源码保护强度实测
  • Ubuntu下PlatformIO下载极慢?一招配置proxy,完美解决ESP32依赖包下载超时!
  • 用原生 JavaScript 实现一个基础代谢率(BMR)在线计算器:从公式到落地
  • 2.算法效率的核心密码:时间复杂度和空间复杂度详解
  • NestOS官网源代码解析:构建现代化容器主机操作系统网站的技术实践
  • 江诗丹顿官方换电池价格查询|热线及完整维修地址权威信息公告(2026年7月最新) - 江诗丹顿服务中心
  • Java Web人事管理系统实战:JSP+Servlet+MVC架构完整开发指南
  • 英伟达出手:通用机器人为何总在现实中「翻车」?
  • Nacos 2.3.2 Windows 单机部署:3步配置MySQL持久化与鉴权启动
  • openEuler hygon-kernel深度解析:国产海光处理器内核优化完全指南
  • GCC16倒逼C++生态升级:分层兼容架构与项目迁移实战
  • WeChat 与微信数据导出对比:2版本差异解析,通讯录等5类数据仅限海外版
  • OpenAI创始人奥尔特曼:至少到目前为止,我相当确信,AI总体上是在创造就业岗位
  • 影刀RPA 变量使用进阶:list-dict-自定义对象
  • 导师说论文有AI痕迹,有哪些真正亲测好用的的降AIGC软件推荐?
  • 高精度信号采集系统设计与优化:AD7175-8与TM4C129EKCPDT应用
  • 2026萍乡漏水检测维修口碑榜TOP5权威推荐:正规防水补漏公司甄选-卫生间/厨房/阳台/屋顶/地下室渗漏水精准查漏:房屋防水补漏避坑指南 - 安佳防水
  • NoteExpress 3.8 文献管理实战:10篇SCI论文的引用格式自动生成与3步定稿流程