PCL-基于超体聚类的LCCP点云分割

目录

  • 一、LCCP方法
  • 二、代码实现
  • 三、实验结果
  • 四、总结
  • 五、相关链接

一、LCCP方法

LCCP指的是Local Convexity-Constrained Patch,即局部凸约束补丁的意思。LCCP方法的基本思想是在图像中找到局部区域内的凸结构,并将这些结构用于分割图像或提取特征。这种方法可以帮助识别图像中的凸物体,并对它们进行分割。LCCP方法通常结合了空间和法线信息,以提高图像分割的准确性和稳定性。

LCCP算法大致可以分成两个部分:1.基于超体聚类的过分割。2.在超体聚类的基础上再聚类。
该方法流程图如下:
在这里插入图片描述

二、代码实现

#include <iostream>
#include <pcl/ModelCoefficients.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/filters/extract_indices.h>
#include <boost/thread/thread.hpp>
#include <stdlib.h>
#include <cmath>
#include <limits.h>
#include <boost/format.hpp>
#include <pcl/console/parse.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/point_cloud_color_handlers.h>
#include <pcl/filters/passthrough.h>
#include <pcl/segmentation/supervoxel_clustering.h>
#include <pcl/segmentation/lccp_segmentation.h>
#include <vtkPolyLine.h> 
#include <pcl/point_cloud.h>
#include <pcl/segmentation/supervoxel_clustering.h>
#include <pcl/visualization/pcl_visualizer.h>using namespace std;
typedef pcl::PointXYZ PointT;
typedef pcl::LCCPSegmentation<PointT>::SupervoxelAdjacencyList SuperVoxelAdjacencyList;
//邻接线条可视化
void addSupervoxelConnectionsToViewer(pcl::PointXYZRGBA& supervoxel_center, pcl::PointCloud<pcl::PointXYZRGBA>& adjacent_supervoxel_centers,std::string supervoxel_name, pcl::visualization::PCLVisualizer::Ptr& viewer)
{vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();vtkSmartPointer<vtkPolyLine> polyLine = vtkSmartPointer<vtkPolyLine>::New();for (auto adjacent_itr = adjacent_supervoxel_centers.begin(); adjacent_itr != adjacent_supervoxel_centers.end(); ++adjacent_itr){points->InsertNextPoint(supervoxel_center.data);points->InsertNextPoint(adjacent_itr->data);}vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();polyData->SetPoints(points);polyLine->GetPointIds()->SetNumberOfIds(points->GetNumberOfPoints());for (unsigned int i = 0; i < points->GetNumberOfPoints(); i++)polyLine->GetPointIds()->SetId(i, i);cells->InsertNextCell(polyLine);polyData->SetLines(cells);viewer->addModelFromPolyData(polyData, supervoxel_name);
}int main(int argc, char** argv)
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);pcl::PCDReader reader;// 读入点云PCD文件reader.read("E:****.pcd", *cloud);cout << "Point cloud data: " << cloud->points.size() << " points" << endl;pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);pcl::PointIndices::Ptr inliers(new pcl::PointIndices);// 创建分割对象pcl::SACSegmentation<pcl::PointXYZ> seg;// 可选择配置,设置模型系数需要优化seg.setOptimizeCoefficients(true);// 必须配置,设置分割的模型类型、所用随机参数估计方法seg.setModelType(pcl::SACMODEL_PLANE);seg.setMethodType(pcl::SAC_RANSAC);seg.setDistanceThreshold(0.02);// 距离阈值 单位m。距离阈值决定了点被认为是局内点时必须满足的条件//seg.setDistanceThreshold(0.15);// 距离阈值 单位m。距离阈值决定了点被认为是局内点时必须满足的条件//距离阈值表示点到估计模型的距离最大值。seg.setInputCloud(cloud);//输入点云seg.segment(*inliers, *coefficients);//实现分割,并存储分割结果到点集合inliers及存储平面模型系数coefficientsif (inliers->indices.size() == 0){PCL_ERROR("Could not estimate a planar model for the given dataset.");return (-1);}//***********************************************************************//-----------输出平面模型的系数 a,b,c,d-----------cout << "Model coefficients: " << coefficients->values[0] << " "<< coefficients->values[1] << " "<< coefficients->values[2] << " "<< coefficients->values[3] << endl;cout << "Model inliers: " << inliers->indices.size() << endl;//***********************************************************************// 提取地面pcl::ExtractIndices<pcl::PointXYZ> extract;extract.setInputCloud(cloud);extract.setIndices(inliers);extract.filter(*cloud_filtered);cout << "Ground cloud after filtering: " << endl;cout << *cloud_filtered << std::endl;pcl::PCDWriter writer;writer.write<pcl::PointXYZ>("3dpoints_ground.pcd", *cloud_filtered, false);// 提取除地面外的物体extract.setNegative(true);extract.filter(*cloud_filtered);cout << "Object cloud after filtering: " << endl;cout << *cloud_filtered << endl;//writer.write<pcl::PointXYZ>(".pcd", *cloud_filtered, false);// 点云可视化boost::shared_ptr<pcl::visualization::PCLVisualizer>viewer0(new pcl::visualization::PCLVisualizer("显示点云"));//左边窗口显示输入的点云,右边的窗口显示分割后的点云int v1(0), v2(0);viewer0->createViewPort(0, 0, 0.5, 1, v1);viewer0->createViewPort(0.5, 0, 1, 1, v2);viewer0->setBackgroundColor(0, 0, 0, v1);viewer0->setBackgroundColor(0.3, 0.3, 0.3, v2);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color_in(cloud, 255, 0, 0);viewer0->addPointCloud<pcl::PointXYZ>(cloud, color_in, "cloud_in", v1);viewer0->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "cloud_in", v1);viewer0->addPointCloud<pcl::PointXYZ>(cloud_filtered, "cloud_out", v2);viewer0->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 255, 0, "cloud_out", v2);viewer0->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "cloud_out", v2);while (!viewer0->wasStopped()){viewer0->spinOnce(100);boost::this_thread::sleep(boost::posix_time::microseconds(1000));}//***********************************************************************//超体聚类 float voxel_resolution = 0.01f;    // 设置体素大小,该设置决定底层八叉树的叶子尺寸float seed_resolution = 0.15f;    // 设置种子大小,该设置决定超体素的大小float color_importance = 0.0f;    // 设置颜色在距离测试公式中的权重,即颜色影响超体素分割结果的比重。 真实点云都是一个颜色,所以这个参数无作用float spatial_importance = 0.9f;  // 设置空间距离在距离测试公式中的权重,较高的值会构建非常规则的超体素,较低的值产生的体素会按照法线float normal_importance = 4.0f;   // 设置法向量的权重,即表面法向量影响超体素分割结果的比重。bool use_single_cam_transform = false;bool use_supervoxel_refinement = false;unsigned int k_factor = 0;//voxel_resolution is the resolution (in meters) of voxels used、seed_resolution is the average size (in meters) of resulting supervoxels  pcl::SupervoxelClustering<PointT> super(voxel_resolution, seed_resolution);super.setUseSingleCameraTransform(use_single_cam_transform);super.setInputCloud(cloud_filtered); //cloud_filteredsuper.setColorImportance(color_importance);//Set the importance of spatial distance for supervoxels.super.setSpatialImportance(spatial_importance);//Set the importance of scalar normal product for supervoxels. super.setNormalImportance(normal_importance);std::map<uint32_t, pcl::Supervoxel<PointT>::Ptr> supervoxel_clusters;super.extract(supervoxel_clusters);std::multimap<uint32_t, uint32_t> supervoxel_adjacency;super.getSupervoxelAdjacency(supervoxel_adjacency);pcl::PointCloud<pcl::PointNormal>::Ptr sv_centroid_normal_cloud = pcl::SupervoxelClustering<PointT>::makeSupervoxelNormalCloud(supervoxel_clusters);cout << "超体素分割的体素个数为:" << supervoxel_clusters.size() << endl;// 获取点云对应的超体素分割标签pcl::PointCloud<pcl::PointXYZL>::Ptr supervoxel_cloud = super.getLabeledCloud();pcl::visualization::PCLVisualizer::Ptr viewer1(new pcl::visualization::PCLVisualizer("VCCS"));viewer1->setWindowName("超体素分割");viewer1->addPointCloud(supervoxel_cloud, "超体素分割");viewer1->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "超体素分割");viewer1->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_OPACITY, 0.5, "超体素分割");//-----------------------------------------获得体素点云的邻接单元----------------------------------------------multimap<uint32_t, uint32_t>SupervoxelAdjacency;super.getSupervoxelAdjacency(SupervoxelAdjacency);for (auto label_itr = SupervoxelAdjacency.cbegin(); label_itr != SupervoxelAdjacency.cend();){uint32_t super_label = label_itr->first;//获取体素单元的标签pcl::Supervoxel<pcl::PointXYZ>::Ptr super_cloud = supervoxel_clusters.at(super_label);//把对应标签内的点云、体素质心、以及质心对应的法向量提取出来pcl::PointCloud<pcl::PointXYZRGBA> adjacent_supervoxel_centers;for (auto adjacent_itr = SupervoxelAdjacency.equal_range(super_label).first; adjacent_itr != SupervoxelAdjacency.equal_range(super_label).second; ++adjacent_itr){pcl::Supervoxel<pcl::PointXYZ>::Ptr neighbor_supervoxel = supervoxel_clusters.at(adjacent_itr->second);adjacent_supervoxel_centers.push_back(neighbor_supervoxel->centroid_);}std::stringstream ss;ss << "supervoxel_" << super_label;addSupervoxelConnectionsToViewer(super_cloud->centroid_, adjacent_supervoxel_centers, ss.str(), viewer1);label_itr = SupervoxelAdjacency.upper_bound(super_label);}// 等待直到可视化窗口关闭while (!viewer1->wasStopped()){viewer1->spinOnce(100);boost::this_thread::sleep(boost::posix_time::microseconds(1000));}//return 0;//***********************************************************************//LCCP分割float concavity_tolerance_threshold = 10;float smoothness_threshold = 0.8;uint32_t min_segment_size = 0;bool use_extended_convexity = false;bool use_sanity_criterion = false;pcl::LCCPSegmentation<PointT> lccp;lccp.setConcavityToleranceThreshold(concavity_tolerance_threshold);//CC效验beta值lccp.setSmoothnessCheck(true, voxel_resolution, seed_resolution, smoothness_threshold);lccp.setKFactor(k_factor);               //CC效验的k邻点lccp.setInputSupervoxels(supervoxel_clusters, supervoxel_adjacency);lccp.setMinSegmentSize(min_segment_size);//最小分割尺寸lccp.segment();pcl::PointCloud<pcl::PointXYZL>::Ptr sv_labeled_cloud = super.getLabeledCloud();pcl::PointCloud<pcl::PointXYZL>::Ptr lccp_labeled_cloud = sv_labeled_cloud->makeShared();lccp.relabelCloud(*lccp_labeled_cloud);SuperVoxelAdjacencyList sv_adjacency_list;lccp.getSVAdjacencyList(sv_adjacency_list);pcl::visualization::PCLVisualizer::Ptr viewer2(new pcl::visualization::PCLVisualizer("LCCP超体素分割"));viewer2->setWindowName("LCCP超体素分割");viewer2->addPointCloud(lccp_labeled_cloud, "LCCP超体素分割");viewer2->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "LCCP超体素分割");viewer2->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_OPACITY, 0.5, "LCCP超体素分割");// 等待直到可视化窗口关闭while (!viewer2->wasStopped()){viewer2->spinOnce(100);boost::this_thread::sleep(boost::posix_time::microseconds(1000));}return 0;}

三、实验结果

原数据
原数据
去除地面后
在这里插入图片描述
超体聚类过分割
在这里插入图片描述
LCCP分割
在这里插入图片描述

四、总结

从实验结果来看,LCCP算法在相似物体场景分割方面有着较好的表现,对于颜色类似但棱角分明的物体可使用该算法。

五、相关链接

[1]PCL-低层次视觉-点云分割(超体聚类)
[2]PCL_使用LCCP进行点云分割

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/875348.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DolphinScheduler学习

1.查看文档 点击访问&#xff1a;https://dolphinscheduler.apache.org/zh-cn/docs 我们可以看到相关的文档简介里有 介绍 DolphinScheduler是Apache DolphinScheduler 是一个分布式易扩展的可视化DAG工作流任务调度开源系统。适用于企业级场景&#xff0c;提供了一个可视化…

太原高校大学智能制造实验室数字孪生可视化系统平台建设项目验收

随着科技的不断进步&#xff0c;智能制造已经成为推动制造业转型升级的重要力量。太原高校大学智能制造实验室紧跟时代步伐&#xff0c;积极推进数字孪生可视化系统平台的建设&#xff0c;并于近日圆满完成了项目的验收工作。这一里程碑式的成果&#xff0c;不仅标志着实验室在…

uniapp安卓plus原生选择系统文件

uniapp安卓plus原生选择系统文件 效果&#xff1a; 组件代码&#xff1a; <template xlang"wxml" minapp"mpvue"><view></view> </template> <script>export default {name: file-manager,props: {},data() {return {is…

靶场实战 _ ATTCK 实战 Vulnstack 红队

环境配置 网络拓扑图 (仅供参考) 攻击机&#xff1a;kali ip:192.168.111.5靶机&#xff1a;web-centos 外网ip:192.168.111.10 内网ip:192.168.93.100web1-ubuntu ip: 192.168.93.120PC ip: 192.168.93.30win 2008 ip:192.168.93.20win 2012 ip:192.168.93.10 信息搜集 端口…

【C++】string类(下)

个人主页~ string类&#xff08;上&#xff09; string类 二、模拟实现string类1、头文件string.h2、常见构造3、容量函数4、访问及遍历5、类对象修改6、流插入流提取重载 二、模拟实现string类 今天我们来实现一下上篇文章中详细介绍过的接口 1、头文件string.h #pragma onc…

Redis的应用场景及类型

目录 一、Redis的应用场景 1、限流 2、分布式锁 3、点赞 4、消息队列 二、Redis类型的命令及用法 1、String类型 2、Hash类型 3、List类型 4、Set类型 5、Zset类型 6、Redis工具类 Redis使用缓存的目的就是提升读写性能 实际业务场景下&#xff0c;我们就可以把 Mys…

【常微分方程】

框架 常微分方程的概念一阶微分方程可变离分量齐次方程一阶线性微分方程可降阶的高阶微分方程二阶常系数齐次线性微分方程二阶常系数非齐次线性微分方程 讲解 【1】 常微分方程&#xff1a;是微分方程的特殊情况&#xff1b; 阶&#xff1a;是方程未知函数的最高阶导数的阶数&…

ElementUI,修改el-table中的数据,视图无法及时更新

需求&#xff1a;点击table表格中的“修改”之后&#xff0c;当前行变为可输入状态的行&#xff0c;点击“确定”后变为普通表格&#xff1b; 先贴上已经完美解决问题的代码 实现代码&#xff1a; <section><div style"display: flex;justify-content: space-b…

爬虫学习1:初学者简单了解爬虫的基本认识和操作(详细参考图片)

爬虫 定义&#xff1a;爬虫&#xff08;Web Crawler 或 Spider&#xff09;是一种自动访问互联网上网页的程序&#xff0c;其主要目的是索引网页内容&#xff0c;以便搜索引擎能够快速检索到相关信息。以下是爬虫的一些关键特性和功能&#xff1a; 自动化访问&#xff1a;爬虫能…

【React】事件绑定:深入解析高效处理用户交互的最佳实践

文章目录 一、什么是事件绑定&#xff1f;二、基本事件绑定三、绑定 this 上下文四、传递参数五、事件对象六、事件委托七、常见事件处理八、优化事件处理 React 是现代前端开发中最受欢迎的框架之一&#xff0c;其组件化和高效的状态管理能力使得构建复杂的用户界面变得更加容…

嵌入式MCU固件的几种Flash划分方式详解

通过OTA远程等方式下载的程序,其实还需要提前下载bootloader程序,才能进一步下载APP程序。 今天就来说说通过OTA方式升级固件时,几种flash划分方式。 独立型 所谓独立型就是专门划出一部分闪存(Flash)空间用来存储引导程序(BootLoader)。 如下图: BootLoader:引导…

扫地机器人离线语音识别芯片,工业级智能交互ic,NRK3301

随着科技的飞速发展&#xff0c;智能家居已成为人们追求高品质生活的新趋势。扫地机器人&#xff0c;作为智能家居的重要一员&#xff0c;正逐步从简单的清扫工具进化为具备高度智能的家居助手。 在这一背景下&#xff0c;离线语音识别技术显得尤为重要。传统的扫地机器人大多依…

问题记录-Spring Security- bean httpSecurity not found

问题描述 最近使用Security的时候报了下面的错误&#xff1a; 配置如下&#xff1a; EnableWebSecurity Slf4j public class SecurityConfig {Resourceprivate CustUserService custUserService;Beanpublic AuthenticationProvider authenticationProvider() {return new A…

element-plus时间组件el-date-picker只能选择当前及之前日期

<el-date-picker v-model"timeVal" type"daterange" value-format"YYYY-MM-DD" range-separator"To" start-placeholder"开始时间" end-placeholder"结束时间" />默认是这样的&#xff0c;需要绑定disabled…

一款基于Cortex-M0+的单片机音频编解码 - CJC2100

USBCodec芯片可以对数字音频信号进行多种处理&#xff0c;例如增加音量、均衡调节、音效处理等。这些处理可以通过耳机的控制按钮来实现&#xff0c;让用户可以根据自己的喜好来调整音频效果。USBCodec芯片还可以控制噪声和失真的水平&#xff0c;以提供高品质的音频输出。噪声…

[IMX6ULL]移植NXP Linux Kernel 5.15

移植NXP Linux Kernel 5.15 2024-7-7 hongxi.zhu 1. 下载NXP Linux Kernel 5.15 仓库[nxp-imx/linux-imx] git clone -b lf-5.15.y https://github.com/nxp-imx/linux-imx.git 2. 编译NXP Linux Kernel 5.15 make ARCHarm CROSS_COMPILEarm-linux-gnueabihf- distclean make…

【3D 重建】NeRF,3D Gaussian Splatting

文章目录 AI 甘安捏【入门介绍&#xff0c;形象生动】3D 重建技術 (一): 什麼是 3D 重建 (3D Reconstruction)&#xff1f;為什麼需要 3D 重建&#xff1f;【NeRF&#xff0c;3D Gaussian Splatting简介】3D 重建技術 (二): NeRF&#xff0c;AI技術革命 -- 用神經網路把場景「背…

【维普网】收录的电子刊汇总(部分省市职称评审认可)

《中国科技期刊数据库&#xff08;文摘版&#xff09;医药卫生》是经国家新闻出版总署批准&#xff0c;科技部西南信息中心主管、重庆维普资讯有限公司主办的连续型电子出版物。国内刊号&#xff1a;50-9212/R&#xff0c;国际刊号&#xff1a; 1671-5608。主要栏目为影像与检验…

Cornerstone3D 演示库恢复更新啦~

前言 从0上手Cornerstone3D系列的git库终于有时间更新优化了一版。主要更新以下内容&#xff1a; ✨ vue2更新至vue3版本&#xff0c;代码迁移为vue3组合式写法 ✨ UI风格升级&#xff0c;新增交互提示 ✨ 修复页面切换报错问题 ✨ … 关于git库 &#x1f3af; 地址&…

el-upload照片墙自定义上传多张图片(手动一次性上传多张图片)包含图片回显,删除

需求&#xff1a;el-upload照片墙自定义上传多张图片&#xff08;手动一次性上传多张图片&#xff09;包含图片回显&#xff0c;删除&#xff0c;预览&#xff0c;在网上看了很多&#xff0c;都没有说怎么把数据转为file格式的&#xff0c;找了很久最终实现&#xff0c; 难点&a…