Ubuntu 20.04.06 PCL C++学习记录(二十一)【切记使用rm * -rf前先确认是否是对应文件夹】

@[TOC]PCL中点云分割模块的学习

学习背景

参考书籍:《点云库PCL从入门到精通》以及官方代码PCL官方代码链接,,PCL版本为1.10.0,CMake版本为3.16,测试点云下载地址

学习内容

根据欧几里得距离和需要保持的用户可自定义条件对点进行聚类,点云文件可从上述地址下载。

源代码及所用函数

源代码

#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);
  else
    return (false);
}


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

}


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 ("/home/jojo/PointCloud/Statues_4.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);

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

}

CMakeLists.txt

cmake_minimum_required(VERSION 3.16 FATAL_ERROR)#指定CMake的最低版本要求为3.16
project(project)#设置项目名称
find_package(PCL 1.10 REQUIRED)#查找PCL库,要求版本为1.10或更高。
include_directories(${PCL_INCLUDE_DIRS})#将PCL库的头文件目录添加到包含路径中
link_directories(${PCL_LIBRARY_DIRS})#将PCL库的库文件目录添加到链接器搜索路径中。
add_definitions(${PCL_DEFINITIONS})#添加PCL库的编译器定义
add_executable (conditional_euclidean_clustering conditional_euclidean_clustering.cpp)
target_link_libraries (conditional_euclidean_clustering ${PCL_LIBRARIES})#将PCL库链接到可执行文件目标。

运行结果

注意:当使用 PCL 的标准 PCD 查看器打开输出点云时,按“5”将切换到强度通道可视化。 太小的簇将被涂成红色,太大的簇将被涂成蓝色,而实际的簇/感兴趣的物体将被随机着色为黄色和青色, 如果不按则都为一个颜色。
在这里插入图片描述

函数

补充内容

  • std::cout << “降采样中\n”,tt.tic();和std::cout << “降采样中\n”,tt.tic()<<std::endl;的区别
    1. std::cout << “降采样中\n”, tt.tic();
      这个语句使用了逗号运算符 ,。逗号运算符会按照从左到右的顺序依次计算其左右两侧的表达式,并返回右侧表达式的值。在这个语句中,首先会输出字符串 “降采样中\n”,然后计算 tt.tic(),但是 tt.tic() 的返回值会被丢弃,因为它没有被使用或输出。
    2. std::cout << “降采样中\n”, tt.tic() << std::endl;
      这个语句也使用了逗号运算符 ,。同样地,它会先输出字符串 “降采样中\n”,然后计算 tt.tic()。但是,这里的 tt.tic() 的返回值会被传递给 std::cout,然后再输出一个换行符 std::endl。

第二个语句不仅会输出字符串 “降采样中\n”,还会输出 tt.tic() 的返回值,并在最后添加一个换行符

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

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

相关文章

8. 托盘图标与菜单

内容概要&#xff1a; 托盘图标的设置与事件 右键菜单的相关操作 窗口组件&#xff1a; 1.组件的属性 组件属性&#xff1a;位置 组件属性&#xff1a;可视 2.组件的事件 窗口_托盘事件-带有参数的事件的使用方法 3.组件的方法 置托盘图标 菜单的操作 1.创建菜单 …

大话设计模式——20.解释器模式(Interpreter Pattern)

简介 给定一个语言&#xff0c;定义它的文法的一种表示&#xff0c;并定义一个解释器&#xff0c;这个解释器使用该表示来解释语言中的句子 UML图 应用场景 某种特定类型的问题发生的频率足够多&#xff0c;就可能值得将该问题的各个实例表述为一个简单语言中的句子&#xff0…

关于pandas 无法读取 csv 文件数据的解决方式

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 …

词频统计程序

使用Hadoop MapReduce处理文本文件&#xff0c;Mapper负责将文本分割为单词&#xff0c;然后Reducer对每个单词进行计数&#xff0c;最后将结果写入输出文件。 // 定义WordCount公共类 public class WordCount {// 主入口方法&#xff0c;处理命令行参数public static void m…

C++实现幻方实验

我们这个实验目的是实现大于2的奇数的n阶幻方 根据上述的例子我们可以看到一些规律&#xff0c;显示1放在最上方中间的位置&#xff0c;然后向右上方延申&#xff0c;在达到n这个数字时&#xff0c;停止延申&#xff0c;然后在n的下方开始n1的新一轮延申。明白了原理之后就很容…

羊大师说:“羊奶”,每一滴都值得珍惜

亲爱的读者们&#xff0c;我是羊大师。在无数次探索自然的奥秘和追求健康生活的旅途中&#xff0c;我发现了一种珍贵的液体——羊奶。今天&#xff0c;我要带大家深入了解羊奶&#xff0c;看看它是如何成为餐桌上的超级食品。 1. 羊奶的营养价值 首先&#xff0c;羊奶含有丰富…

财富池指标公式--实用多空博弈买点提示通达信副图指标公式源码

实用多空博弈买点提示通达信副图指标&#xff0c;不含未来函数&#xff0c;信号简单。 当白色多头能量线金叉黄色空方能量线&#xff0c;且出现紫色向上的信号后参考买入是一个较为稳健的买点&#xff0c;也可在白色多头能量线金叉黄色空方能量线时就介入。 配合其它选股指标…

向新而行,企商在线做好“AI+”大文章

文&#xff1a;中国高新技术产业导报 记者 张伟 作为人工智能典型服务商屡获认可&#xff0c;入选第二批北京市通用人工智能产业创新伙伴计划成员&#xff1b;作为唯一上榜的AI算力企业&#xff0c;实力入选中国信通院《2023高质量数字化转型产品及服务全景图&#xff08;9月…

ubuntu20挂载webdav

WebDAV 是个好东西&#xff0c;尤其是配个自己的 NAS 使用&#xff0c;熟悉以后就再也离不开它啦 sudo apt-get update sudo apt-get install davfs2 上下左右键可以切换到“是”选项 2.创建目录挂载点 sudo mkdir /mnt/webdav 3.配置 davfs2 编辑 davfs2.conf 文件以配置 da…

系统监测工具-tcpdump的使用

一个简单的tcpdump抓包过程。主要抓包观察三次握手&#xff0c;四次挥手的数据包 有两个程序&#xff1a;客户端和服务器两个程序 服务器端的ip地址使用的是回环地址127.0.0.1 端口号使用的是6000 tcpdump -i 指定用哪个网卡等&#xff0c;dstip地址端口指定抓取目的地址…

Linux:gcc

Linux&#xff1a;gcc gcc概述语言发展史gcc的编译过程预处理编译汇编 gcc的链接过程动态库与静态库 gcc概述 GCC&#xff08;英文全拼&#xff1a;GNU Compiler Collection&#xff09;是 GNU 工具链的主要组成部分&#xff0c;是一套以 GPL 和 LGPL 许可证发布的程序语言编译…

自定义类型—结构体

目录 1 . 结构体类型的声明 1.1 结构的声明 1.2 结构体变量的创建与初始化 1.3 结构体的特殊声明 1.4 结构体的自引用 2. 结构体内存对齐 2.1 对齐规则 2.2 为什么存在内存对齐 2.3 修改默认对齐数 3. 结构体传参 4.结构体实现位段 4.1 位段的内存分配 1 . 结构体类…

12.C++常用的算法_遍历算法

文章目录 遍历算法1. for_each()代码工程运行结果 2. transform()代码工程运行结果 3. find()代码工程运行结果 遍历算法 1. for_each() 有两种方式&#xff1a; 1.普通函数 2.仿函数 代码工程 #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<vect…

数据结构之树的性质总结

节点的度&#xff1a;该节点拥有的孩子个数 叶子节点&#xff1a;度为0的节点 层数&#xff1a;根节点为第一层&#xff0c;根的子节点为第二层&#xff0c;以此类推 所有树的性质&#xff1a;所有节点的总度数等于节点数减一 完全m叉树性质 完全m 叉树&#xff0c;节点的…

【Canvas与艺术】绘制磨砂黄铜材质Premium Quality徽章

【关键点】 渐变色的使用、斜纹的实现、底图的寻觅 【成果图】 ​​​​​​​ 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><tit…

若依Vue3:新一代前后端分离权限管理系统

随着技术的不断进步&#xff0c;前后端分离的开发模式逐渐成为主流&#xff0c;特别是在构建权限管理系统时。在这样的背景下&#xff0c;若依Vue3应运而生&#xff0c;作为基于Spring Boot、Spring Security、JWT、Vue3、Vite和Element Plus的全新解决方案&#xff0c;它在技术…

Ubuntu20.04安装ROS过程记录以及常见报错处理

sudo sh -c ‘echo “deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main” > /etc/apt/sources.list.d/ros-latest.list’ sudo apt-key adv --keyserver ‘hkp://keyserver.ubuntu.com:80’ --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 sudo apt-…

linux启动流程(s3c2400)

概述 大致流程&#xff1a;内核&#xff08;kernel&#xff09;都是由bootloader程序引导启动的&#xff0c;所以我们应该先烧进去bootloader程序。然后可以通过保存的内核代码或者通过远程连接&#xff08;nfs/tftp&#xff09;的主机下载再运行&#xff0c;再挂载根文件系统。…

ABAP 前导0的处理

前导0这个东西真的很烦&#xff0c;经常因为前导0导致连接条件有问题&#xff0c;出不来数据&#xff0c;这里就总结一下前导0 在sql语句中的添加和去除 文章目录 ABAP 前导0的处理添加前导0-自适应运行结果 去除前导0方法一、使用SUBSTRING截取运行结果 方法二、去零法运行结…

小白新手学习 Python 使用哪个 Linux 系统更好?

对于小白新手学习Python&#xff0c;选择哪个Linux系统是一个很重要的问题&#xff0c;因为不同的Linux发行版&#xff08;distribution&#xff09;有着不同的特点、优势和适用场景。在选择时&#xff0c;需要考虑到易用性、学习曲线、社区支持等因素。 Ubuntu Ubuntu 是一个…