PointCloudLib-1.12.1学习笔记-特征(Features)-估计点云中的表面法线

曲面法线是几何曲面的重要属性,并且 大量用于许多领域,例如计算机图形学应用,以应用 校正产生阴影和其他视觉效果的光源。

给定一个几何表面,推断 在表面上的某个点法线,作为垂直于 在这一点上浮出水面。但是,由于我们获取的点云数据集 表示真实表面上的一组点样本,有两个 可能性:

  • 从获取的点云数据集获取下垫表面,使用 曲面网格划分技术,然后从 网孔;
  • 使用近似值从点云数据集推断表面法线 径直。

本教程将解决后者,即给定点云数据集, 直接计算云中每个点的表面法线。

理论入门

尽管存在许多不同的正态估计方法,但我们将 专注于本教程是最简单的教程之一,其表述为 遵循。确定曲面上某个点的法线的问题是 近似于估计与 曲面,进而成为最小二乘平面拟合估计问题。

注意

有关更多信息,包括最小二乘问题的数学方程,请参阅 [RusuDissertation]。

因此,估计表面法线的解决方案简化为 特征向量和特征值(或 PCA – 主成分)的分析 分析)从 查询点。更具体地说,对于每个点\粗体符号{p}_i,我们 按如下方式组装协方差矩阵\mathcal{C}

 

\mathcal{C} = \frac{1}{k}\sum_{i=1}^{k}{\cdot (\boldsymbol{p}_i-\overline{\boldsymbol{p}})\cdot(\boldsymbol{p}_i-\overline{\boldsymbol{p}})^{T}}, ~\mathcal{C} \cdot \vec{​{\mathsf v}_j} = \lambda_j \cdot \vec{​{\mathsf v}_j},~ j \in \{0, 1, 2\}

其中k考虑的点相邻要素数 的邻域表示\overline{\boldsymbol{p}}最近邻的 \粗体符号{p}_i3D 质心,\lambda_j是协方差矩阵的第 -个特征值和第 j\vec{​{\mathsf v}_j} j-个特征向量。

要从 PCL 中的一组点估计协方差矩阵,可以使用:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
  // Placeholder for the 3x3 covariance matrix at each surface patch
  Eigen::Matrix3f covariance_matrix;
  // 16-bytes aligned placeholder for the XYZ centroid of a surface patch
  Eigen::Vector4f xyz_centroid;

  // Estimate the XYZ centroid
  compute3DCentroid (cloud, xyz_centroid);

  // Compute the 3x3 covariance matrix
  computeCovarianceMatrix (cloud, xyz_centroid, covariance_matrix);

一般来说,因为没有数学方法来解决 正常,其方向通过主成分分析 (PCA) 计算为 上面显示是模棱两可的,并且在整个点上的方向不一致 云数据集。下图显示了这些对 表示厨房环境一部分的较大数据集。的右侧部分 该图表示扩展高斯图像 (EGI),也称为法线 球体,描述点云中所有法线的方向。 由于数据集是 2.5D 的,因此是从单个 观点,法线应该只存在于 EGI 的一半球体上。 但是,由于方向不一致,它们分布在 整个球体。

_images/unflipped_scene1.jpg _images/unflipped_scene2.jpg _images/unflipped_sphere.jpg

 

如果观点{\mathsf v}_p实际上是已知的,那么这个问题的解决方案是微不足道的。要使所有法线\vec{\boldsymbol{n}}_i始终朝向视点,它们需要满足以下等式:

\vec{\boldsymbol{n}}_i \cdot ({\mathsf v}_p - \boldsymbol{p}_i) > 0

下图显示了数据集中所有法线后的结果 上图始终以观点为导向。

_images/flipped_scene1.jpg _images/flipped_scene2.jpg _images/flipped_sphere.jpg

 

要在 PCL 中手动重新定向给定点法线,可以使用:

flipNormalTowardsViewpoint (const PointT &point, float vp_x, float vp_y, float vp_z, Eigen::Vector4f &normal);

注意

如果数据集有多个采集视点,则上述法态重新定向方法不成立,需要实现更复杂的算法。详情请见[鲁苏论文]。

选择正确的秤

如前所述,需要从以下公式估计某一点的表面法线 点的周围点邻域支持(也称为 K 邻域)。

最近邻估计问题的细节提出了一个问题: 正确的比例因子:给定采样点云数据集,什么是 正确的k(通过pcl::Feature::setKSearch给出)或r(通过pcl::Feature::setRadiusSearch给出)值,应该用于确定 一个点的最近邻集?

这个问题极其重要,是限制 点要素的自动估计(即,没有用户给定的阈值) 表示法。为了更好地说明这个问题,下图提供了 选择较小尺度(即小 R 或 K)与 较大的尺度(即较大的 R 或 K)。图的左侧部分描绘了 合理选择的比例因子,具有估计的表面法线 两个平面和小边的近似垂直 整个桌子都可见。但是,如果比例因子太大(右 部分),因此相邻点的集合是来自相邻的较大覆盖点 表面,估计的点要素制图表达会变形,其中 两个平面边缘处的旋转曲面法线,并涂抹 边缘和抑制的精细细节。

_images/normals_different_radii.jpg _images/curvature_different_radii.jpg

 

在不涉及太多细节的情况下,假设现在, 必须根据确定点邻域的比例进行选择 在应用程序所需的详细级别上。简单地说,如果 杯柄和圆柱形部分之间边缘的曲率为 重要的是,比例因子需要足够小才能捕获这些细节, 否则很大。

估计法线

虽然在特征中已经给出了一个正态估计的例子,但为了 更好地解释幕后发生的事情。

以下代码片段将估计所有 输入数据集中的点。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <pcl/point_types.h>
#include <pcl/features/normal_3d.h>

{
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);

  ... read, pass in or create a point cloud ...

  // Create the normal estimation class, and pass the input dataset to it
  pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
  ne.setInputCloud (cloud);

  // Create an empty kdtree representation, and pass it to the normal estimation object.
  // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
  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>);

  // Use all neighbors in a sphere of radius 3cm
  ne.setRadiusSearch (0.03);

  // Compute the features
  ne.compute (*cloud_normals);

  // cloud_normals->size () should have the same size as the input cloud->size ()*
}

来自 NormalEstimation 类的实际计算调用在内部不执行任何操作,但:

for each point p in cloud P

  1. get the nearest neighbors of p

  2. compute the surface normal n of p

  3. check if n is consistently oriented towards the viewpoint and flip otherwise

视点默认为 (0,0,0),可通过以下方式进行更改:

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

要计算单点法线,请使用:

computePointNormal (const pcl::PointCloud<PointInT> &cloud, const std::vector<int> &indices, Eigen::Vector4f &plane_parameters, float &curvature);

其中,云是包含点的输入点云,索引表示中的 k 最近邻的集合,plane_parameters 曲率表示正态估计的输出,plane_parameters在前 3 个坐标上保持法线(nx、ny、nz), 第四个坐标是 D = nc 。p_plane(这里的质心)+ p。输出表面曲率估计为协方差矩阵的特征值之间的关系(如上所示),如下所示:

 

\sigma = \frac{\lambda_0}{\lambda_0 + \lambda_1 + \lambda_2}

使用 OpenMP 加速正态估计

对于精通速度的用户,PCL 提供了表面的额外实现 使用 OpenMP 使用多核/多线程范式的正常估计 以加快计算速度。该类的名称是 pcl::NormalEstimationOMP,其 API 与 单线程 pcl::NormalEstimation,使其适合作为插入式 更换。在具有 100 个内核的系统上,您应该获得 8-6 之间的任何内容 计算时间快几倍。

注意

如果您的数据集是有组织的(例如,使用 TOF 相机、立体相机等获取 - 也就是说,它具有宽度和高度),为了获得更快的结果,请参阅使用积分图像的正态估计

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黄晓魚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值