法向量估计

/*
* @Description: 法向量估计(运⾏耗时2min)。:https://www.cnblogs.com/liyao7758258/p/6479255.html
* @Author: HCQ
* @Company(School): UCAS
* @Date: 2020-10-19 16:33:43
* @LastEditors: Please set LastEditors
* @LastEditTime: 2020-10-19 14:34:00
* @FilePath: /pcl-learning/10features特征/1法向量估计/normal_estimation.cpp
*/
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/integral_image_normal.h> //法线估计类头⽂件
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/point_types.h>
#include <pcl/features/normal_3d.h>
int
main ()
{//打开点云代码
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new
pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile ("../table_scene_lms400.pcd", *cloud);
//创建法线估计估计向量
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
ne.setInputCloud(cloud);
//创建⼀个空的KdTree对象,并把它传递给法线估计向量
//基于给出的输⼊数据集,KdTree将被建⽴
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new
pcl::search::KdTree<pcl::PointXYZ> ());
ne.setSearchMethod(tree);
//存储输出数据
pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new
pcl::PointCloud<pcl::Normal>);
//使⽤半径在查询点周围3厘⽶范围内的所有临近元素
ne.setRadiusSearch(0.03);
//计算特征值
ne.compute(*cloud_normals);
// cloud_normals->points.size ()应该与input cloud_downsampled->points.size ()有
相同的尺⼨
// 存储特征值为点云
pcl::PCDWriter writer;
writer.write<pcl::Normal> ( "../table_cloud_normals.pcd" , *cloud_normals,
false); // 保存⽂件
//可视化
pcl::visualization::PCLVisualizer viewer("PCL Viewer");
viewer.setBackgroundColor (0.0, 0.0, 0.0);
viewer.addPointCloudNormals<pcl::PointXYZ,pcl::Normal>(cloud, cloud_normals);
// 将估计的点云表⾯法线添加到屏幕
while (!viewer.wasStopped ())
{viewer.spinOnce ();
}
return 0;
}

表面估计

表面法线是几何体表面一个非常重要的属性,例如:在进行光照渲染的时候产生符合可视习惯的效果时需要表面法线的信息才能正常进行,对于一个已经知道的几何体表面,根据垂直于点表面的矢量,因此推出表面某一点的法线方向比较容易,然而由于我们获取的点云的数据集在真实的物体的表面表现为一组定点的样本,这样就会有两种方法解决:
(1)使用曲面重建技术,从获取的点云数据中得到采样点对应的曲面,然后从曲面模型中计算出表面法线。
(2)直接从点云数据中近似推断表面法线。

在确定表面一点法线的问题近似于估计表面的一个相切面法线的问题,因此转换过来就是求一个最小二乘法平面拟合的问题。

使用积分图进行法线估计Normal Estimation Using Integral Images

三种法线估计方法:
(1)COVARIANCE_MATRIX模式:从具体某个点的局部领域的协方差矩阵创建9个积分,来计算这个点的法线;
(2)AVERAGE_3D_GRADIENT模式:创建6个积分图来计算水平方向和垂直方向的平滑后的三维梯度并使用两个梯度间的向量积计算法线;
AVERAGE_DEPTH——CHANGE模式:只创建了⼀个单⼀的积分图,从⽽平局深度变化计算法线;

/*
* @Description: 为输⼊数据集中的点的⼦集估计⼀组表⾯法线。
https://pcl.readthedocs.io/projects/tutorials/en/latest/how_features_work.htm
l#how-3d-features-work
* @Author: HCQ
* @Company(School): UCAS
* @Email: 1756260160@qq.com
* @Date: 2020-10-19 15:04:50
* @LastEditTime: 2020-10-19 18:34:17
* @FilePath: /pcl-learning/10features特征/2估计点云⼦集的表⾯法线
(error)/normal_estimation_subdset_points.cpp
*/
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d.h>
// 报错已解决:下⾯报错 error: ‘shared_ptr’ is not a member of ‘pcl’
int main ()
{//打开点云代码
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new
pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile ("../table_scene_lms400.pcd", *cloud);
// //创建⼀组要使⽤的索引。为简单起⻅,我们将使⽤云中前10%的点
std::vector<int> indices (std::floor (cloud->size () / 10));
for (std::size_t i = 0; i < indices.size (); ++i) indices[i] = i;
// //创建NormalEstimation类,并将输⼊数据集传递给它
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
ne.setInputCloud (cloud);
// 传递索引
// std::shared_ptr<std::vector<int> > indicesptr (new std::vector<int>
(indices)); // 报错
pcl::shared_ptr<std::vector<int> > indicesptr (new std::vector<int>
(indices)); // 解决报错
ne.setIndices (indicesptr);
// 创建⼀个空的kdtree表示形式,并将其传递给normal estimation 对象
// 它的内容将根据给定的输⼊数据集填充到对象内部(因为未提供其他搜索表⾯)。
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new
pcl::search::KdTree<pcl::PointXYZ> ());
ne.setSearchMethod (tree);
// Output datasets
pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new
pcl::PointCloud<pcl::Normal>);
// 在半径3cm的范围内近邻
ne.setRadiusSearch (0.03);
// 计算特征
ne.compute (*cloud_normals);
// cloud_normals->size () should have the same size as the input
indicesptr->size ()
}

估算点特征直方图(PFH)特征

点特征直⽅图(PFH)在PCL中的实现是pcl_features模块的⼀部分。默认PFH的实现使⽤5个区间分类。(例如:四个特征值中的每个都使⽤5个区间来统计)

#include <pcl/point_types.h> //点类型头⽂件
#include <pcl/features/pfh.h> //pfh特征估计类头⽂件
...//其他相关操作
pcl::PointCloud<pcl::PointXYZ>::Ptrcloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::Normal>::Ptrnormals(new pcl::PointCloud<pcl::Normal>());
...//打开点云⽂件估计法线等
//创建PFH估计对象pfh,并将输⼊点云数据集cloud和法线normals传递给它
pcl::PFHEstimation<pcl::PointXYZ,pcl::Normal,pcl::PFHSignature125> pfh;
pfh.setInputCloud(cloud);
pfh.setInputNormals(normals);
//如果点云是类型为PointNormal,则执⾏pfh.setInputNormals (cloud);
//创建⼀个空的kd树表示法,并把它传递给PFH估计对象。
//基于已给的输⼊数据集,建⽴kdtree
pcl::KdTreeFLANN<pcl::PointXYZ>::Ptrtree(new pcl::KdTreeFLANN<pcl::PointXYZ>
());
pfh.setSearchMethod(tree);
//输出数据集
pcl::PointCloud<pcl::PFHSignature125>::Ptrpfhs(new
pcl::PointCloud<pcl::PFHSignature125>());
//使⽤半径在5厘⽶范围内的所有邻元素。
//注意:此处使⽤的半径必须要⼤于估计表⾯法线时使⽤的半径!!!
pfh.setRadiusSearch(0.05);
//计算pfh特征值
pfh.compute(*pfhs);
// pfhs->points.size ()应该与input cloud->points.size ()有相同的⼤⼩,即每个点都有⼀个pfh特征向量

估算FPFH

PFH和FPFH计算⽅式之间的主要区别总结如下:
(1)FPFH没有对全互连 点的所有邻近点的计算参数进⾏统计,从图中可以看到,因此可能漏掉了⼀些重要的点对,⽽这些漏掉的对点可能对捕获查询点周围的⼏何特征有贡献。
(2)PFH特征模型是对查询点周围的⼀个精确的邻域半径内,⽽FPFH还包括半径r范围以外的额外点对(不过在2r内);
(3)因为重新权重计算的⽅式,所以FPFH结合SPFH值,重新捕获邻近重要点对的⼏何信息;
(4)由于⼤⼤地降低了FPFH的整体复杂性,因此FPFH有可能使⽤在实时应⽤中;
(5)通过分解三元组,简化了合成的直⽅图。也就是简单⽣成d分离特征直⽅图,对每个特征维度来单独绘制,并把它们连接在⼀起;

#include
#include //fpfh特征估计类头⽂件声明
...//其他相关操作
pcl::PointCloud<pcl::PointXYZ>::Ptrcloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::Normal>::Ptrnormals(new pcl::PointCloud<pcl::Normal>());
...//打开点云⽂件估计法线等
//创建FPFH估计对象fpfh,并把输⼊数据集cloud和法线normals传递给它。
pcl::FPFHEstimation<pcl::PointXYZ,pcl::Normal,pcl::FPFHSignature33> fpfh;
fpfh.setInputCloud(cloud);
fpfh.setInputNormals(normals);
//如果点云是类型为PointNormal,则执⾏fpfh.setInputNormals (cloud);
//创建⼀个空的kd树对象tree,并把它传递给FPFH估计对象。
//基于已知的输⼊数据集,建⽴kdtree
pcl::search::KdTree<PointXYZ>::Ptrtree(new pcl::search::KdTree<PointXYZ>);
fpfh.setSearchMethod(tree);
//输出数据集
pcl::PointCloud<pcl::FPFHSignature33>::Ptrfpfhs(new
pcl::PointCloud<pcl::FPFHSignature33>());
//使⽤所有半径在5厘⽶范围内的邻元素
//注意:此处使⽤的半径必须要⼤于估计表⾯法线时使⽤的半径!!!
fpfh.setRadiusSearch(0.05);
//计算获取特征向量
fpfh.compute(*fpfhs);
// fpfhs->points.size ()应该和input cloud->points.size ()有相同的⼤⼩,即每个点有⼀个特征向量

估算视点特征直方图(VFH)

视点特征直⽅图(或VFH)是源于FPFH描述⼦。由于它的获取速度和识别⼒,我们决定利⽤FPFH强⼤的识别⼒,但是为了使构造的特征保持缩放不变性的性质同时,还要区分不同的位姿,计算时需要考虑加⼊视点变量。

我们做了以下两种计算来构造特征,以应⽤于⽬标识别问题和位姿估计:
(1)扩展FPFH,使其利⽤整个点云对象来进⾏计算估计(如2图所示),在计算FPFH时以物体中⼼点与物体表⾯其他所有点之间的点对作为计算单元。
(2)添加视点⽅向与每个点估计法线之间额外的统计信息,为了达到这个⽬的,我们的关键想法是在FPFH计算中将视点⽅向变量直接融⼊到相对法线⻆计算当中。

通过统计视点⽅向与每个法线之间⻆度的直⽅图来计算视点相关的特征分量。
注意:并不是每条法线的视⻆,因为法线的视⻆在尺度变换下具有可变性,我们指的是平移视点到查询点后的视点⽅向和每条法线间的⻆度。第⼆组特征分量就是前⾯PFH中讲述的三个⻆度,如PFH⼩节所述,只是现在测量的是在中⼼点的视点⽅向和每条表⾯法线之间的⻆度。

因此新组合的特征被称为视点特征直⽅图(VFH)。包含了两部分:
1.⼀个视点⽅向相关的分量
2.⼀个包含扩展FPFH的描述表⾯形状的分量。

#include <pcl/point_types.h>
#include <pcl/features/vfh.h> //VFH特征估计类头⽂件
...//其他相关操作
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new
pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>
());
...//打开点云⽂件估计法线等
//创建VFH估计对象vfh,并把输⼊数据集cloud和法线normal传递给它
pcl::VFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::VFHSignature308> vfh;
vfh.setInputCloud (cloud);
vfh.setInputNormals (normals);
//如果点云是PointNormal类型,则执⾏vfh.setInputNormals (cloud);
//创建⼀个空的kd树对象,并把它传递给FPFH估计对象。
//基于已知的输⼊数据集,建⽴kdtree
pcl::KdTreeFLANN<pcl::PointXYZ>::Ptr tree (new
pcl::KdTreeFLANN<pcl::PointXYZ> ());
vfh.setSearchMethod (tree);
//输出数据集
pcl::PointCloud<pcl::VFHSignature308>::Ptr vfhs (new
pcl::PointCloud<pcl::VFHSignature308> ());
//计算特征值
vfh.compute (*vfhs);
// vfhs->points.size ()的⼤⼩应该是1,即vfh描述⼦是针对全局的特征描述

PCL——点云特征描述与提取相关推荐

  1. PCL 点云特征描述与提取

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者:开着拖拉机唱山歌 链接:https://zhuanlan.zhihu.com/p/1032192 ...

  2. PCL中点云特征描述与提取精通级实例解析

    PCL中点云特征描述与提取精通级实例解析 1 3D对象识别的假设验证 2 隐式形状模型方法 2.1 隐式形状模型识别方法概述 2.2 实例解析 1 3D对象识别的假设验证   本教程将学习在高噪声和严 ...

  3. PCL点云特征描述与提取

    PCL点云特征描述与提取 1.局部描述子(local descriptor) (1)估计某一点的表面法线 (2)估计一个点云的表面法线 2.点特征直方图(Point Feature Histogram ...

  4. PCL代码经典赏析七:PCL 点云特征描述与提取

    文章目录 更新:2019年8月 说明 目录索引 PCL 点云特征描述与提取 PCL 描述三维特征相关基础 PCL 法线估计实例 ------ 估计某一点的表面法线 PCL 法线估计实例 ------ ...

  5. PCL点云特征描述与提取(1)

    3D点云特征描述与提取是点云信息处理中最基础也是最关键的一部分,点云的识别.分割,重采样,配准曲面重建等处理大部分算法,都严重依赖特征描述与提取的结果.从尺度上来分,一般分为局部特征的描述和全局特征的 ...

  6. PCL点云特征描述与提取(4)

    如何从一个深度图像(range image)中提取NARF特征 代码解析narf_feature_extraction.cpp #include <iostream>#include &l ...

  7. PCL点云特征描述与提取(3)

    快速点特征直方图(FPFH)描述子 已知点云P中有n个点,那么它的点特征直方图(PFH)的理论计算复杂度是,其中k是点云P中每个点p计算特征向量时考虑的邻域数量.对于实时应用或接近实时应用中,密集点云 ...

  8. PCL点云特征描述与提取(2)

    点特征直方图(PFH)描述子 正如点特征表示法所示,表面法线和曲率估计是某个点周围的几何特征基本表示法.虽然计算非常快速容易,但是无法获得太多信息,因为它们只使用很少的几个参数值来近似表示一个点的k邻 ...

  9. PCL中3D点云特征描述与提取(三)

    PCL中3D点云特征描述与提取(三) 1 如何从一个深度图像中提取NARF特征 2 RoPs特征 2.1 理论基础 2.1.1 生物视觉认知学启示 2.1.2 局部参考坐标框架构建 2.1.3 RoP ...

最新文章

  1. 我也没想到 springboot + rabbitmq 做智能家居,会这么简单
  2. GOROOT、GOPATH
  3. 在android布局中使用include和merge标签
  4. MyBatisPlus中自定义全局操作流程
  5. 10.9 kill以及raise函数
  6. mac下anaconda安装selenium+PhantomJS
  7. 在一个电子商务网站应用中,涉及的实体信息类有很多,比如用户类User和用户地址类Address; 而每一个实体类的对象信息要存储到相应的数据库表中,如userTable和addressTable。
  8. python init self_转载--------Python中:self和__init__的含义 + 为何要有self和__init__
  9. 哲学家就餐问题(如何避免死锁)(多线程版)
  10. 线程池ThreadPoolExecutor使用
  11. 软件工程系组织12级学生到工商学院参加比赛
  12. 联想电脑EasyCamera无法打开摄像头
  13. android 手机格式验证,android – 使用国家/地区代码验证手机号码
  14. java阶梯计费_Excel阶梯计费的公式
  15. QSPI FLASH与SD卡同时支持fatfs文件系统
  16. javascript Array系列函数之2:unshift
  17. Win11色温如何进行调整设置
  18. 录屏软件电脑版免费哪个好?4款免费屏幕录制软件下载
  19. numpy.random.randint()函数生成随机坐标点
  20. Ubuntu搭建深度学习环境(3090显卡)

热门文章

  1. netDxf实现对cad文件的读取与写入
  2. 关于在GET请求中使用body
  3. Java项目:电影院售票管理系统(java+Servlet+JSP+JDBC+Mysql)
  4. Google服务器架构图解简析
  5. 解决xlrd不能打开xlsx表格以及打开失败问题
  6. 利用马尔可夫模型分析游戏装备强化概率问题
  7. 空之轨迹手游服务器维护,空之轨迹7月9日临时维护公告_空之轨迹7月9日更新了什么_玩游戏网...
  8. 自媒体常用小程序:去水印、配音、文案提取
  9. Cypher高级查询
  10. 我们总在拒绝别人,又如何能提高得了自己?