PCL 法向量精细化处理

目录

一、概述

1.1原理

1.2实现步骤

1.3应用场景

二、代码实现

2.1关键函数

2.1.1 pcl::NormalEstimationOMP

2.1.2 pcl::NormalRefinement

2.1.3 visualizePointCloud

2.2完整代码

三、实现效果


PCL点云算法汇总及实战案例汇总的目录地址链接:

PCL点云算法与项目实战案例汇总(长期更新)


一、概述

        法向量精细化处理不仅可以提高法向量的估计精度,还可以用于后续的点云处理和特征提取任务。通过对比初始法向量与精细化法向量的可视化效果,可以直观地看到处理的提升。

1.1原理

        法向量估计基于最近邻点的协方差矩阵,通过计算法线的方向来描述点云表面的局部几何形状。为了进一步优化法向量结果,法向量精细化使用加权平均法调整法线方向,使其更平滑并更加贴合表面结构。法向量计算公式为:

1.2实现步骤

  1. 加载点云数据:从PCD文件中加载点云。
  2. 法向量计算:通过最近邻搜索为每个点计算法向量。
  3. 法向量精细化:对初始法向量进行平滑处理。
  4. 可视化:封装可视化函数,显示原始法向量与精细化后的法向量对比。

1.3应用场景

  1. 3D重建:提升法向量精度,增强3D模型的重建效果。
  2. 曲面光滑处理:通过精细化法向量来实现曲面平滑。
  3. 特征提取:在法向量基础上进行更精确的几何特征提取。

二、代码实现

2.1关键函数

2.1.1 pcl::NormalEstimationOMP

并行加速法向量估计函数,利用OpenMP进行并行计算。

pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> ne;
ne.computePointNormal(*cloud, k_indices[i],normal.normal_x, normal.normal_y, normal.normal_z, normal.curvature);

2.1.2 pcl::NormalRefinement

法向量精细化处理函数,迭代调整法向量。

pcl::NormalRefinement<pcl::Normal> nr(k_indices, k_sqr_distances);
nr.setMaxIterations(50);        // 设置最大迭代次数
nr.setConvergenceThreshold(0.1); // 设置收敛阈值
nr.filter(*normals_refined);    // 进行法线精细化处理

2.1.3 visualizePointCloud

封装可视化函数,显示原始点云、法向量及精细化后的法向量。

void visualizePointCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud,pcl::PointCloud<pcl::Normal>::Ptr& normals,pcl::PointCloud<pcl::Normal>::Ptr& normals_refined)
{boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("Normal viewer"));int v1(0), v2(1);viewer->setWindowName("法向量精细化处理");viewer->createViewPort(0, 0.0, 0.5, 1.0, v1);viewer->createViewPort(0.5, 0.0, 1.0, 1.0, v2);viewer->setBackgroundColor(1.0, 1.0, 1.0, v1);viewer->setBackgroundColor(0.98, 0.98, 0.98, v2);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color(cloud, 0, 225, 0);viewer->addCoordinateSystem(0.1);viewer->addPointCloud<pcl::PointXYZ>(cloud, single_color, "sample cloud", v1);viewer->addPointCloudNormals<pcl::PointXYZ, pcl::Normal>(cloud, normals, 20, 0.02, "normals", v1);viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "sample cloud", v1);viewer->addPointCloud<pcl::PointXYZ>(cloud, single_color, "cloud", v2);viewer->addPointCloudNormals<pcl::PointXYZ, pcl::Normal>(cloud, normals_refined, 20, 0.02, "normals_refined", v2);viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "cloud", v2);while (!viewer->wasStopped()){viewer->spinOnce(100);boost::this_thread::sleep(boost::posix_time::microseconds(100000));}
}

2.2完整代码

#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d_omp.h> // 使用OMP并行计算法向量
#include <pcl/filters/normal_refinement.h> // 法向量精细化处理
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>// 封装的可视化函数
void visualizePointCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud,pcl::PointCloud<pcl::Normal>::Ptr& normals,pcl::PointCloud<pcl::Normal>::Ptr& normals_refined)
{boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("Normal viewer"));int v1(0), v2(1);viewer->setWindowName("法向量精细化处理");viewer->createViewPort(0, 0.0, 0.5, 1.0, v1);viewer->createViewPort(0.5, 0.0, 1.0, 1.0, v2);viewer->setBackgroundColor(0.0, 0.0, 0.0, v1);viewer->setBackgroundColor(0.08, 0.08, 0.08, v2);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color(cloud, 0, 225, 0);viewer->addCoordinateSystem(0.1);viewer->addPointCloud<pcl::PointXYZ>(cloud, single_color, "sample cloud", v1);viewer->addPointCloudNormals<pcl::PointXYZ, pcl::Normal>(cloud, normals, 20, 0.02, "normals", v1);viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "sample cloud", v1);viewer->addPointCloud<pcl::PointXYZ>(cloud, single_color, "cloud", v2);viewer->addPointCloudNormals<pcl::PointXYZ, pcl::Normal>(cloud, normals_refined, 20, 0.02, "normals_refined", v2);viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "cloud", v2);while (!viewer->wasStopped()){viewer->spinOnce(100);boost::this_thread::sleep(boost::posix_time::microseconds(100000));}
}int main()
{// ------------------------------加载点云数据---------------------------------pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);if (pcl::io::loadPCDFile<pcl::PointXYZ>("bunny.pcd", *cloud) == -1){PCL_ERROR("Could not read file\n");return -1;}const int k = 50; // K近邻点的个数std::vector<pcl::Indices> k_indices; // 近邻点的索引std::vector<std::vector<float>> k_sqr_distances; // 到近邻点的距离// ----------------------------构建邻域点索引---------------------------------pcl::search::KdTree<pcl::PointXYZ> search; // 初始化KD树的search方法search.setInputCloud(cloud);  // 输入点云search.nearestKSearch(*cloud, pcl::Indices(), k, k_indices, k_sqr_distances); // 获取点云数据中每个点的K近邻// ------------------------------计算法线-------------------------------------pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> ne;pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);for (size_t i = 0; i < cloud->size(); ++i){pcl::Normal normal;ne.computePointNormal(*cloud, k_indices[i],normal.normal_x, normal.normal_y, normal.normal_z, normal.curvature);// 法线方向朝向视点pcl::flipNormalTowardsViewpoint((*cloud)[i], (*cloud).sensor_origin_[0], (*cloud).sensor_origin_[1], (*cloud).sensor_origin_[2],normal.normal_x, normal.normal_y, normal.normal_z);normals->push_back(normal);}// ------------------------------法线精细化处理------------------------------------pcl::PointCloud<pcl::Normal>::Ptr normals_refined(new pcl::PointCloud<pcl::Normal>);pcl::NormalRefinement<pcl::Normal> nr(k_indices, k_sqr_distances); // 法线精细化处理nr.setInputCloud(normals);      // 添加法向量nr.setMaxIterations(500);        // 最大迭代次数nr.setConvergenceThreshold(0.01);// 收敛阈值nr.filter(*normals_refined);    // 进行法线精细化处理// 调用可视化函数visualizePointCloud(cloud, normals, normals_refined);return 0;
}

三、实现效果

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

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

相关文章

非酒精性脂肪性肝炎NASH临床赛道的百米冲刺,谁将成为胜者?

前 言 非酒精性脂肪性肝炎&#xff08;NASH&#xff09;是一种与肥胖、血脂异常、2型糖尿病和代谢综合征密切相关的疾病&#xff0c;可能会发展为肝硬化、终末期肝病甚至肝癌。据美国肝脏基金会统计数据显示&#xff0c;截至2023年8月&#xff0c;美国成年人中有5%的NASH患者…

【牛客刷题实战】BC120 争夺前五名

大家好&#xff0c;我是小卡皮巴拉 文章目录 目录 牛客题目&#xff1a; BC120 争夺前五名 题目描述 输入描述&#xff1a; 输出描述&#xff1a; 示例1 示例2 解题思路&#xff1a; 具体思路&#xff1a; 题目要点&#xff1a; 完整代码&#xff1a; 兄弟们共…

WMS 智慧仓储管理系统的可视化管理_SunWMS

【大家好&#xff0c;我是唐Sun&#xff0c;唐Sun的唐&#xff0c;唐Sun的Sun。一站式数智工厂解决方案服务商】 WMS 智慧仓储管理系统的可视化管理主要表现在以下几个方面&#xff1a; 首先是库存可视化。通过系统&#xff0c;仓库管理人员能够以直观的图表、图形等形式清晰地…

基于sklearn的机器学习应用平台 v2.0

基于sklearn的机器学习应用平台 v2.0 链接&#xff1a;https://pan.baidu.com/s/1nvHMTrtBmtPLT4oNXdw74A 提取码私信博主获取 关于作者 作者&#xff1a;小白熊 作者简介&#xff1a;精通python、matlab、c#语言&#xff0c;擅长机器学习&#xff0c;深度学习&#xff0c;机…

【实时计算 Flink】检查点和快照超时的诊断方法与调优策略

Flink的状态管理是一个复杂而关键的领域&#xff0c;涉及到作业的性能、稳定性和资源利用等多个方面。通过对状态生成机制和优化策略地深入理解与正确应用&#xff0c;结合实时计算Flink版提供的产品能力&#xff0c;可以帮您有效地优化Flink作业以应对大规模状态作业带来的挑战…

卫瓴科技,驶向「协同CRM」深水区

在卫瓴协同CRM的产品之上&#xff0c;能看到的不单纯是产品本身&#xff0c;即“提高转化率”这个单纯的指标&#xff0c;而更多的是在产品之中蕴含的“现代企业营销建设”的科学理念和认知。以此为基础&#xff0c;企业可以构建真正有价值且能长期驱动的品牌营销模型。 作者…

是德(Keysight)N9030A、N9030B PXA信号分析仪

Keysight N9030B PXA 信号分析仪是加速高要求应用创新的性能基准。 PXA 提供从优秀到卓越的测量选项&#xff0c;让您处于领先地位。利用高达 510 MHz 的分析带宽和优于 70 dB 的 SFDR 来分析最新信号&#xff0c;并通过本底噪声扩展 (NFE) 揭示以前隐藏的信号。要了解设备的真…

pdf怎么加密码怎么设置密码?这几种pdf设置密码的方法简单!

pdf怎么加密码怎么设置密码&#xff1f;PDF格式作为现代办公和学习中频繁使用的文档类型&#xff0c;其身影遍布于各类场景&#xff0c;然而&#xff0c;在享受PDF带来的便利之余&#xff0c;不少用户对其安全性产生了疑虑&#xff0c;尽管PDF文件相较于其他格式更难被直接编辑…

养生健康:从日常细节中寻觅长寿之钥

养生健康&#xff1a;从日常细节中寻觅长寿之钥 在这个快节奏的时代&#xff0c;健康似乎成了一种奢侈品&#xff0c;但实则不然。养生之道&#xff0c;不在于繁复的仪式&#xff0c;而在于融入日常的点点滴滴。今天&#xff0c;就让我们一起探讨几个简单却至关重要的养生习惯…

冷流还是热流

https://www.youtube.com/watch?vM8YtV47kaqA&t607s pl学习视频 什么是冷流&#xff1f; fun fibonacci(): Flow<BigInteger> flow {var x BigInteger.ZEROvar y BigInteger.ONEwhile (true) {println("fibonacci while $x")emit(x)x y.also {y x}…

【GESP】C++一级练习BCQM3033,略微复杂的计算,国庆七天乐

应该算第一道对小学生来说&#xff0c;计算逻辑稍微复杂一点的题目。多定义几个变量可能对解题过程更有帮助。 题解详见&#xff1a;https://www.coderli.com/gesp-1-bcqm3033/ 【GESP】C一级练习BCQM3033&#xff0c;略微复杂的计算&#xff0c;国庆七天乐 | OneCoder应该算第…

前端vue-安装pinia,它和vuex的区别

创建一个store的目录&#xff0c;任意一个js文件&#xff0c;再导入pinia&#xff0c;再定义

虚拟化数据恢复—互斥不当导致vmfs卷损坏的数据恢复案例

虚拟化数据恢复环境&#xff1a; 某企业信息管理平台&#xff0c; 几台VMware ESX Server主机共享一台存储设备&#xff0c;大约有几十台虚拟机。 虚拟化故障&原因&#xff1a; Vcenter报告虚拟磁盘丢失。管理员通过ssh远程到ESX中执行fdisk -l命令查看磁盘&#xff0c;发…

Authentication Lab | Client Side Auth

关注这个靶场的其它相关笔记&#xff1a;Authentication Lab —— 靶场笔记合集-CSDN博客 0x01&#xff1a;Client Side Auth 前情提要 有些时候&#xff0c;开发人员会将身份验证的逻辑写于前端&#xff0c;这样写是十分不安全的&#xff0c;因为前端的代码几乎全部都是可见的…

《Windows PE》5.1 导出表

导出表&#xff08;Export Table&#xff09;是一个在可执行文件或动态链接库&#xff08;DLL&#xff09;中的数据结构&#xff0c;用于描述该文件中导出的函数、变量和其他符号。导出表通常位于DLL动态链接库中。 本节必须掌握的知识点&#xff1a; 导入表数据结构 PE中的导…

【数据结构与算法】Divide and Conquer

4.4 Divide and Conquer 1) 概述 分治思想 将大问题划分为两个到多个子问题子问题可以继续拆分成更小的子问题&#xff0c;直到能够简单求解如有必要&#xff0c;将子问题的解进行合并&#xff0c;得到原始问题的解 之前学过的一些经典分而治之的例子 二分查找快速排序归并…

九、Drf序列化器

九、序列化器 9.1序列化 从数据库取QuerySet或数据对象转换成JSON 9.1.1序列化器的简易使用 #新建一张部门表 class Depart(models.Model):titlemodels.CharField(verbose_name部门,max_length32)ordermodels.IntegerField(verbose_name顺序)countmodels.IntegerField(verb…

软件测试学习笔记丨allure学习指南

本文转自测试人社区&#xff0c;原文链接&#xff1a;https://ceshiren.com/t/topic/32336 安装与下载 需要下载本地文件&#xff0c;并且添加到环境变量里 windows&#xff1a;下载&#xff0c;解压&#xff0c;并配置环境变量 mac&#xff1a;brew install allure 环境变量…

Docsify搭建个人博客

前提&#xff1a;电脑安装了Node.js 安装到本地 CMD命令下输入node -v查看是否已经安装了Node.js 安装docsify-cli工具&#xff1a;npm i docsify-cli -g 使用git下载docsify-Plus项目&#xff0c;Gitee地址&#xff1a;https://gitee.com/librarycodes/docsify-plus cd…

Linux的启动流程、移植到开发板

1、linux驱动开发与裸机开发的区别 Linux系统驱动和裸机驱动的主要区别在于运行时的环境和依赖。Linux系统驱动依赖于Linux内核提供的API和服务&#xff0c;而裸机驱动则是在没有操作系统支持的情况下直接与硬件交互。因此&#xff0c;两者的开发和调试方法也有很大差异。 2、…