表面法线是集合体表面一个十分重要的属性,对一个已知的几何体表面,根据垂直于点表面的矢量,推理出表面某一点的法线方向比较容易,然而由于我们获取的点云的数据集在真实的物体的表面表现为一组定点的样本,这样就会有两种解决方法:
(1)使用曲面重建技术,从获取的点云数据中得到采样点对应的曲面,然后从曲面模型中计算出表面法线
(2)直接从点云数据总近似推断表面法线:确定一点法线的问题近似于估计表面的一个相切面法线的问题,因 此转换过来就是求一个最小二乘法平面拟合的问题
(3)使用积分图进行法线估计:此方法只适用于有序点云
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 29 30 31 32
| #include <iostream> #include <pcl/io/io.h> #include <pcl/io/pcd_io.h> #include <pcl/features/integral_image_normal.h> #include <pcl/visualization/pcl_visualizer.h>
int main() { pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::io::loadPCDFile("table_scene_mug_stereo_textured.pcd",*cloud);
pcl::PointCloud<pcl::Normal>::Ptr normal(new pcl::PointCloud<pcl::Normal>); pcl::IntegralImageNormalEstimation<pcl::PointXYZ,pcl::Normal> ne; /********************************************************************************* * 三种法线估计方法: * COVARIANCE_MATRIX 从具体某个点的局部邻域的协方差矩阵创建9个积分,来计算这个点的法线 * AVERAGE_3D_GRADIENT 创建6个积分图像来计算水平方向和垂直方向的平滑后的三维梯度并使用两个梯度间的向量积计算法线 * AVERAGE_DEPTH_CHANGE 创建一个单一的积分图,评估深度变化计算法线 *********************************************************************************/ ne.setNormalEstimationMethod(ne.AVERAGE_3D_GRADIENT);//设置法线估计方法 ne.setMaxDepthChangeFactor(0.02f);//设置深度变化系数 ne.setNormalSmoothingSize(10.0f);//设置法线优化时考虑的邻域大小 ne.setInputCloud(cloud);//输入的点云 ne.compute(*normal);//计算法线
pcl::visualization::PCLVisualizer viewer; viewer.setBackgroundColor(0,0,0); viewer.addPointCloudNormals<pcl::PointXYZ,pcl::Normal>(cloud,normal); while (!viewer.wasStopped()){ viewer.spinOnce(); } return 0; }
|
法线输出结果可视化