估计一个点云的表面法线

  • 包含相关头文件
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/features/normal_3d.h>
#include <pcl/visualization/pcl_visualizer.h>
  • 定义了两个类型别名 PointTPointNT,用于表示输入点云和输出点云中各个点的类型。
    输出点云的类型也可以是pcl::Normal,但无法用PCLVisualizer显示。
typedef pcl::PointXYZ PointT;
typedef pcl::PointNormal PointNT;
  • 读取点云,如果点云数据不存在,程序结束 
pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);

if (pcl::io::loadPCDFile<PointT>("../input_cloud/rabbit.pcd", *cloud) == -1)
{
	PCL_ERROR("找不到文件...\n");
	return -1;
}
  • 创建一个 pcl::NormalEstimation 类型的对象 nest,该对象用于进行法线估计运算。在创建这个对象时,需要指定输入点云和输出点云的数据类型。
  • 设置了法线估计中的一个参数 KSearch,表示在计算每个点的法向量时要考虑周围的最近邻点数,这里设置为 50。
  • 输入点云赋值给 nest 对象,并调用 compute() 函数来计算法向量。计算结果存储在一个 pcl::PointCloud<PointNT>::Ptr 类型的指针变量 normals 中。
pcl::NormalEstimation<PointT, PointNT> nest;
//nest.setRadiusSearch(0.01); // 设置拟合时邻域搜索半径,最好用模型分辨率的倍数
nest.setKSearch(50); 
nest.setInputCloud(cloud);
pcl::PointCloud<PointNT>::Ptr normals(new pcl::PointCloud<PointNT>);
nest.compute(*normals);
  • 将原始点云数据中的每个点的坐标信息(x、y、z)复制到法向量点云数据中去。
    生成时只生成了法向量,没有将原始点云信息拷贝,为了显示需要复制原信息
    也可用其他方法进行连接,如:pcl::concatenateFields
    for (size_t i = 0; i < cloud->points.size(); ++i)
    {	
    	normals->points[i].x = cloud->points[i].x;
    	normals->points[i].y = cloud->points[i].y;
    	normals->points[i].z = cloud->points[i].z;
    }
  •  将法向量计算结果和原始点云信息结合起来,并使用 PCL 库中的可视化工具进行展示。
    我们创建了一个 PCL 可视化对象 viewer,并使用 addPointCloud() 函数将原始点云数据添加到可视化对象中,命名为 "cloud"。
    设置了两个参数 levelscale,用于控制法向量集合的显示效果。其中 level 表示多少条法向量集合显示成一条,scale 表示法向量长度的缩放比例。
    调用 viewer.spin() 语句来启动可视化窗口,等待用户交互操作。
pcl::visualization::PCLVisualizer viewer;
viewer.setBackgroundColor(1, 0.6, 0.8,0.2);  // R=255/255, G=153/255, B=204/255	
pcl::visualization::PointCloudColorHandlerCustom<PointT> color_handler(cloud, 0, 255, 0);
viewer.addPointCloud<PointT>(cloud, color_handler, "cloud");
int level = 100;
float scale = 1; 
viewer.addPointCloudNormals<PointNT>(normals, level, scale, "normals");

viewer.spin();

 完整代码:

#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
// 包含相关头文件
#include <pcl/features/normal_3d.h>
#include <pcl/visualization/pcl_visualizer.h>

typedef pcl::PointXYZ PointT;
typedef pcl::PointNormal PointNT; // 也可以pcl::Normal,但无法用PCLVisualizer显示。

int main(int argc, char** argv)
{
	// 读取点云
	pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);

	if (pcl::io::loadPCDFile<PointT>("../input_cloud/rabbit.pcd", *cloud) == -1)
	{
		PCL_ERROR("找不到文件...\n");
		return -1;
	}

	// 计算法向量
	pcl::NormalEstimation<PointT, PointNT> nest;
	//nest.setRadiusSearch(0.01); // 设置拟合时邻域搜索半径,最好用模型分辨率的倍数
	nest.setKSearch(50); // 设置拟合时采用的点数
	nest.setInputCloud(cloud);
	pcl::PointCloud<PointNT>::Ptr normals(new pcl::PointCloud<PointNT>);
	nest.compute(*normals);

	for (size_t i = 0; i < cloud->points.size(); ++i)
	{	// 生成时只生成了法向量,没有将原始点云信息拷贝,为了显示需要复制原信息
		// 也可用其他方法进行连接,如:pcl::concatenateFields
		normals->points[i].x = cloud->points[i].x;
		normals->points[i].y = cloud->points[i].y;
		normals->points[i].z = cloud->points[i].z;
	}

	// 显示
	pcl::visualization::PCLVisualizer viewer;
	viewer.setBackgroundColor(1, 0.6, 0.8,0.2);  // R=255/255, G=153/255, B=204/255	
    pcl::visualization::PointCloudColorHandlerCustom<PointT> color_handler(cloud, 0, 255, 0);	
    viewer.addPointCloud<PointT>(cloud, color_handler, "cloud");
	int level = 100; // 多少条法向量集合显示成一条
	float scale = 1; // 法向量长度
	viewer.addPointCloudNormals<PointNT>(normals, level, scale, "normals");

	viewer.spin();

	system("pause");
	return 0;
}

运行效果:

 

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

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

相关文章

第14届蓝桥杯国赛真题剖析-2023年5月28日Scratch编程初中级组

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第149讲。 第14届蓝桥杯Scratch国赛真题&#xff0c;这是2023年5月28日上午举办的全国总决赛&#xff0c;比赛仍然采取…

进程管道:popen函数实例

基础知识 可能最简单的在两个程序之间传递数据的方法就是使用popen和pclose函数了。它们的原型如下所示&#xff1a; #include <stdio.h>FILE *popen(const char *command, const char *type);int pclose(FILE *stream); 1&#xff0e;popen函数 popen函数允许一个程…

FTL没有映射,跟发工资没有钱有什么区别

大家好&#xff0c;我是五月。 前言 FTL&#xff08;Flash Translation Layer&#xff09;&#xff0c;即闪存转换层&#xff0c;是各种存储设备的核心算法&#xff0c;作用是将Host传下来的逻辑地址转换成物理地址&#xff0c;也就是映射。 地址映射是FTL最原始最基本的功能…

苹果手机之间如何互传照片?批量传输操作指南

很多时候&#xff0c;我们用手机拍摄了好看的照片或者收藏了一些有趣的图片&#xff0c;想要分享给朋友&#xff0c;却不知道苹果手机之间如何互传照片&#xff1f;在分享大量照片的时候不清楚如何批量操作&#xff1f;别担心&#xff0c;下面小编就来分享一下苹果手机照片传输…

海思3559万能平台搭建:SPI输出h264码流

前言 面对各种各样的客户需求&#xff0c;spi接口也是一种传码流的形式&#xff0c;spi同步422可以保证抗干扰能力强的同时传输距离也很长&#xff0c;本文会介绍海思平台spi作为主机的发送功能以及发送码流的处理方式 1. 管脚复用&#xff1a; 首先需要配置的肯定是管脚复用&…

Linux进程间通信【共享内存】

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; Linux学习之旅 &#x1f383;操作环境&#xff1a; CentOS 7.6 阿里云远程服务器 文章目录 &#x1f307;前言&#x1f3d9;️正文1、什么是共享内存&#xff1f;2、共享内存的相关知识2.1、共享内存的数据结构…

load_dataset加载huggingface数据集失败

1. 一般的加载方式 from datasets import load_dataset dataset_dict load_dataset(cmrc2018)这种加载方式可能会显示因为连接问题导致失败&#xff0c;此时可以在hugging face里面找到对应的页面下载下来 然后改一下代码&#xff1a; from datasets import load_dataset d…

springmvc整合thymeleaf

概述 Thymeleaf提供了一组Spring集成&#xff0c;使您可以将其用作Spring MVC应用程序中JSP的全功能替代品。 这些集成将使您能够&#xff1a; Controller像使用JSP一样&#xff0c;将Spring MVC 对象中的映射方法转发到Thymeleaf管理的模板。在模板中使用Spring表达式语言&…

罗马不是一天建成的,那为什么建了那么多罗马?

这一个罗马&#xff0c;那一个罗马&#xff0c;东一个罗马&#xff0c;西一个罗马&#xff0c;世界历史的大半部分都在跟罗马打交道。更要命的是四大文明古国还没有古代罗马。 存在感这么强&#xff0c;还不是四大文明古国&#xff0c;名字还难记&#xff0c;公元前居然就有共…

【C++】在线编译器推荐,让你随时随地编写代码

▒ 目录 ▒ &#x1f6eb; 问题描述环境 1️⃣ 支持调试网站Repl.itOnlineGDB 2️⃣ 不支持调试网站Wandboxjson.cnjdoodletutorialspointcppshellideonecoliruonline-ide 3️⃣ 性能分析网站Quick C BenchmarkCompare C Builds 4️⃣ 其它C Insights&#xff08;学习模板、C11…

Hightopo 使用心得(3)- 吸附与锚点

吸附与锚点是 HT for Web 中两个比较重要的概念。这两个概念在执行交互和动画时会经常被用到。 吸附&#xff0c;顾名思义&#xff0c;是一个节点吸附到另一个节点上。就像船底的贝类一样&#xff0c;通过吸附到船身&#xff0c;在船移动的时候自己也会跟着移动&#xff1b;而…

pandas---缺失值的处理

1. 处理缺失值 判断数据中是否包含NaN&#xff1a; pd.isnull(df)&#xff1b;pd.notnull(df) 存在缺失值nan: 删除存在缺失值的:dropna(axisrows) 不会修改原数据&#xff0c;需要接受返回值&#xff1b; 替换缺失值:fillna(value, inplaceTrue) value:替换成的值&#…

JavaScript数学对象-数字进制转换

关注“大前端私房菜”微信公众号&#xff0c;输入暗号【面试宝典】即可免费领取107页前端面试题。 什么是进制 进制就是达到指定位置时候进一位 常见的进制 十进制: 0 1 2 3 4 5 6 7 8 9 10 11 12 ... 99 100 101 二进制: 0 1 10 11 100 101 110 111 1000 八进制: 0 1 2 3 4 …

走进人工智能|GANs AI时代下的前卫艺术

前言&#xff1a; GANs的作用是以生成模型的形式学习数据分布&#xff0c;从而产生逼真的样本数据&#xff0c;可以应用于图像合成、风格转换、视频生成等领域。 文章目录 序言背景适用领域技术支持应用领域程序员如何学总结 序言 GANs&#xff08;生成对抗网络&#xff09;是…

ASEMI代理台湾光宝LTV-3120光耦合器中文资料

编辑-Z LTV-3120是一种高性能光耦&#xff0c;由于其可靠性、效率和多功能性&#xff0c;在各种应用中都很受欢迎。本文将全面了解LTV-3120其功能、应用以及它如何改进您的电子设计。 什么是光电耦合器&#xff1f; 光耦&#xff0c;也称为光隔离器&#xff0c;是一种利用光在…

Mediapipe实时3D目标检测和跟踪(自动驾驶实现)

&#x1f680; 导语 3D目标检测是根据物体的形状、位置和方向来识别和定位物体的任务。在2D目标检测中&#xff0c;被检测到的物体仅表示为矩形边界框。3D目标检测任务通过预测物体周围的包围框&#xff0c;可以获取物体的三维位置信息。 3D目标检测在各行各业都有广泛的应用。…

Flink 系列二 Flink 状态化流处理概述

本篇作为Flink系列的第二篇&#xff0c;第一篇是环境准备&#xff0c;需要的同学可以看&#xff1a;https://blog.csdn.net/lly576403061/article/details/130358449?spm1001.2014.3001.5501。希望可以通过系统的学习巩固该方面的知识&#xff0c;丰富自己的技能树。废话不多说…

jmeter模拟多用户并发

目录 前言&#xff1a; 一、100个真实的用户 二、100个用户同时登录 前言&#xff1a; JMeter可以轻松地模拟多用户并发&#xff0c;从而测试Web应用程序的性能和稳定性。 一、100个真实的用户 1、一个账号模拟100虚拟用户同时登录和100账号同时登录 区别 &#xff08;…

运维圣经:Webshell应急响应指南

目录 Webshell简介 Webshell检测手段 Webshell应急响应指南 一. Webshell排查 二. 确定入侵时间 三. Web日志分析 四. 漏洞分析 五. 漏洞复现 六. 清除Webshell并修复漏洞 七. Webshell防御方法 Webshell简介 Webshell通常指以JSP、ASP、 PHP等网页脚本文件形式存在…

Webstorm 加载vue项目时,特别卡顿,完美解决。觉得有用加好友打赏

觉得有用加好友打赏&#xff1a;QQ&#xff1a;854138497 上图cpu直接干满。 根据上图提示&#xff0c;直接 disable hints&#xff0c;或者到下图的settings里面设置。 Code vision取消后&#xff0c;webstorm 明显就不卡了。记得重启webstorm。 还有一种方式&#xff0c;根…