点云分割-pcl区域生长算法

news2024/10/10 14:23:58

目录

  • 写在前面
  • 原理
  • 代码
    • 运行结果
  • 参考

写在前面

1、本文内容
pcl的区域生长算法的使用和原理

2、平台/环境
cmake, pcl
3、转载请注明出处:
https://blog.csdn.net/qq_41102371/article/details/131927376

原理

参考:https://pcl.readthedocs.io/projects/tutorials/en/master/region_growing_segmentation.html#region-growing-segmentation
https://blog.csdn.net/taifyang/article/details/124097186

这里主要将可设置的参数列出:
KSearch: 用于计算法向量的最近邻点数量,针对K近邻搜索求法向量,也可使用半径搜索求法向量:

  normal_estimator.setKSearch(KSearch);// 30
 // normal_estimator.setRadiusSearch(2);

MinClusterSize: 至少多少点才能构成一个簇
NumberOfNeighbours: 区域生长的近邻点数量
SmoothnessThreshold: 法向量角度阈值,判断当前邻域点和种子点的法向量夹角是否小于此阈值,小于则将当前邻域点加入当前簇
CurvatureThreshold: 曲率阈值,若当前近邻点与种子点夹角小于法向量阈值,并且曲率小于此曲率阈值,则加入种子点

代码

新建文件夹

mkdir pcl_region_growging_segmentation
cd pcl_region_growging_segmentation

pcl_region_growging_segmentation/CMakeLists.txt

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)

project(region_growing_segmentation)

find_package(PCL 1.5 REQUIRED)

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

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

pcl_region_growging_segmentation/region_growging_segmentation.cpp

#include <iostream>
#include <vector>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/search/search.h>
#include <pcl/search/kdtree.h>
#include <pcl/features/normal_3d.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/filters/passthrough.h>
#include <pcl/segmentation/region_growing.h>

template <typename PointT>
void PcdVisualizer(pcl::PointCloud<PointT> cloud, bool coordinate = false)
{
  pcl::visualization::PCLVisualizer::Ptr viewer(
      new pcl::visualization::PCLVisualizer("3D Viewer"));
  viewer->setBackgroundColor(0, 0, 0);
  pcl::PointCloud<PointT>::Ptr cloud_ptr(new pcl::PointCloud<PointT>);
  *cloud_ptr = cloud;
  viewer->addPointCloud<PointT>(cloud_ptr, "cloud");
  if (coordinate)
  {
    viewer->addCoordinateSystem(1.0, "global");
  }
  while (!viewer->wasStopped())
  {
    viewer->spinOnce(100);
    // td::this_thread::sleep_for(100ms);
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
  }
}

int main(int argc, char **argv)
{
  if (argc < 2)
  {
    std::cout << "please input a pcd" << std::endl;
    return 0;
  }
  std::string pcd_path = argv[1];
  std::cout << "pcd_path: " << pcd_path << std::endl;
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
  if (pcl::io::loadPCDFile<pcl::PointXYZ>(pcd_path, *cloud) == -1)
  {
    std::cout << "Cloud reading failed." << std::endl;
    return (-1);
  }

  int KSearch = std::atoi(argv[2]);
  int MinClusterSize = std::atoi(argv[3]);
  int NumberOfNeighbours = std::atoi(argv[4]);
  double SmoothnessThreshold = std::atof(argv[5]);
  double CurvatureThreshold = std::atof(argv[6]);

  std::cout << "KSearch: " << KSearch << std::endl;
  std::cout << "MinClusterSize: " << MinClusterSize << std::endl;
  std::cout << "NumberOfNeighbours: " << NumberOfNeighbours << std::endl;
  std::cout << "SmoothnessThreshold: " << SmoothnessThreshold << std::endl;
  std::cout << "CurvatureThreshold: " << CurvatureThreshold << std::endl;

  pcl::search::Search<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
  pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
  pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;
  normal_estimator.setSearchMethod(tree);
  normal_estimator.setInputCloud(cloud);
  normal_estimator.setKSearch(KSearch);// 30
  // normal_estimator.setRadiusSearch(2);
  normal_estimator.compute(*normals);

  pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;
  reg.setMinClusterSize(MinClusterSize); //50
  reg.setMaxClusterSize(1000000);
  reg.setSearchMethod(tree);
  reg.setNumberOfNeighbours(NumberOfNeighbours); //30
  reg.setInputCloud(cloud);
  reg.setInputNormals(normals);
  reg.setSmoothnessThreshold(SmoothnessThreshold / 180.0 * M_PI); //5.0
  reg.setCurvatureThreshold(CurvatureThreshold); //1.0

  std::vector<pcl::PointIndices> clusters;
  reg.extract(clusters);

  std::cout << "Number of clusters is equal to " << clusters.size() << std::endl;
  std::cout << "First cluster has " << clusters[0].indices.size() << " points." << std::endl;
  std::cout << "These are the indices of the points of the initial" << std::endl
            << "cloud that belong to the first cluster:" << std::endl;
  int counter = 0;
  // while (counter < clusters[0].indices.size ())
  // {
  //   std::cout << clusters[0].indices[counter] << ", ";
  //   counter++;
  //   if (counter % 10 == 0)
  //     std::cout << std::endl;
  // }
  std::cout << std::endl;

  pcl::PointCloud<pcl::PointXYZRGB>::Ptr colored_cloud = reg.getColoredCloud();
  PcdVisualizer(*colored_cloud);

  return (0);
}

windows: pcl_region_growging_segmentation/compile.bat

cmake -DCMAKE_BUILD_TYPE=Release -DPCL_DIR="your pcl path whcih including cmake files of pcl" -S ./ -B ./build
cmake --build ./build --config Release --parallel 8 --target ALL_BUILD

for example:

-DPCL_DIR="D:/carlos/install/PCL 1.10.0/cmake"

linux: pcl_region_growging_segmentation/compile.sh

cmake -DCMAKE_BUILD_TYPE=Release -DPCL_DIR="your pcl path whcih including cmake files of pcl" -S ./ -B ./build
cmake --build ./build --config Release --parallel 8 

运行结果

windows: pcl_region_growging_segmentation/run.bat

set PATH=D:\carlos\install\PCL 1.10.0\bin;D:\carlos\install\PCL 1.10.0\3rdParty\FLANN\bin;D:\carlos\install\PCL 1.10.0\3rdParty\VTK\bin;D:\carlos\install\PCL 1.10.0\3rdParty\Qhull\bin;D:\carlos\install\PCL 1.10.0\3rdParty\OpenNI2\Tools;%PATH%
.\build\Release\region_growing_segmentation.exe ^
C:\Users\12538\Downloads\region_growing_tutorial.pcd ^
50 500 30 5 1.0

其中set PATH是设置环境变量,用于运行时能够找到pcl所需要的dll
pcl提供的测试数据:https://raw.github.com/PointCloudLibrary/data/master/tutorials/region_growing_tutorial.pcd
在这里插入图片描述

包含建筑,车辆,树木的一个点云数据:
在这里插入图片描述

参考

文中已列出

主要做激光/影像三维重建,配准、分割等常用点云算法,技术交流、咨询可私信

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

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

相关文章

从风控系统看架构设计原型图分析

目录 一、对架构与架构图的理解 &#xff08;一&#xff09;架构的本质 &#xff08;二&#xff09;软件设计中架构域的划分 &#xff08;三&#xff09;架构图设计 架构图设计的必要性 如何画架构图 二、实践业务架构与产品架构设计 &#xff08;一&#xff09;列出问…

基于SpringBoot+vue的学生成绩管理系统设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

重学C++系列之虚继承

一、什么是虚继承 虚继承是C中一种继承的机制。继承有普通继承和虚继承两种机制&#xff0c;默认是普通继承&#xff0c;如果要使用多继承&#xff0c;需要在继承方式里加上关键字virtual。 二、为什么要虚继承 在C中&#xff0c;为解决二义性问题&#xff0c;引入虚继承机制。…

tinkerCAD案例:9. Saw Shaped Wrench 锯形扳手

tinkerCAD案例&#xff1a;9. Saw Shaped Wrench 锯形扳手 ln this lesson you will learn how to create a cool saw shaped wrench. 在本课中&#xff0c;您将学习如何制作一个很酷的锯形扳手。 Start the lesson by dragging a polygon to the workplane. 通过将多边形拖动…

从模型坐标到屏幕坐标

在 3D 引擎中&#xff0c;场景通常被描述为三维空间中的模型或对象&#xff0c;每个模型对象由许多三维顶点组成。最终&#xff0c;这些模型对象将在平面屏幕上呈现和显示。 渲染场景始终相对于摄像机&#xff0c;因此&#xff0c;还必须相对于摄像机的视图定义场景的顶点。了…

zeppelin spark kerberos 使用过程遇到的问题

参考配置教程: Configure Zeppelin for a Kerberos-Enabled Cluster zeppelin spark kerberos 使用过程遇到的问题 ambari创建zeppelin时,会创建Kerberos account and keytab /etc/security/keytabs/zeppelin.server.kerberos.keytab interpreter配置 keytab Interpreter Ke…

新来个技术总监,禁止我们用Git的rebase!?

△Hollis, 一个对Coding有着独特追求的人△ 这是Hollis的第 429 篇原创分享 作者 l Hollis 来源 l Hollis&#xff08;ID&#xff1a;hollischuang&#xff09; 在Git中&#xff0c;merge和rebase是两种不同的代码合并策略&#xff0c;它们用于将一个分支的更改合并到另一个分支…

动态内存常见的问题

对空指针的解引用 改正后的代码&#xff1a; 返回栈&#xff08;临时变量&#xff09;空间地址的问题 释放空间后及时把指针设为空 void Test(void) {char* str (char*)malloc(100);strcpy(str, "hello");free(str);str NULL;//释放空间后及时把指针设为空if (s…

嵌入式学习入门和求职经验

入门阶段&#xff1a;&#xff08;不要只看书&#xff0c;要多动手&#xff0c;但千万不是直接动手&#xff0c;不去看书&#xff09; C语言&#xff1a;嵌入式编程大多用C语言、少量汇编&#xff0c;先学习C语言&#xff0c;汇编用到的时候再上网查询。教材&#xff1a;随便一…

unity调用c++dll时变量处理问题

在C中为了处理方便可以将有些局部变量变为全局变量。 以下面三个变量为例 如果还有新全局变量需要这其来赋值&#xff0c;就会有问题。 如下面的body1_ptr为了dll生成处理方便&#xff0c;变为全局变量后&#xff0c;这个指针变赋值就会有问题。 因为geometry_path这个只在调…

上分秘籍 :如何用大模型跨模态能力核查网络谣言?

也许&#xff0c;你也曾听说过&#xff1a;&#x1f449;眼见未必为实&#x1f449;假新闻可比真新闻好传太多啦&#xff01;&#x1f449;谣言一张嘴&#xff0c;辟谣跑断腿大模型时代来临&#xff0c;除了肝&#xff0c;对付网络谣言&#xff0c;是不是有了新出路&#xff1f…

Java_23_并发包

并发包 并发包的来历&#xff1a; 在实际开发中如果不需要考虑线程安全问题&#xff0c;大家不需要做线程安全&#xff0c;因为如果做了反而性能不好&#xff01; 但是开发中有很多业务是需要考虑线程安全问题的&#xff0c;此时就必须考虑了。否则业务出现问题。 Java为很多业…

考公笔记题

一、考公报名网址 国家公务员局&#xff1a;国家公务员局 二、历年题库 华图在线&#xff1a;国省考公务员题库_公职教育类在线题库-华图在线 公务员&#xff1a;《行测》与《申论》 重点学习&#xff1a; 判断推理&#xff08;图形推理、定义判断&#xff08;影响不大&am…

vue中的数据代理

vue数据代理 Vue实现数据代理的核心----Object.defineProperty(); 数据代理 数据代理的定义是&#xff1a;一个对象操作(读\写)另一个对象中的属性和方法。 // 数据代理&#xff1a;通过一个对象代理对另一个对象中属性的操作&#xff08;读/写&#xff09;let obj { x: 100…

STM32之智能小车,手把手从0到1,模块化编程

小车介绍 本博文将会从0到1实现一个智能小车&#xff0c;该小车实现功能&#xff1a;1. 摇头避障模式、2. 跟随模式、3. 循迹模式、4. 小车测速并显示在OLED屏幕、5. 语音控制小车等等。 硬件组成 STM32F103开发板、小车套件、L9110S电机模块、超声波模块&#xff08;HC-SR04&a…

代码随想录算法训练营第二十五天 | 读PDF复习环节3

读PDF复习环节3 本博客的内容只是做一个大概的记录&#xff0c;整个PDF看下来&#xff0c;内容上是不如代码随想录网站上的文章全面的&#xff0c;并且PDF中有些地方的描述&#xff0c;是很让我疑惑的&#xff0c;在困扰我很久后&#xff0c;无意间发现&#xff0c;其网站上的讲…

Ubuntu-解决包依赖关系

Ubuntu-解决包依赖关系的办法 安装软件包的时候&#xff0c;有时会遇到类似下图的依赖问题&#xff0c;无法正常安装&#xff0c;下面提供三种方法解决依赖问题。 1.可以尝试用下面方法处理依赖问题&#xff0c;紧跟前一条安装命令后面输入下面命令&#xff0c;然后再执行安装…

第一次使用easyExcel报错信息记录 NullPointerException + MultipartException

第一次使用easyExcel报错信息记录 文章目录 第一次使用easyExcel报错信息记录NullPointerExceptionMultipartException NullPointerException 使用easyExcel报的错误 显示我的easyExcel监听器中出现了空指针异常 //报错信息 Creating a new SqlSessionClosing non transacti…

【Ajax】笔记-同源策略

同源策略(Same-Origin Policy)&#xff0c;是浏览器的一种安全策略 同源&#xff08;即url相同&#xff09;&#xff1a;协议、域名、端口号 必须完全相同。&#xff08;请求是来自同一个服务&#xff09; 跨域&#xff1a;违背了同源策略&#xff0c;即跨域。 ajax请求是遵循…

手把手教-gd32f450基于rt-thread发布的bsp包手动添加以太网外设

一、开发环境 rt-thread发布版本4.1.0&#xff1b; bsp包选用的是gd32目录下的gd32450z-eval rt-thread-v4.1.0\bsp\gd32\gd32450z-eval\ 开发板gd32f450z系列开发板。 二、手动添加以太网ETH外设 先看下初始结构 可以看到&#xff0c;配置中什么也没有。 手动添加步骤如下&…