Difference of Normals Based Segmentation

news2024/12/27 4:15:36

文章目录

  • 例子
    • 官网的可视化图片流程
    • C++
    • cmakelist
  • 参考

记录翻译一下pcl中的例子
实现的“法线差”功能,用于基于比例的无组织点云分割。

例子

官网的可视化图片流程

在这里插入图片描述

C++

代码流程:

  1. 设置输入点云相关参数。图片左上
  2. 设置两个半径求取法相量点云,使用DoN根据两个不同半径的法向量生成DoN点云。图片右上
  3. 更加DoN点云,设置曲率阈值进行滤波,获取符合要求的点云。图片右下
  4. 根据欧式距离对滤波后的点云进行聚类处理。图片左下
#include <string>

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/search/organized.h>
#include <pcl/search/kdtree.h>
#include <pcl/features/normal_3d_omp.h>
#include <pcl/filters/conditional_removal.h>
#include <pcl/segmentation/extract_clusters.h>

#include <pcl/features/don.h>

using namespace pcl;

int
main (int argc, char *argv[])
{
  ///The smallest scale to use in the DoN filter.
  double scale1;

  ///The largest scale to use in the DoN filter.
  double scale2;

  ///The minimum DoN magnitude to threshold by
  double threshold;

  ///segment scene into clusters with given distance tolerance using euclidean clustering
  double segradius;

  if (argc < 6)
  {
    std::cerr << "usage: " << argv[0] << " inputfile smallscale largescale threshold segradius" << std::endl;
    exit (EXIT_FAILURE);
  }

  /// the file to read from.
  std::string infile = argv[1];
  /// small scale
  std::istringstream (argv[2]) >> scale1;
  /// large scale
  std::istringstream (argv[3]) >> scale2;
  std::istringstream (argv[4]) >> threshold;   // threshold for DoN magnitude
  std::istringstream (argv[5]) >> segradius;   // threshold for radius segmentation

  // Load cloud in blob format
  pcl::PCLPointCloud2 blob;
  pcl::io::loadPCDFile (infile.c_str (), blob);
  pcl::PointCloud<PointXYZRGB>::Ptr cloud (new pcl::PointCloud<PointXYZRGB>);
  pcl::fromPCLPointCloud2 (blob, *cloud);

  // Create a search tree, use KDTreee for non-organized data.
  // 构建搜索树
  pcl::search::Search<PointXYZRGB>::Ptr tree;
  if (cloud->isOrganized ())
  {
    tree.reset (new pcl::search::OrganizedNeighbor<PointXYZRGB> ());
  }
  else
  {
    tree.reset (new pcl::search::KdTree<PointXYZRGB> (false));
  }

  // Set the input pointcloud for the search tree
  tree->setInputCloud (cloud);

  if (scale1 >= scale2)
  {
    std::cerr << "Error: Large scale must be > small scale!" << std::endl;
    exit (EXIT_FAILURE);
  }

  // Compute normals using both small and large scales at each point
  pcl::NormalEstimationOMP<PointXYZRGB, PointNormal> ne;
  ne.setInputCloud (cloud);
  ne.setSearchMethod (tree);

  /**
   * NOTE: setting viewpoint is very important, so that we can ensure
   * normals are all pointed in the same direction!
   */
   // 设置法向量的观测方向
  ne.setViewPoint (std::numeric_limits<float>::max (), std::numeric_limits<float>::max (), std::numeric_limits<float>::max ());

  // calculate normals with the small scale
  std::cout << "Calculating normals for scale..." << scale1 << std::endl;
  //半径较小的点云的法向量
  pcl::PointCloud<PointNormal>::Ptr normals_small_scale (new pcl::PointCloud<PointNormal>);

  ne.setRadiusSearch (scale1);
  ne.compute (*normals_small_scale);

  // calculate normals with the large scale
  std::cout << "Calculating normals for scale..." << scale2 << std::endl;
  //半径较大的点云的法向量
  pcl::PointCloud<PointNormal>::Ptr normals_large_scale (new pcl::PointCloud<PointNormal>);

  ne.setRadiusSearch (scale2);
  ne.compute (*normals_large_scale);

  // Create output cloud for DoN results
  PointCloud<PointNormal>::Ptr doncloud (new pcl::PointCloud<PointNormal>);
  copyPointCloud (*cloud, *doncloud);

  std::cout << "Calculating DoN... " << std::endl;
  // Create DoN operator
  pcl::DifferenceOfNormalsEstimation<PointXYZRGB, PointNormal, PointNormal> don;
  don.setInputCloud (cloud);
  don.setNormalScaleLarge (normals_large_scale);
  don.setNormalScaleSmall (normals_small_scale);

  if (!don.initCompute ())
  {
    std::cerr << "Error: Could not initialize DoN feature operator" << std::endl;
    exit (EXIT_FAILURE);
  }

  // Compute DoN
  don.computeFeature (*doncloud);//计算点云法向量变化程度保存到doncloud

  // Save DoN features
  pcl::PCDWriter writer;
  writer.write<pcl::PointNormal> ("don.pcd", *doncloud, false); 

  // Filter by magnitude
  std::cout << "Filtering out DoN mag <= " << threshold << "..." << std::endl;

  // Build the condition for filtering
  // 构建条件滤波器
  pcl::ConditionOr<PointNormal>::Ptr range_cond(new pcl::ConditionOr<PointNormal>());// 设置滤波条件 或 or
  range_cond->addComparison (pcl::FieldComparison<PointNormal>::ConstPtr(new pcl::FieldComparison<PointNormal> ("curvature", pcl::ComparisonOps::GT, threshold)));//保留大于阈值的点
  // Build the filter
  pcl::ConditionalRemoval<PointNormal> condrem;
  condrem.setCondition (range_cond);
  condrem.setInputCloud (doncloud);
	// 保存滤波结果
  pcl::PointCloud<PointNormal>::Ptr doncloud_filtered (new pcl::PointCloud<PointNormal>);

  // Apply filter
  condrem.filter (*doncloud_filtered);
  doncloud = doncloud_filtered;

  // Save filtered output
  std::cout << "Filtered Pointcloud: " << doncloud->size () << " data points." << std::endl;

  writer.write<pcl::PointNormal> ("don_filtered.pcd", *doncloud, false); 

  // Filter by magnitude
  std::cout << "Clustering using EuclideanClusterExtraction with tolerance <= " << segradius << "..." << std::endl;
	// 用于聚类的kd-tree
  pcl::search::KdTree<PointNormal>::Ptr segtree (new pcl::search::KdTree<PointNormal>);
  segtree->setInputCloud (doncloud);

  // 聚类分成了几块不同的点云的点云的index
  std::vector<pcl::PointIndices> cluster_indices;
  // 欧几里得聚类
  pcl::EuclideanClusterExtraction<PointNormal> ec;

  ec.setClusterTolerance (segradius);
  ec.setMinClusterSize (50);
  ec.setMaxClusterSize (100000);
  ec.setSearchMethod (segtree);
  ec.setInputCloud (doncloud);
  ec.extract (cluster_indices);

  int j = 0;
  for (const auto& cluster : cluster_indices)
  {
    pcl::PointCloud<PointNormal>::Ptr cloud_cluster_don (new pcl::PointCloud<PointNormal>);
    for (const auto& idx : cluster.indices)
    {
      cloud_cluster_don->points.push_back ((*doncloud)[idx]);
    }

    cloud_cluster_don->width = cloud_cluster_don->size ();
    cloud_cluster_don->height = 1;
    cloud_cluster_don->is_dense = true;

    //Save cluster
    // 保存聚类结果
    std::cout << "PointCloud representing the Cluster: " << cloud_cluster_don->size () << " data points." << std::endl;
    std::stringstream ss;
    ss << "don_cluster_" << j << ".pcd";
    writer.write<pcl::PointNormal> (ss.str (), *cloud_cluster_don, false);
    ++j;
  }
}

//条件
pcl::ConditionOr<PointNormal> // 条件或 ||
pcl::ConditionAnd<PointNormal> // 条件与 &&

//比较器
pcl::ComparisonOps::GT // >
pcl::ComparisonOps::GE // >=
pcl::ComparisonOps::LT // <
pcl::ComparisonOps::LE // <=
pcl::ComparisonOps::EQ // ==

cmakelist

# 最低的cmakelist版本
 cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
 # 项目名称
 project(don_segmentation
 # 寻找pcl库
 find_package(PCL 1.7 REQUIRED)
 # 包含文件路径
 include_directories(${PCL_INCLUDE_DIRS})
 link_directories(${PCL_LIBRARY_DIRS})
 add_definitions(${PCL_DEFINITIONS})
# 可执行文件
add_executable (don_segmentation don_segmentation.cpp)
# 链接库
target_link_libraries (don_segmentation ${PCL_LIBRARIES})

参考

  1. https://pcl.readthedocs.io/projects/tutorials/en/latest/don_segmentation.html
  2. https://pcl.readthedocs.io/projects/tutorials/en/latest/conditional_removal.html
  3. https://pcl.readthedocs.io/en/latest/cluster_extraction.html

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

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

相关文章

安装VastBase G100 v2.2 Build 12

1、防火墙设置 1.1 关闭防火墙和selinux 1.1.1 关闭防火墙 systemctl status firewalld.service systemctl stop firewalld.service systemctl disable firewalld1.1.2 关闭selinux vim /etc/selinux/config1.2 修改hosts文件,添加实际的IP地址和主机名 vi /etc/hosts 1.3…

【状态估计】卡尔曼滤波器、扩展卡尔曼滤波器、双卡尔曼滤波器和平方根卡尔曼滤波器研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

win10修改本地host文件,增加自定义本地访问域名127.0.0.1(超详细)

1. 按winR&#xff0c;输入C:\Windows\System32\drivers\etc打开host文件所在位置&#xff1a; 2.右键hosts文件–>点击属性->点击安全&#xff0c;把所有组用户名权限打开&#xff1a; 右键属性切换到安全 配置好之后点击应用-确定 最后验证一下 验证 5. winR&#x…

作为前端开发,你了解MutationObserver吗?

目录 前言 演变过程 基础概念 MutationObserver observe(target, options) attributes&#xff1a;是否监听标签属性变化 childList&#xff1a;是否监听子节点变化 characterData&#xff1a;是否监听文本节点内容的变化 attributeOldValue&#xff1a;是否记录属性变…

前端058_权限系统(身份认证+退出+刷新令牌)_刷新令牌获取新的认证信息

当访问令牌 access_toke 过期,后台会响应状态码 401 ,通过刷新令牌 refresh_toke 获取新令牌。获取后重新发送引发获取新令牌的请求。 1、请求拦截401错误实现刷新令牌请求 所有的请求后台数据,都是通过在 src/utils/request.js 封装的 axios 对象进行发送请求,所以当调…

蓝牙标签协议

1.Request write block size command CMD DATA 0x01 无 Response for write block size command CMD DATA (short) 0x01 Block size 注意&#xff1a;short是低位在前&#xff0c;高位在后 2.Request write screen command CMD DATA 0x02 Image length(int) Imag…

GIS软件中网络分析的5种应用

什么是网络分析&#xff1f;几乎每个人都需要一个网络分析的类型在他们的生活中。 例如&#xff0c;去海滩的最短路线是什么&#xff1f;应该在哪里建一所医院来最好地服务一个社区&#xff1f;如何优化运输车队&#xff1f; 以下是5种最常见的网络分析类型&#xff1a;点对点…

原来Allegro工程师还分这几个等级,薪资差距好大

随着电子设计领域的不断发展&#xff0c;Allegro工程师的需求也越来越高&#xff0c;在发展过程中&#xff0c;不同等级的Allegro工程师之间存在着薪资和工作范围上的差异&#xff0c;那么你知道不同等级的Allegro工程师有什么不同吗&#xff1f; NO.1初级Allegro工程师 ①分布…

HYA-D-M5、HYA-C-01、HYA-D-02气控电磁阀

HY-C-M5、HY-D-01、HY-D-02、HYA-D-M5、HYA-C-01、HYA-D-02、H280-4-D-S-L、H280-5-D-D-L、H380-5-G-S-L、H380-5-D-S-L电磁阀分电控及气控。维护须知&#xff1a; 1&#xff0c;安装时&#xff0c;请注意气体流动方向及接管是否正确&#xff0c;电压是否符合要求2.请注意防尘…

内部知识库搭建的意义何在?可以给哪些内部人员使用?

随着企业的不断发展和壮大&#xff0c;内部知识管理成为了越来越重要的一项工作。而内部知识库搭建则是内部知识管理的重要手段之一。本文将介绍内部知识库搭建的意义以及可供哪些内部人员使用&#xff0c;以及如何搭建一个高效的内部知识库。 内部知识库搭建的意义&#xff1…

拓展冒泡排序

冒泡排序 冒泡排序的动态演示 比较相邻的元素。 1&#xff0c;如果第一个比第二个大&#xff08;升序&#xff09;&#xff0c;就交换他们两个。 2&#xff0c;对每一对相邻元素作同样的工作&#xff0c;从开始第一对到结尾的最后一对。这步做完后&#xff0c; 最后的元素会是…

解决Antd Tree组件,二次点击时不取消选中,保持高亮

一、问题概述 ant design 提供的 Tree树组件 支持点击高亮树节点&#xff0c;再次点击取消高亮。 默认效果如下&#xff1a; 然而大多数业务场景下&#xff0c;我们希望多次点击同一个节点不会取消他的选中效果。 二、解决方案 监听onSelect时间&#xff0c;并使用select…

PG系列1:windows下安装PG15

文章目录 一. 下载PG二. 开始安装PG2.1 开始安装2.2 验证 一. 下载PG 官网地址: https://www.postgresql.org/选择Download 选择windows Download the installer 点击下载 二. 开始安装PG 2.1 开始安装 这个安装很简单&#xff0c;直接下一步即可&#xff0c;此处…

5.Java内存模型之JMM

Java内存模型之JMM 5.1 先从大场面试开始 你知道什么是Java内存模型JMM吗&#xff1f; JMM和volatile他们两个之间的关系&#xff1f; JMM没有那些特征或者它的三大特征是什么&#xff1f; 为什么要有JMM&#xff0c;它为什么出现&#xff1f;作用和功能是什么&#xff1f; hap…

智能井盖:智慧城市下的井盖管理新模式

随着全球城市化进程的加快&#xff0c;智慧城市的概念越来越受到关注。井盖作为城市的基础设施之一&#xff0c;井盖的安全管理成为城市管理者关注的重要问题。传统的井盖管理方式面临诸多挑战&#xff0c;如人力成本高、巡检效率低、隐患难以发现等。随着智慧城市的发展&#…

leangoo领歌敏捷工具中,如何快速查看项目内所有任务卡片

项目管理员能不能快捷的查看整个项目内的所有任务&#xff1f; 能不能快捷查看项目内某一个成员的所有任务&#xff1f; 能不能快捷的在项目内通过一些条件选择查看任务&#xff1f; 可以导出项目内某一个人的所有任务吗&#xff1f;方便做一些统计 等等... 这些现在Leang…

路径规划 | 图解Informed RRT*算法(附ROS C++/Python/Matlab仿真)

目录 0 专栏介绍1 Informed RRT*原理2 Informed RRT*流程3 ROS C实现4 Python实现5 Matlab实现 0 专栏介绍 &#x1f525;附C/Python/Matlab全套代码&#x1f525;课程设计、毕业设计、创新竞赛必备&#xff01;详细介绍全局规划(图搜索、采样法、智能算法等)&#xff1b;局部…

超全、超详细的Redis学习笔记总结

❤ 作者主页&#xff1a;欢迎来到我的技术博客&#x1f60e; ❀ 个人介绍&#xff1a;大家好&#xff0c;本人热衷于Java后端开发&#xff0c;欢迎来交流学习哦&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 如果文章对您有帮助&#xff0c;记得关注、点赞、收藏、…

「2024」预备研究生mem-消序核心原则

一、消序 二、核心原则 相同备选池 三、练习题

数据库索引简介及优化

索引 1.索引简介 1.1 概念 MySQL官方对索引的定义为&#xff1a;索引&#xff08;Index&#xff09;是帮助MySQL高效获取数据的数据结构。索引的本质&#xff1a;索引是数据结构。 注&#xff1a;在数据之外&#xff0c;数据库系统还维护着满足特定查找算法的数据结构&…