点云表面法向量的估计
点云表面法向量是一种重要几何表面特性,在计算机图像学中有很广的应用,例如在进行光照渲染和其他可视化效果时确定一个合理的光源位置。
通过已知的确定几何表面来估计表面法向量通常并没有什么难度。但通过一组实际获取的真实表面点云数据来进行相应的法向量估计,通常有两种方案:
1. 使用表面重建技术,针对获取的点运数据集,从网格化后的重建表面上估计法向量。
2. 直接从点云数据中估计法向量。
直接从点云数据中获取法向量的方法下文中将给出相应的介绍。
理论基础
尽管有许多关于点云法向量估计的方法,我们主要集中讲解最简单的一个,其原理如下。表面上一点处的法向量的估计问题近似于估计与此表面相切的一个平面的法向量问题,于是该问题转换为最小二乘法拟合估计问题。
注:更多为细节在Rusu先生的<Semantic 3D Object Maps for Everyday Manipulation in Human Living Environments>,这本书三分之一的部分讲的是三维数据早期的一些处理,其余三分之二是实际机器人在场景语义识别时的应用。
通过最小二乘法思想求解一点处的法向量问题实际上转化为了一个求解一个协方差矩阵的的特征值和特征向量的过程(也可以成为PCA主成分分析法)。
其中a,b,c就是该预求解的平面的法向量,法向量n=(a,b,c)。由空间解析几何的知识,法向量对应的的为最小特征值所对应的值。
以上只是纯粹的一些数学理论推导,在PCL中通过调用相关的的函数实现。
PCL中函数实现
// 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);
但是向量的求解一般存在方向问题,通过时上述的方法获取的法向量也存在方向不一致的情况,针对这一问题,通常有两种解决方案。
1. 已知视点的情况下,法向量需满足以下方程。
2. 不知道视点的情况下,需满足一下方程。
选择一个合适的尺度:上述的法向量估计实际上对是以点集中某点为查询点所确定的k近邻或r邻域所进行的估计,k或r的选取对法向量和曲率的估计十分重要,一般情况下,如果对某特征的细节要求很高,k或r应该取小尺度,反之亦然。
法向量估计代码
#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->points.size () should have the same size as the input cloud->points.size ()*
}
算法流程如下:
对点云P中的每个点p:
(1) 得到p点的最近邻或由半径r确定一个邻域;
(2) 计算p点的法向量;
(3) 检查法向量的一致性,不一致翻转。
使用OpenMP加速
实际应用中若对计算速度有要求,可以使用PCL提供的附加实现程序,多线程开发。类命名为pcl::NormaleEstimationOMP来实现。
目前微信交流群不断壮大,由于人数太多,目前有两个群,为了鼓励大家分享,我们希望大家能在学习的同时积极分享,将您的问题或者小总结投稿发到群主邮箱主邮箱dianyunpcl@163.com。
作者:翻译组点云小白