Difference of Normals Based Segmentation

news/2024/11/20 21:29:46/

文章目录

  • 例子
    • 官网的可视化图片流程
    • 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 bydouble threshold;///segment scene into clusters with given distance tolerance using euclidean clusteringdouble 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 scalestd::istringstream (argv[2]) >> scale1;/// large scalestd::istringstream (argv[3]) >> scale2;std::istringstream (argv[4]) >> threshold;   // threshold for DoN magnitudestd::istringstream (argv[5]) >> segradius;   // threshold for radius segmentation// Load cloud in blob formatpcl::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 treetree->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 pointpcl::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 scalestd::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 scalestd::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 resultsPointCloud<PointNormal>::Ptr doncloud (new pcl::PointCloud<PointNormal>);copyPointCloud (*cloud, *doncloud);std::cout << "Calculating DoN... " << std::endl;// Create DoN operatorpcl::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 DoNdon.computeFeature (*doncloud);//计算点云法向量变化程度保存到doncloud// Save DoN featurespcl::PCDWriter writer;writer.write<pcl::PointNormal> ("don.pcd", *doncloud, false); // Filter by magnitudestd::cout << "Filtering out DoN mag <= " << threshold << "..." << std::endl;// Build the condition for filtering// 构建条件滤波器pcl::ConditionOr<PointNormal>::Ptr range_cond(new pcl::ConditionOr<PointNormal>());// 设置滤波条件 或 orrange_cond->addComparison (pcl::FieldComparison<PointNormal>::ConstPtr(new pcl::FieldComparison<PointNormal> ("curvature", pcl::ComparisonOps::GT, threshold)));//保留大于阈值的点// Build the filterpcl::ConditionalRemoval<PointNormal> condrem;condrem.setCondition (range_cond);condrem.setInputCloud (doncloud);// 保存滤波结果pcl::PointCloud<PointNormal>::Ptr doncloud_filtered (new pcl::PointCloud<PointNormal>);// Apply filtercondrem.filter (*doncloud_filtered);doncloud = doncloud_filtered;// Save filtered outputstd::cout << "Filtered Pointcloud: " << doncloud->size () << " data points." << std::endl;writer.write<pcl::PointNormal> ("don_filtered.pcd", *doncloud, false); // Filter by magnitudestd::cout << "Clustering using EuclideanClusterExtraction with tolerance <= " << segradius << "..." << std::endl;// 用于聚类的kd-treepcl::search::KdTree<PointNormal>::Ptr segtree (new pcl::search::KdTree<PointNormal>);segtree->setInputCloud (doncloud);// 聚类分成了几块不同的点云的点云的indexstd::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.ppmy.cn/news/340812.html

相关文章

计算机蓝屏代码0x0000007b,电脑开机出现蓝屏代码0x0000007b怎么办?

电脑开机后就出现蓝屏代码为0x0000007b到底什么意思呢&#xff1f;0x0000007b算是电脑蓝屏常见故障之一&#xff0c;导致这样情况的原因有几种&#xff0c;下面小白系统帮你分析下导致蓝屏0x0000007b的原因以及解决方案。 情况一&#xff1a;重装xp系统出现的蓝屏 很多朋友的电…

计算机蓝屏代码0x0000007b,解决电脑蓝屏出现代码0x0000007b怎么解决

最近,小编发现有朋友想知道蓝屏代码0x0000007b的解决方法呢,其实解决该问题的方法很简单,大家如果想要学习的话小编肯定也是会教你们的,好了,下面就和小编一块来看看蓝屏代码0x0000007b的解决方法吧! 在对电脑的使用过程中,我们经常都会遇到一些关于屏幕方面上的故障,比…

计算机蓝屏代码0x0000007b,开机出现蓝屏代码0X0000007B原因分析及解决方法

使用电脑的朋友,出现电脑蓝屏实在是让人难己排查,有些蓝屏出现后有相关文件提示,比如说xxx.sys之类的提示,我们可以根据提示查找什么导致蓝屏,但有些蓝屏出现后直接没有任何提示,只有出现一个蓝屏代码,这些代码出现蓝屏的原因有很多,但0x0000007b蓝屏可以肯定是什么原因…

计算机蓝屏代码0x0000007b,电脑蓝屏代码0x0000007b 电脑蓝屏0x0000007b怎么解决 - 云骑士一键重装系统...

Ready 品牌型号&#xff1a;联想GeekPro 2020 系统&#xff1a;win10 1909 64位企业版 软件版本&#xff1a;360安全卫士12.0.0 部分用户可能电脑型号不一样&#xff0c;但系统版本一致都适合该方法。 平时我们在使用电脑的过程中&#xff0c;或许会遇到电脑蓝屏的情况&#xf…

蓝屏0x0000007b要怎么办?有什么简单的处理方法?

遇到蓝屏0x0000007b要怎么办?相信很多人都遇到过吧?这种蓝屏其实是很让人烦恼的&#xff0c;会导致系统直接无法使用&#xff0c;今天小编就来给大家详细的说说。 一.电脑蓝屏0x0000007b怎么办 1.首先点击开机键将电脑关闭&#xff0c;然后重启电脑开机按下F10进入bios。 2.选…

第57讲:Python定义函数时添加函数注解

文章目录 1.函数注解的概念2.函数注解的定义2.1.形参的注解2.2.形参和返回值的注解2.3.访问定义的函数注解1.函数注解的概念 定义函数时,为了更加清楚的表示形参和返回值的类型或作用,可以给形参和返回值添加函数注解,从而对形参和返回值做更加充分的解释说明,更久的通俗易…

Java中isAssignableFrom与instanceof的区别

最近看到一个新的用法isAssignableFrom&#xff0c;和以前学的instanceof类似的效果&#xff0c;于是记录一下。 一、isAssignableFrom 假设有两个类Class1和Class2。Class1.isAssignableFrom(Class2)表示: 类Class1和Class2是否相同。确定一个类Class2是不是继承来自于另一…

CSS相关面试题

1、标准盒子模型和IE怪异盒子模型&#xff1f; 标准盒子模型就是指的元素的宽度和高度仅包括的内容区域&#xff0c;不包括边框和内边距&#xff0c;也就是说&#xff0c;元素的实际宽度和高度等于内容区域的宽度和高度IE怪异盒子是指元素的高度和宽度&#xff0c;包括内容区域…