pcl--第五节 点云表面法线估算

估算点云表面法线 *¶

表面法线是几何表面的重要属性,在许多领域(例如计算机图形应用程序)中大量使用,以应用正确的光源以产生阴影和其他视觉效果。

给定一个几何表面,通常很难将表面某个点的法线方向推断为垂直于该点表面的向量。但是,由于我们获取的点云数据集是真实表面上的一组点样本,因此有两种可能性:

  1. 使用表面网格化技术从获取的点云数据集中获取基础表面,然后从网格中计算表面法线;
  2. 使用近似值直接从点云数据集中推断表面法线。

我们将使用后者,即给定点云数据集,直接计算云中每个点的表面法线。

理论基础¶

尽管有许多不同的法线估计方法,我们先了解其中最简单也是最常见的一个,确定表面一点法线的问题近似于估计表面的一个相切面法线的问题,因此转换过来以后就变成一个最小二乘法平面拟合估计问题。

参见官网介绍

算法论文链接RusuDissertation

法线计算¶

image-20200511174327410

image-20200511174656445

// 定义一小块表面区域的协方差矩阵
Eigen::Matrix3f covariance_matrix;
// 定义一小块表面区域的质心坐标
Eigen::Vector4f xyz_centroid;
// 计算质心坐标
pcl::compute3DCentroid(*cloud, xyz_centroid);
// 计算3x3的协方差矩阵
pcl::computeCovarianceMatrix(*cloud , xyz_centroid, covariance_matrix);

法线方向问题¶

没有直接的数学方法可以解决法线的朝向问题,如下边的左图和中图,该数据及来自厨房环境的一部分。很明显图中显示出的法线方向并非朝着一个方向。可以观察右图,对所有法线合并成的扩展高斯图(EGI),也称为法线球体(Normal Sphere),它描述了点云中所有法线的方向。由于数据是2.5维的,即数据只从单一视角获取,其法线也应该仅是一个半球体的扩展高斯图,由于我们没有定下法线的方向,所以这些法线遍布球体。

image-20200516192216734

image-20200516192721669

则可以观察到将所有法线重新定向之后的效果和其对应的扩展高斯图EGI。

选择合适的比例¶

如前所述,需要根据该点的周围点邻域支持,也称为k-neighborhood(k邻域)来估算该点的表面法线。 最近邻估计问题的细节提出了正确的比例因子的问题:给定采样点云数据集,如何选择正确的k(通过pcl::Feature::setKSearch给出)或r(通过pcl::Feature::setRadiusSearch 给出)值来确定点的最近邻居?

image-20200516182945375

这个问题非常重要,并且构成了点特征表示的自动估计(即在没有用户给定阈值的情况下)的限制因素。为了更好地说明此问题,下图显示了选择较小的比例(即较小的r或k)与较大的比例(即较大的r或k)的效果。图的左侧部分描绘了一个合理选择的比例因子,其中估计的表面法线大致垂直于两个平面,并且在整个桌子上可见小的边缘。但是,如果比例因子太大(右侧部分),则相邻对象的集合会覆盖来自相邻表面的较大点,则估计的点要素表示会失真,在两个平面边缘处旋转的曲面法线会被涂抹边缘和压制的精细细节。

_images/normals_different_radii.jpg

_images/curvature_different_radii.jpg

无需赘述太多,只需假设现在必须根据应用所需的详细程度来选择确定点的邻域的比例即可。简而言之,如果杯子的手柄和圆柱部分之间的边缘处的曲率很重要,则比例因子必须足够小以捕获这些细节,否则要大。

默认视点坐标为(0,0,0)(0,0,0),可以使用以下代码修改:

setViewPoint(float vpx, float vpy, float vpx);

计算表面法向量内部伪代码:

// 遍历每个点云P中的点p
for each point p in cloud P // 得到p点的最近邻1. get the nearest neighbors of p// 计算p点的表面法线n2. compute the surface normal n of p// 检查n的方向是否指向视点,如果不是则进行反转3. check if n is consistently oriented towards the viewpoint and flip otherwise

#include <pcl/visualization/cloud_viewer.h>
#include <iostream>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d.h>int
main() {// load point cloudpcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::io::loadPCDFile("person.pcd", *cloud);// estimate normalspcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);// Object for normal estimation.pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normalEstimation;//normalEstimation.setIndices()normalEstimation.setInputCloud(cloud);// For every point, use all neighbors in a radius of 3cm.normalEstimation.setRadiusSearch(0.03);// A kd-tree is a data structure that makes searches efficient. More about it later.// The normal estimation object will use it to find nearest neighbors.pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree(new pcl::search::KdTree<pcl::PointXYZ>);normalEstimation.setSearchMethod(kdtree);// Calculate the normals.normalEstimation.compute(*normals);// visualize normalspcl::visualization::PCLVisualizer viewer("PCL Viewer");viewer.setBackgroundColor(0.0, 0.0, 0.5);viewer.addPointCloud<pcl::PointXYZ>(cloud, "cloud");// 参数int level=2 表示每n个点绘制一个法向量// 参数float scale=0.01 表示法向量长度缩放为0.01倍viewer.addPointCloudNormals<pcl::PointXYZ, pcl::Normal>(cloud, normals, 2, 0.01, "normals");//    viewer.addCoordinateSystem(1.0);while (!viewer.wasStopped()) {viewer.spinOnce();}return 0;
}

 

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

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

相关文章

python execute() 使用%s 拼接sql 避免sql注入攻击 好于.format

1 execute(参数一:sql 语句) # 锁定当前查询结果行 cursor.execute("SELECT high, low, vol FROM table_name WHERE symbol %s FOR UPDATE;"% (symbol,)) 2 .format() cursor.execute("SELECT high, low, vol FROM table_name WHERE symbol {} FOR UPDATE;…

Pytorch实现LSTM预测模型并使用C++相应的ONNX模型推理

Pytorch实现RNN模型 代码 import torch import torch.nn as nnclass LSTM(nn.Module):def __init__(self, input_size, output_size, out_channels, num_layers, device):super(LSTM, self).__init__()self.device deviceself.input_size input_sizeself.hidden_size inpu…

CockroachDB集群部署

CockroachDB集群部署 1、CockroachDB简介 CockroachDB(有时简称为CRDB)是一个免费的、开源的分布式 SQL 数据库&#xff0c;它建立在一个事务性和强一致性的键 值存储之上。它由 PebbleDB(一个受 RocksDB/leveldb 启发的 K/B 存储库)支持&#xff0c;并使用 Raft 分布式共识…

TypeScript入门

目录 一&#xff1a;语言特性 二&#xff1a;TypeScript安装 NPM 安装 TypeScript 三&#xff1a;TypeScript基础语法 第一个 TypeScript 程序 四&#xff1a;TypeScript 保留关键字 空白和换行 TypeScript 区分大小写 TypeScript 注释 TypeScript 支持两种类型的注释 …

初识C语言——详细入门一(系统性学习day4)

目录 前言 一、C语言简单介绍、特点、基本构成 简单介绍&#xff1a; 特点&#xff1a; 基本构成&#xff1a; 二、认识C语言程序 标准格式&#xff1a; 简单C程序&#xff1a; 三、基本构成分类详细介绍 &#xff08;1&#xff09;关键字 &#xff08;2&#xf…

fork函数

二.fork函数 2.1函数原型 fork()函数在 C 语言中的原型如下&#xff1a; #include <unistd.h>pid_t fork(void);其中pid_t是一个整型数据类型&#xff0c;用于表示进程ID。fork()函数返回值是一个pid_t类型的值&#xff0c;具体含义如下&#xff1a; 如果调用fork()的…

MyBatis中当实体类中的属性名和表中的字段名不一样,怎么办

方法1&#xff1a; 在mybatis核心配置文件中指定&#xff0c;springboot加载mybatis核心配置文件 springboot项目的一个特点就是0配置&#xff0c;本来就省掉了mybatis的核心配置文件&#xff0c;现在又加回去算什么事&#xff0c;总之这种方式可行但没人这样用 具体操作&…

MFC C++ 数据结构及相互转化 CString char * char[] byte PCSTR DWORE unsigned

CString&#xff1a; char * char [] BYTE BYTE [] unsigned char DWORD CHAR&#xff1a;单字节字符8bit WCHAR为Unicode字符:typedef unsigned short wchar_t TCHAR : 如果当前编译方式为ANSI(默认)方式&#xff0c;TCHAR等价于CHAR&#xff0c;如果为Unicode方式&#xff0c…

Python灰帽编程——错误异常处理与面向对象

文章目录 错误异常处理与面向对象1. 错误和异常1.1 基本概念1.1.1 Python 异常 1.2 检测&#xff08;捕获&#xff09;异常1.2.1 try except 语句1.2.2 捕获多种异常1.2.3 捕获所有异常 1.3 处理异常1.4 特殊场景1.4.1 with 语句 1.5 脚本完善 2. 内网主机存活检测程序2.1 scap…

Git从入门到起飞(详细)

Git从入门到起飞 Git从入门到起飞什么是Git&#xff1f;使用git前提(注册git)下载Git在Windows上安装Git在macOS上安装Git在Linux上安装Git 配置Git配置全局用户信息配置文本编辑器 创建第一个Git仓库初始化仓库拉取代码添加文件到仓库提交更改推送 Git基本操作查看提交历史比较…

【Java 基础篇】Java字符打印流详解:文本数据的输出利器

在Java编程中&#xff0c;我们经常需要将数据输出到文件或其他输出源中。Java提供了多种输出流来帮助我们完成这项任务&#xff0c;其中字符打印流是一个非常有用的工具。本文将详细介绍Java字符打印流的用法&#xff0c;以及如何在实际编程中充分利用它。 什么是字符打印流&a…

矩阵 m * M = c

文章目录 题1题2 题1 (2023江苏领航杯-prng) 题目来源&#xff1a;https://dexterjie.github.io/2023/09/12/%E8%B5%9B%E9%A2%98%E5%A4%8D%E7%8E%B0/2023%E9%A2%86%E8%88%AA%E6%9D%AF/ 题目描述&#xff1a; (没有原数据&#xff0c;自己生成的数据) from Crypto.Util.number…

DNG格式详解,DNG是什么?为何DNG可以取代RAW统一单反相机、苹果安卓移动端相机拍摄输出原始图像数据标准

返回图像处理总目录&#xff1a;《JavaCV图像处理合集总目录》 前言 在DNG格式发布之前&#xff0c;我们先了解一下之前单反相机、苹果和安卓移动端相机拍照输出未经处理的原始图像格式是什么&#xff1f; RAW 什么是RAW&#xff1f; RAW是未经处理、也未经压缩的格式。可以…

Rust通用编程概念(3)

Rust通用编程概念 1.变量和可变性1.执行cargo run2.变量3.变量的可变性4.常量5.遮蔽5.1遮蔽与mut区别1.遮蔽2.mut 2.数据类型1.标量类型1.1整数类型1.2浮点数类型1.3数字运算1.4布尔类型1.5字符类型 2.复合类型2.1元组类型2.2数组类型1.访问数组2.无效的数组元素访问 3.函数3.1…

js实现贪吃蛇游戏

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>贪吃蛇游戏</title><style>.game-contai…

如何解决 503 Service Temporarily Unavailable?

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f405;&#x1f43e;猫头虎建议程序员必备技术栈一览表&#x1f4d6;&#xff1a; &#x1f6e0;️ 全栈技术 Full Stack: &#x1f4da…

想要精通算法和SQL的成长之路 - 填充书架

想要精通算法和SQL的成长之路 - 填充书架 前言一. 填充书架1.1 优化 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 填充书架 原题链接 题目中有一个值得注意的点就是&#xff1a; 需要按照书本顺序摆放。每一层当中&#xff0c;只要厚度不够了&#xff0c;当前层最高…

vue3写垂直轮播效果(translateY)

实现思路&#xff1a;卡片移动使用css的translateY属性实现&#xff0c;每个卡片从最下面移动到最上面&#xff0c;然后直接移动到最下面&#xff0c;每次改变的位移是固定的&#xff0c;假设每次移动50px&#xff0c;当移动到最小时&#xff0c;就让translataY为0&#xff0c;…

Python150题day06

1.4字典练习题 ①字典基本操作 dic { python: 95, java: 99, c: 100 } 用程序解答以下题目 1.字典的长度是多少 2.请修改java这个key对应的value值为98 3.删除 c 这个key 4.增加一个key-value对&#xff0c;key值为 php,value是90 5.获取所有的key值&#xff0c;存储在列表里…

【考研数学】高等数学第六模块 —— 空间解析几何(1,向量基本概念与运算)

文章目录 引言一、空间解析几何的理论1.1 基本概念1.2 向量的运算 写在最后 引言 我自认空间想象能力较差&#xff0c;所以当初学这个很吃力。希望现在再接触&#xff0c;能好点。 一、空间解析几何的理论 1.1 基本概念 1.向量 —— 既有大小&#xff0c;又有方向的量称为向…