【PCL】(二十六)自定义条件的欧几里得聚类分割点云

(二十六)自定义条件的欧几里得聚类分割点云

以下代码实现自定义条件对点进行欧几里得聚类分割。

conditional_euclidean_clustering.cpp

#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;


/*条件函数的格式是固定的:
前两个输入参数的类型必须与pcl::ConditionalEuclideanClustering类中使用的模板化类型相同:包括当前种子点(第一个参数)和当前候选点(第二个参数)的点信息。
第三个输入参数必须是浮点值:为种子点和候选点之间的平方距离。
输出参数必须是布尔值。返回TRUE将把候选点合并到种子点的簇中,否则不会。*/

// 条件函数示例1
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);
      else
            return (false);
}
// 条件函数示例2
bool enforceNormalOrIntensitySimilarity (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 (std::abs (point_a.intensity - point_b.intensity) < 5.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);
      return (false);
}
// 条件函数示例3
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 used
      pcl::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 cloud
      std::cerr << "Loading...\n", tt.tic ();
      pcl::io::loadPCDFile ("Statues_5.pcd", *cloud_in);
      std::cerr << ">> Done: " << tt.toc () << " ms, " << cloud_in->size () << " points\n";

      // Downsample the cloud using a Voxel Grid class
      std::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_normals
      std::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 class
      std::cerr << "Segmenting to clusters...\n", tt.tic ();  
      pcl::ConditionalEuclideanClustering<PointTypeFull> cec (true);  // 类初始化为TRUE。这将允许提取太小或太大的簇
      cec.setInputCloud (cloud_with_normals);
      cec.setConditionFunction (&customRegionGrowing);  //   指定条件函数
      cec.setClusterTolerance (100.0);
      cec.setMinClusterSize (cloud_with_normals->size () / 1000);   // 占云总点不到0.1%的簇被认为太小。
      cec.setMaxClusterSize (cloud_with_normals->size () / 5);   // 占云总点20%以上的簇被认为太大。
      cec.segment (*clusters);
      // 太小的集群或太大的集群不会传递到主输出,而是可以在单独的pcl::Indices据容器中检索,但前提是类已用TRUE初始化。
      cec.getRemovedClusters (small_clusters, large_clusters); 
      std::cerr << ">> Done: " << tt.toc () << " ms\n";



      // Using the intensity channel for lazy visualization of the output
      for (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 cloud
      std::cerr << "Saving...\n", tt.tic ();
      pcl::io::savePCDFile ("output.pcd", *cloud_out);
      std::cerr << ">> Done: " << tt.toc () << " ms\n";

      return (0);
}

编译

cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(conditional_euclidean_clustering)

find_package(PCL 1.7 REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})

add_executable (conditional_euclidean_clustering conditional_euclidean_clustering.cpp)
target_link_libraries (conditional_euclidean_clustering ${PCL_LIBRARIES})

数据样本

编译并运行:

$ ./conditional_euclidean_clustering

在这里插入图片描述
太小的簇为蓝色的;太大的簇为红色的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android Studio编译及调试知识

文章目录 Android Studio编译kotlin项目Android Studio编译Java和kotlin混合项目的过程gradle打印详细错误信息&#xff0c;类似这种工具的使用Android apk 从你的代码到APK打包的过程&#xff0c;APK安装到你的Android手机上的过程&#xff0c;最后安装好的形态&#xff0c;以…

Mint_21.3 drawing-area和goocanvas的FB笔记(五)

FreeBASIC SDL图形功能 SDL - Simple DirectMedia Layer 是完整的跨平台系统&#xff0c;有自己的窗口、直接捕获键盘、鼠标和游戏操纵杆的事件&#xff0c;直接操作音频和CDROM&#xff0c;在其surface上可使用gfx, openGL和direct3D绘图。Window3.0时代&#xff0c;各种应用…

准谐振PWM控制器-能够实现多种保护功能FAN6921MRMY 功率因数控制器

高度集成的FAN6921MRMY将功率因数控制器 (PFC) 和准谐振 PWM 控制器相结合。集成提供了成本高效的设计&#xff0c;可减少外部组件数量。对于 PFC&#xff0c;FAN6921MRMY使用控制导通时间技术提供调节的直流输出电压&#xff0c;执行自然的功率因数校正。FAN6921MRMY使用创新的…

【代码随想录算法训练营Day40】01背包问题一维dp数组;二维dp数组(滚动数组);416.分割等和子集

文章目录 ❇️Day 41 第九章 动态规划 part04✴️今日任务❇️01背包问题 二维背包问题的区别暴力解法动规五部曲 ❇️01背包问题 一维二维转一维&#xff1a;滚动数组动规五部曲 ❇️416. 分割等和子集随想录思路自己的思路二维方法一维方法 自己的代码二维方法一维方法 ❇️D…

Kibana二次开发环境搭建

1 kibana环境搭建 1.1 搭建后端服务 &#xff08;1&#xff09;java环境安装 ElasticSearch运行需要java jdk支持。所以要先安装JAVA环境。由于ElasticSearch 5.x 往后依赖于JDK 1.8的&#xff0c;所以现在我们下载JDK 1.8或者更高版本。下载JDK1.8,下载完成后安装&#xff…

去电脑维修店修电脑需要注意什么呢?装机之家晓龙

每当电脑出现故障时&#xff0c;你无疑会感到非常沮丧。 如果计算机已过了保修期&#xff0c;您将无法享受制造商的免费保修服务。 这意味着您必须自费找到一家电脑维修店。 去电脑维修店并不容易。 大家一定要知道&#xff0c;电脑维修非常困难&#xff0c;尤其是笔记本电脑维…

qtCreator可以全局包含。VSqt中千万不能全局包含,你的控件头文件会自己变成<>括号,编译就报错

qtCreator可以全局包含。 VSqt中千万不能全局包含&#xff0c;你的控件头文件会自己变成&#xff1c;&#xff1e;括号&#xff0c;编译就报错

重建大师6.2版本的建模效果出现下图中模糊的情况,是什么原因?

可能是因为坐标原点设置的不对&#xff0c;图例中的三角网都出现了精度损失的问题。 坐标原点设置的具体操作&#xff1a;提交产品后&#xff0c;在弹出的界面&#xff0c;可以设定坐标原点。 重建大师是一款专为超大规模实景三维数据生产而设计的集群并行处理软件&#xff0…

第七届强网杯-PWN-【warmup】

文章目录 warmup libc 2.35检查IDA逆向maindeldelete_noteadd_noteshow_noteinput_numberread_16atoi __errno_location()相关解释prctl相关 思路高版本off by null利用技巧产生chunk extend泄露libc基地址泄露heap基地址修改放入tcachebin中的chunk的fd为stdout最后add两个chu…

AI大模型助力创意思维,拓展无限可能性

在当今快速发展的科技时代&#xff0c;人工智能大模型正逐渐成为我们生活中不可或缺的一部分。它们拥有强大的计算能力和学习能力&#xff0c;能够帮助我们解决许多复杂的问题&#xff0c;同时也可以为创意思维的拓展提供无限可能性。 人工智能大模型可以通过对海量数据的分析…

docker部署springboot jar包项目

docker部署springboot jar包项目 前提&#xff0c;服务器环境是docker环境&#xff0c;如果服务器没有安装docker&#xff0c;可以先安装docker环境。 各个环境安装docker&#xff1a; Ubuntu上安装Docker&#xff1a; ubuntu离线安装docker: CentOS7离线安装Docker&#xff1…

华为北向网管NCE开发教程(1)闭坑选接口协议

华为北向网管NCE开发教程&#xff08;1&#xff09;闭坑选接口协议 华为北向网管NCE开发教程&#xff08;2&#xff09;REST接口开发 华为北向网管NCE开发教程&#xff08;3&#xff09;CORBA协议开发 本文一是记录自己开发华为北向网管遇到的坑&#xff0c;二是给需要的人&…

Rocky Linux 的安装

1. 为什么用Rocky 因为CentOS不干了&#xff0c;这是CentOS的现状&#xff1a; CentOS Linux 8 在 2021 年底停止更新&#xff1b; CentOS Linux 7 用户较多&#xff0c;这个版本将在 2024 年 6 月 30 日停止支持&#xff1b; 未来社区不会再有 CentOS Linux 的新版本&…

联立方程模型的可识别性的通俗解释

联立方程模型的可识别性&#xff0c;主要的解法是阶条件算法和秩条件算法&#xff0c;数学公式角度的解释就不讲了&#xff0c;参考下面的前人文献。 【计量经济学】联立方程模型-CSDN博客 说一下公式算法背后的通俗原理。 在计量经济模型中&#xff0c;比如 Y23*Xu中&#x…

[java基础揉碎]super关键字

super关键字: 基本介绍 super代表父类的引用&#xff0c;用于访问父类的属性、方法、构造器 super给编程带来的便利/细节 1.调用父类的构造器的好处(分工明确&#xff0c;父类属性由父类初始化&#xff0c;子类的属性由子类初始化) 2.当子类中有和父类中的成员(属性和方法)重…

Springer旗下SCI,16天见刊!稳定检索13年,质量稳定

毕业推荐 SCIE&#xff1a; • 计算机类&#xff0c;6.5-7.0&#xff0c;JCR1区&#xff0c;中科院2区 • 2个月19天录用&#xff0c;6天见刊&#xff0c;36天检索 SCI&EI&#xff08;CCF-C类&#xff09; • 算法类&#xff0c;2.0-3.0&#xff0c;JCR3区&#xff0c…

数字孪生的大方向趋势及未来

hello宝子们...我们是艾斯视觉擅长ui设计和前端开发10年经验&#xff01;希望我的分享能帮助到您&#xff01;如需帮助可以评论关注私信我们一起探讨&#xff01;致敬感谢感恩&#xff01; 数字孪生的大方向趋势及未来 一、引言 数字孪生&#xff08;Digital Twin&#xff09…

高级语言讲义2016计专(仅高级语言部分)

1.斐波那契序列的第n项可以表示成以下形式&#xff0c;编写一个非递归函数&#xff0c;返回该数列的第n项的数值 #include <stdio.h>int func(int n) {if(n1||n2)return 1;int p1,q1,num;for(int i3; i<n; i) {numpq;qp;pnum;}return num; } 2.在MXN的二维数组A中&am…

Win11 没有网络bug

1.问题描述 没有网络&#xff0c;dns一直是固定的&#xff0c;但是dns已经是自动获取了(MAC地址随机) 2.解决办法 1.首先&#xff0c;删除所有网络的手动dns配置,控制中心那个dns管理没有用,在设置中删除网络,不然问题还会出现 - 2.然后&#xff0c;进入注册表\HKEY_LOCAL_MACH…

数据结构之栈详解(C语言手撕)

&#x1f389;个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生 &#x1f648;个人主页&#x1f389;&#xff1a;GOTXX &#x1f43c;个人WeChat&#xff1a;ILXOXVJE &#x1f43c;本文由GOTXX原创&#xff0c;首发CSDN&…