[点云分割] 条件欧氏聚类分割
介绍
条件欧氏聚类分割是一种基于欧氏距离和条件限制的点云分割方法。它通过计算点云中点与点之间的欧氏距离,并结合一定的条件限制来将点云分割成不同的区域或聚类。
在条件欧氏聚类分割中,通常会定义以下两个条件来判断两个点是否属于同一个聚类:
-
距离条件:两个点之间的欧氏距离是否小于设定的阈值。如果两个点之间的距离小于阈值,则认为它们是相邻的,属于同一个聚类。
-
条件限制:除了距离条件外,还可以根据其他的条件来限制聚类的形成。例如,可以限制点的法线方向、颜色、强度等属性的相似性,只有当这些属性满足一定的条件时,两个点才被认为是相邻的,属于同一个聚类。
条件欧氏聚类分割的步骤通常包括以下几个步骤:
-
初始化:设置距离阈值和其他条件限制的参数。
-
遍历点云:对于点云中的每个点,依次进行以下操作:
-
计算当前点与其周围点之间的欧氏距离。
-
根据距离条件和其他条件限制,判断当前点是否与周围点属于同一个聚类。如果是,则将它们标记为同一个聚类。
-
继续遍历其他未被标记的点,重复上述操作,直到所有点都被遍历完。
-
-
输出聚类结果:将同一个聚类的点标记为一组,形成不同的聚类簇。
效果

代码
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/console/time.h>#include <pcl/filters/voxel_grid.h>
#include <pcl/features/normal_3d.h>
#include <pcl/segmentation/conditional_euclidean_clustering.h>typedef pcl::PointXYZI PointTypeIO;
typedef pcl::PointXYZINormal PointTypeFull;bool enforceIntensitySimilarity (const PointTypeFull& point_a, const PointTypeFull& point_b, float /*squared_distance*/){if (std::abs (point_a.intensity - point_b.intensity) < 5.0f)return (true);elsereturn (false);}bool enforceNormalOrIntensitySimilarity (const PointTypeFull& point_a, const PointTypeFull& point_b, float /*squared_distance*/)
{// 将点云的法线信息转换未Eigen库的Eigen:vector3f类型Eigen::Map<const Eigen::Vector3f> point_a_normal = point_a.getNormalVector3fMap (), point_b_normal = point_b.getNormalVector3fMap ();// 判断点云A的点云B的强度差是否小于5.0if (std::abs (point_a.intensity - point_b.intensity) < 5.0f)return (true);// 判断点云A和点云B的法线夹角的余弦值是否大于30°对应的余弦值,即判断法线相似性if (std::abs (point_a_normal.dot (point_b_normal)) > std::cos (30.0f / 180.0f * static_cast<float> (M_PI)))return (true);return (false);
}bool customRegionGrowing (const PointTypeFull& point_a, const PointTypeFull& point_b, float squared_distance)
{Eigen::Map<const Eigen::Vector3f> point_a_normal = point_a.getNormalVector3fMap (), point_b_normal = point_b.getNormalVector3fMap ();// 根据平方距离的大小,判断生长条件if (squared_distance < 10000){if (std::abs (point_a.intensity - point_b.intensity) < 8.0f)return (true);if (std::abs (point_a_normal.dot (point_b_normal)) > std::cos (30.0f / 180.0f * static_cast<float> (M_PI)))return (true);}else{if (std::abs (point_a.intensity - point_b.intensity) < 3.0f)return (true);}return (false);
}int main ()
{// Data containers usedpcl::PointCloud<PointTypeIO>::Ptr cloud_in (new pcl::PointCloud<PointTypeIO>), cloud_out (new pcl::PointCloud<PointTypeIO>);pcl::PointCloud<PointTypeFull>::Ptr cloud_with_normals (new pcl::PointCloud<PointTypeFull>);pcl::IndicesClustersPtr clusters (new pcl::IndicesClusters), small_clusters (new pcl::IndicesClusters), large_clusters (new pcl::IndicesClusters);pcl::search::KdTree<PointTypeIO>::Ptr search_tree (new pcl::search::KdTree<PointTypeIO>);pcl::console::TicToc tt;// Load the input point cloudstd::cerr << "Loading...\n", tt.tic ();pcl::io::loadPCDFile ("Statues_4.pcd", *cloud_in);std::cerr << ">> Done: " << tt.toc () << " ms, " << cloud_in->size () << " points\n";// Downsample the cloud using a Voxel Grid classstd::cerr << "Downsampling...\n", tt.tic ();pcl::VoxelGrid<PointTypeIO> vg;vg.setInputCloud (cloud_in);vg.setLeafSize (80.0, 80.0, 80.0);vg.setDownsampleAllData (true);vg.filter (*cloud_out);std::cerr << ">> Done: " << tt.toc () << " ms, " << cloud_out->size () << " points\n";// Set up a Normal Estimation class and merge data in cloud_with_normalsstd::cerr << "Computing normals...\n", tt.tic ();pcl::copyPointCloud (*cloud_out, *cloud_with_normals);pcl::NormalEstimation<PointTypeIO, PointTypeFull> ne;ne.setInputCloud (cloud_out);ne.setSearchMethod (search_tree);ne.setRadiusSearch (300.0);ne.compute (*cloud_with_normals);std::cerr << ">> Done: " << tt.toc () << " ms\n";// Set up a Conditional Euclidean Clustering classstd::cerr << "Segmenting to clusters...\n", tt.tic ();pcl::ConditionalEuclideanClustering<PointTypeFull> cec (true);cec.setInputCloud (cloud_with_normals);cec.setConditionFunction (&customRegionGrowing);cec.setClusterTolerance (500.0);cec.setMinClusterSize (cloud_with_normals->size () / 1000);cec.setMaxClusterSize (cloud_with_normals->size () / 5);cec.segment (*clusters);cec.getRemovedClusters (small_clusters, large_clusters);std::cerr << ">> Done: " << tt.toc () << " ms\n";// Using the intensity channel for lazy visualization of the outputfor (const auto& small_cluster : (*small_clusters))for (const auto& j : small_cluster.indices)(*cloud_out)[j].intensity = -2.0;for (const auto& large_cluster : (*large_clusters))for (const auto& j : large_cluster.indices)(*cloud_out)[j].intensity = +10.0;for (const auto& cluster : (*clusters)){int label = rand () % 8;for (const auto& j : cluster.indices)(*cloud_out)[j].intensity = label;}// Save the output point cloudstd::cerr << "Saving...\n", tt.tic ();pcl::io::savePCDFile ("output.pcd", *cloud_out);std::cerr << ">> Done: " << tt.toc () << " ms\n";return (0);
}
相关文章:
[点云分割] 条件欧氏聚类分割
介绍 条件欧氏聚类分割是一种基于欧氏距离和条件限制的点云分割方法。它通过计算点云中点与点之间的欧氏距离,并结合一定的条件限制来将点云分割成不同的区域或聚类。 在条件欧氏聚类分割中,通常会定义以下两个条件来判断两个点是否属于同一个聚类&…...
Spring事务粒度优化与传播机制
在Spring事务中,我们通常会为了控制事务粒度,会把它进行拆分,为了避免大事务执行太久,占用资源太多,导致资源利用率低的问题。 我们曾经就遇到老系统因为大事务,把服务打死了。 问题出在一个大事务中有一…...
MySQL 基于成本的优化
其实在MySQL中⼀条查询语句的执⾏成本是由下边这两个⽅⾯组成的: I/O成本 我们的表经常使⽤的MyISAM、InnoDB存储引擎都是将数据和索引都存储到磁盘上的,当我们想查询表中的记录时,需要先把数据或者索引加载到内存中 然后再操作。这个从磁盘…...
【maven】【IDEA】idea中使用maven编译项目,报错java: 错误: 找不到符号 【2】
idea中使用maven编译项目,报错java: 错误: 找不到符号 错误状况展示: 如果报这种错,是因为项目中真的找不到报错的方法或者枚举 字段之类的,但实际是 : 点击 File Path...
AIGC,ChatGPT AI绘画 Midjourney 注册流程详细步骤
AI 绘画,Midjourney完成高清图片绘制,轻松掌握AI工具。 前期准备: ① 一个能使用的谷歌账号 ② 可以访问外网 Midjourney注册 1.进入midjourney官网https://www.midjourney.com 点击左下角”Join the Beta”,就可以注册,第一次使用的小伙伴会弹出提示,只需要点击Acc…...
万字解析设计模式之模板方法与解释器模式
一、模板方法模式 1.1概述 定义一个操作中算法的框架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 例如,去银行办理业务一般要经过以下4个流程:取号、排队、办理具体业…...
apipost接口200状态码,浏览器控制台500状态码
后端 url 登录login方法 login(){this.$refs.loginForm.validate(async valid > {if (!valid) return// 由于data属性是一个json对象,需要进行解构赋值{data:result},进行状态码判断const {data: result} await this.$http.post(/api/doLogin,this.…...
Instant Web API .Net Core Crack
Instant Web API .Net Core 是立即构建即时数据库 Web API,无需编码。在几分钟内生成您的 Web API,以更快地构建应用程序。使用 VS 2022 和 Entity Framework Core 为任何 MS SQL 数据库生成 Web API。 新功能 - 使用 Visual Studio 2022 为 PostgreSQL …...
vue项目使用easyplayer播放m3u8直播推流
官网 青犀视频 代码库 / 示例 / demo EasyPlayer 示例效果: 项目背景如图 后端给了m3u8的直播地址 协议是 hls / flv 市面上很多第三方热门播放库都可以完成该多屏播放方式 如Video.js 问题在于 分多屏时 会存在性能问题 并且关闭播放器后 即便删除Dom或调用停…...
Python报错:AttributeError(类属性、实例属性)
Python报错:AttributeError(类属性、实例属性) Python报错:AttributeError 这个错误就是说python找不到对应的对象的属性,百度后才发现竟然是初始化类的时候函数名写错了 __init__应该有2条下划线,如果只有…...
vue+springboot读取git的markdown文件并展示
前言 最近,在研究一个如何将我们git项目的MARKDOWN文档获取到,并且可以展示到界面通过检索查到,于是经过几天的摸索,成功的研究了出来 本次前端vue使用的是Markdown-it Markdown-it 是一个用于解析和渲染 Markdown 标记语言的 …...
多功能PHP图床源码:Lsky Pro开源版v2.1 – 最新兰空图床
Lsky Pro是一款功能丰富的在线图片上传和管理工具,即兰空图床。它不仅可以作为个人云相册,还可以用作写作贴图库。 该程序的初始版本于2017年10月由ThinkPHP 5开发,经过多个版本的迭代,于2022年3月发布了全新的2.0版本。 Lsky Pro…...
Hive内置表生成函数
Hive内置UDTF 1、UDF、UDAF、UDTF简介2、Hive内置UDTF 1、UDF、UDAF、UDTF简介 在Hive中,所有的运算符和用户定义函数,包括用户定义的和内置的,统称为UDF(User-Defined Functions)。如下图所示: UDF官方文档…...
电源控制系统架构(PCSA)之电源控制框架概览
目录 6 电源控制框架 6.1 电源控制框架概述 6.1.1 电源控制框架低功耗接口 6.1.2 电源控制框架基础设施组件 6 电源控制框架 电源控制框架是标准基础设施组件、接口和相关方法的集合,可用于构建SoC电源管理所需的基础设施。 本章介绍框架的主要组件和低功耗接…...
Sentinel 监控数据持久化(mysql)
Sentinel 实时监控仅存储 5 分钟以内的数据,如果需要持久化,需要通过调用实时监控接口来定制,即自行扩展实现 MetricsRepository 接口(修改 控制台源码)。 本文通过使用Mysql持久化监控数据。 1.构建存储表(…...
基于法医调查算法优化概率神经网络PNN的分类预测 - 附代码
基于法医调查算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于法医调查算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于法医调查优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要:针对PNN神…...
canvas高级动画001:文字瀑布流
canvas实例应用100 专栏提供canvas的基础知识,高级动画,相关应用扩展等信息。 canvas作为html的一部分,是图像图标地图可视化的一个重要的基础,学好了canvas,在其他的一些应用上将会起到非常重要的帮助。 文章目录 示例…...
抽象类, 接口, Object类 ---java
目录 一. 抽象类 1.1 抽象类概念 1.2 抽象类语法 1.3 抽象类特性 1.4 抽象类的作用 二. 接口 2.1 接口的概念 2.2 语法规则 2.3 接口的使用 2.4 接口间的继承 2.5 抽象类和接口的区别 三. Object类 3.1 toString() 方法 3.2 对象比较equals()方法 3.3 hash…...
SOAP 协议和 HTTP 协议:深入解读与对比
SOAP 和 HTTP 协议 SOAP 协议 SOAP( Simple Object Access Protocol)是一种用于在节点之间交换结构化数据的网络协议。它使用XML格式来传输消息。它在 HTML 和 SMTP 等应用层协议的基础上进行标记和传输。SOAP 允许进程在整个平台、语言和操作系统中进…...
Unity发布IOS后,使用xcode打包报错:MapFileParser.sh:Permissiondenied
1.错误提示 使用xcode打包错误提示:/Users/mymac/Desktop/myproject/MapFileParser.sh: Permission denied 2.解决方案 打开控制台输入:chmod ax /Users/mymac/Desktop/myproject/MapFileParser.sh。按回车键执行,然后重新使用xcode发布程序…...
跨越数字边界的文化守护者:AO3-Mirror-Site开源镜像网络革命
跨越数字边界的文化守护者:AO3-Mirror-Site开源镜像网络革命 【免费下载链接】AO3-Mirror-Site 项目地址: https://gitcode.com/gh_mirrors/ao/AO3-Mirror-Site 当一位中国同人创作者在深夜试图访问AO3却遭遇连接失败,当一位研究者需要引用特定同…...
Vectorizer完全指南:从位图到矢量的无损转换方案
Vectorizer完全指南:从位图到矢量的无损转换方案 【免费下载链接】vectorizer Potrace based multi-colored raster to vector tracer. Inputs PNG/JPG returns SVG 项目地址: https://gitcode.com/gh_mirrors/ve/vectorizer 在数字设计领域,图像…...
三步解锁你的加密音乐:ncmdumpGUI让网易云音乐重获自由
三步解锁你的加密音乐:ncmdumpGUI让网易云音乐重获自由 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换,Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 你是否曾遇到过这样的困境:在网…...
Steam成就管理器:游戏成就掌控的终极解决方案
Steam成就管理器:游戏成就掌控的终极解决方案 【免费下载链接】SteamAchievementManager A manager for game achievements in Steam. 项目地址: https://gitcode.com/gh_mirrors/st/SteamAchievementManager 还在为Steam游戏中那些遥不可及的成就而烦恼吗&a…...
NCMconverter终极指南:3步快速解密网易云音乐加密格式,释放你的音乐收藏
NCMconverter终极指南:3步快速解密网易云音乐加密格式,释放你的音乐收藏 【免费下载链接】NCMconverter NCMconverter将ncm文件转换为mp3或者flac文件 项目地址: https://gitcode.com/gh_mirrors/nc/NCMconverter 你是否曾经在网易云音乐下载了喜…...
Phi-mini-MoE-instruct企业落地:客服知识库问答+话术建议双模输出演示
Phi-mini-MoE-instruct企业落地:客服知识库问答话术建议双模输出演示 1. 项目概述 Phi-mini-MoE-instruct是一款轻量级混合专家(MoE)指令型小语言模型,专为企业级应用场景设计。该模型在多项基准测试中表现优异: 代…...
Elsevier Tracker:终极免费的学术投稿进度监控解决方案
Elsevier Tracker:终极免费的学术投稿进度监控解决方案 【免费下载链接】Elsevier-Tracker 项目地址: https://gitcode.com/gh_mirrors/el/Elsevier-Tracker 还在为Elsevier投稿系统的繁琐状态查询而烦恼吗?Elsevier Tracker是一款专为科研工作者…...
RWKV-7 (1.5B World)效果展示:1.5B参数模型的上下文长程依赖建模
RWKV-7 (1.5B World)效果展示:1.5B参数模型的上下文长程依赖建模 1. 惊艳的开场:小身材大能量 当大多数人还在追逐千亿参数大模型时,RWKV-7 1.5B World用实际表现证明:参数规模不是衡量模型能力的唯一标准。这个仅有1.5B参数的轻…...
万象视界灵坛环境部署:NVIDIA Container Toolkit兼容性配置指南
万象视界灵坛环境部署:NVIDIA Container Toolkit兼容性配置指南 1. 平台概述 万象视界灵坛(Omni-Vision Sanctuary)是一款基于OpenAI CLIP技术的高级多模态智能感知平台。该平台通过创新的像素风格界面设计,将复杂的语义对齐过程转化为直观的交互体验。…...
DAMOYOLO-S工程实践:实时手机检测-通用ONNX导出与跨平台部署
DAMOYOLO-S工程实践:实时手机检测-通用ONNX导出与跨平台部署 1. 引言:为什么你需要一个高效的手机检测模型? 想象一下,你正在开发一个智能会议室管理系统,需要自动检测参会者是否在会议期间违规使用手机。或者&#…...
