表面法线是几何体表面的重要属性,在很多领域都有大量应用,例如:在进行光照渲染时产生符合可视习惯的效果时需要表面法线信息才能正常进行,对于一个已知的几何体表面,根据垂直于点表面的矢量,因此推断表面某一点的法线方向通常比较简单。然而,由于我们获取的点云数据集在真实物体的表面表现为一组定点样本,这样就会有两种解决方法:
使用曲面重建技术,从获取的点云数据集中得到采样点对应的曲面,然后从曲面模型中计算表面法线;
直接从点云数据集中近似推断表面法线。
本文将针对后一种情况进行讲解,已知一个点云数据集,在其中的每个点处直接近似计算表面法线。
确定表面一点法线的问题近似于估计表面的一个相切面法线的问题,因此转换过来以后就变成一个最小二乘法平面拟合估计问题。
因此估计表面法线的解决方案就变成了分析一个协方差矩阵的特征矢量和特征值(或者PCA―主成分分析),这个协方差矩阵从查询点的近邻元素中创建。更具体地说,对于每一个点Pi,对应的协方差矩阵C,如下:
此处,k是点Pi邻近点的数目,
表示最近邻元素的三维质心,是协方差矩阵的第个特征值,是第j个特征向量。下面利用PCL库编写程序计算一平面上各点的法向量和曲率,在三维空间坐标系中,平面的一般方程是A*x + B*y + C*z + D = 0,该平面的法向量是(A, B, C), 曲率为0。下面我们针对平面方程x + y + z = 1,求出其法向量及曲率,具体代码如下:
#include <iostream> #include <pcl/point_types.h> #include <pcl/io/pcd_io.h> #include <pcl/search/kdtree.h> #include <pcl/features/normal_3d.h> int main(int argc, char* argv[]) { pcl::PointCloud<pcl::PointXYZ>::Ptr inCloud(new pcl::PointCloud<pcl::PointXYZ>); //construct a plane, the equation is x + y + z = 1 for (float x = -1.0; x <= 1.0; x += 0.005) { for (float y = -1.0; y <= 1.0; y += 0.005) { pcl::PointXYZ cloud; cloud.x = x; cloud.y = y; cloud.z = 1 - x - y; inCloud->push_back(cloud); } } pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne; pcl::PointCloud<pcl::Normal>::Ptr pcNormal(new pcl::PointCloud<pcl::Normal>); pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>); tree->setInputCloud(inCloud); ne.setInputCloud(inCloud); ne.setSearchMethod(tree); ne.setKSearch(50); //ne->setRadiusSearch (0.03); ne.compute(*pcNormal); pcl::PointCloud<pcl::PointXYZINormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointXYZINormal>); pcl::concatenateFields(*inCloud, *pcNormal, *cloud_with_normals); pcl::io::savePCDFile("plane_cloud_out.pcd", *cloud_with_normals); return 0; }
查看输出的plane_cloud_out.pcd文件内容为:
# .PCD v0.7 - Point Cloud Data file format VERSION 0.7 FIELDS x y z intensity normal_x normal_y normal_z curvature SIZE 4 4 4 4 4 4 4 4 TYPE F F F F F F F F COUNT 1 1 1 1 1 1 1 1 WIDTH 160801 HEIGHT 1 VIEWPOINT 0 0 0 1 0 0 0 POINTS 160801 DATA ascii -1 -1 3 0 -0.5790202 -0.57987827 -0.57312894 0.0013660738 -1 -0.995 2.9949999 0 -0.57917476 -0.58019817 -0.57264876 0.0012099775 -1 -0.99000001 2.99 0 -0.57867402 -0.58019888 -0.57315409 0.0013703115 -1 -0.98500001 2.9850001 0 -0.57548422 -0.57727969 -0.57928079 0 -1 -0.98000002 2.98 0 -0.57794726 -0.57705164 -0.57705146 0 -1 -0.97500002 2.9749999 0 -0.57838076 -0.57838166 -0.57528275 0.001083424 -1 -0.97000003 2.97 0 -0.57816029 -0.57827228 -0.57561421 0.0015886575 -1 -0.96500003 2.9650002 0 -0.57379341 -0.57841575 -0.57982439 0 -1 -0.96000004 2.96 0 -0.57350898 -0.57807595 -0.5804444 0 -1 -0.95500004 2.9549999 0 -0.57611471 -0.57911509 -0.57681662 0.00042304679 -1 -0.95000005 2.95 0 -0.5727694 -0.57773441 -0.58151358 0 -1 -0.94500005 2.9450002 0 -0.57519817 -0.57795346 -0.57889283 4.5525081e-005 -1 -0.94000006 2.9400001 0 -0.58162284 -0.57636297 -0.5740388 0.0012163053 -1 -0.93500006 2.9349999 0 -0.57649004 -0.57789612 -0.5776636 0.00061652815 -1 -0.93000007 2.9300001 0 -0.57858562 -0.57561904 -0.57784206 0.00059395749 -1 -0.92500007 2.9250002 0 -0.57974231 -0.57732123 -0.57497734 0.00094183162 -1 -0.92000008 2.9200001 0 -0.57631654 -0.57710737 -0.57862443 0 -1 -0.91500008 2.915 0 -0.58175957 -0.57761562 -0.57263952 0.0016304118 -1 -0.91000009 2.9100001 0 -0.57800007 -0.57729512 -0.57675499 0.00068382424 -1 -0.90500009 2.9050002 0 -0.57667315 -0.5772509 -0.57812595 0 -1 -0.9000001 2.9000001 0 -0.57496548 -0.57826763 -0.57881016 0 -1 -0.8950001 2.895 0 -0.57701188 -0.57737064 -0.57766801 0 -1 -0.8900001 2.8900001 0 -0.57927179 -0.57629073 -0.57648361 8.9984467e-005 -1 -0.88500011 2.8850002 0 -0.57844573 -0.57763427 -0.57596803 9.304475e-005 -1 -0.88000011 2.8800001 0 -0.57647377 -0.576976 -0.5785988 0 -1 -0.87500012 2.875 0 -0.57559562 -0.57702911 -0.57941955 0
可以看出一共输出160801个点的信息,这里只列举前面若干个,可以清晰的看出每个点的法向量与(1, 1, 1)共线,曲率为0或接近于0。
文章参考于点击打开链接
转:https://blog.csdn.net/lming_08/article/details/18360329
文章来源: 点云的曲面法向量估计(PCL)