精华内容
下载资源
问答
  • 计算平面一点的法线
    千次阅读
    2021-03-15 17:33:29

    曲线的切线与法平面

    曲线 Γ : { x = φ ( t ) y = ψ ( t )

    更多相关内容
  • PCL入门<三>平面法线

    千次阅读 2017-10-16 11:10:24
    介绍PCL法线的求法

    通常我们需要估计平面的方向,这就需要用到法线了,法线就是指垂直平面的线。

    PCL中有自动求出法线的方法,我们来看一看,

    首先假设我们有一个平面的点云cloud_xyz

    要求出法线首先我们先定义一个法线估计的对象ne

    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
    然后把要求的平面点云传给他

    ne. setInputCloud (cloud_xyz);
    这个方法求出cloud_xyz上每个点的法线方向,他是根据每个点附近的点云组成的平面求出的,所以我们需要设置一个半径,用来估计附近多大的范围取点来算平面,

    ne. setRadiusSearch ( 0.05);
    最后定义一个normal的对象来接受计算出来的法线

    pcl::PointCloud<pcl::Normal>:: Ptr cloud_normals ( new pcl::PointCloud<pcl::Normal>);
    计算并把结果保存在cloud_normals里

    ne. compute (*cloud_normals);
    这时算出来的法线就在这个对象里了,他里面的元素是和点云一一对应的,我们要访问每个点的法线方向,可以这样

    for( int ix= 0;ix<cloud_normals-> points. size();ix++)
    {
    if( isnan(cloud_normals-> points[ix]. normal_x)||
    isnan(cloud_normals-> points[ix]. normal_y)||
    isnan(cloud_normals-> points[ix]. normal_z))
    {
    continue;
    }
    }
    这里的isnan是判断法线是否为nan,因为如果一个点周围找不到足够的点计算平面,则法线中会赋值为nan,如果需要直接当作数字来用的同学们一定要注意这一点,使用我这种方法来判断。normal_x就是法线的x方向了,y z同理。然后PCL算出的法线是不知道正方向的,所以这点需要人为去判断正负。

    展开全文
  • PCL法线计算及原理

    千次阅读 2020-09-08 21:07:28
    法线估计类NormalEstimation的实际计算调用程序内部执行以下操作: 对点云P中的每个点p 1.得到p点的最近邻元素 2.计算p点的表面法线n 3.检查n的方向是否一致指向视点,如果不是则翻转 在PCL内估计一点集对应的协方差...

    这里写目录标题

    程序

    计算协方差矩阵:

    法线估计类NormalEstimation的实际计算调用程序内部执行以下操作:
    对点云P中的每个点p
    1.得到p点的最近邻元素
    2.计算p点的表面法线n
    3.检查n的方向是否一致指向视点,如果不是则翻转
    在PCL内估计一点集对应的协方差矩阵,可以使用以下函数调用实现:
    //定义每个表面小块的3x3协方差矩阵的存储对象
    Eigen::Matrix3fcovariance_matrix;
    //定义一个表面小块的质心坐标16-字节对齐存储对象
    Eigen::Vector4fxyz_centroid;
    //估计质心坐标
    compute3DCentroid(cloud,xyz_centroid);
    //计算3x3协方差矩阵
    computeCovarianceMatrix(cloud,xyz_centroid,covariance_matrix);
    

    注意,以下两种方法输入的点云数据都必须是XYZ格式,不能是XYZRGB

    第一种

    	// =====【2】计算法线========创建法线估计类======
    	pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
    	ne.setInputCloud(cloud_ptr);
    	// 添加搜索算法 kdtree search  最近的几个点 估计平面 协方差矩阵PCA分解 求解法线
    	pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
    	ne.setSearchMethod(tree);//设置近邻搜索算法 
    	// 输出点云 带有法线描述
    	pcl::PointCloud<pcl::Normal>::Ptr cloud_normals_ptr(new pcl::PointCloud<pcl::Normal>);
    	pcl::PointCloud<pcl::Normal>& cloud_normals = *cloud_normals_ptr;
    	// Use all neighbors in a sphere of radius 3cm
    	ne.setRadiusSearch(0.03);//半价内搜索临近点 3cm
    	// 计算表面法线特征
    	ne.compute(cloud_normals);
    

    第二种

    	pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>);
    	pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);//存储估计的法线
    	pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n;//法线估计对象
    	pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);//定义kd树指针
    	tree->setInputCloud(cloud);                        //用cloud构建tree对象
    	n.setInputCloud(cloud);                            //为法线估计对象设置输入点云
    	n.setSearchMethod(tree);                          //设置搜索方法
    	n.setKSearch(10);                                 //设置k搜索的k值为20
    	//n.setRadiusSearch(0.005);
    	n.compute(*normals);                              //估计法线存储结果到normals中
    	std::cerr << "法线计算   完成" << std::endl;
    	//由于XYZ坐标字段和法线字段需要在相同PointCloud对象中,
    	//所以创建一个新的PointNormal类型的点云来存储坐标字段和法线连接后的点云。
    	pcl::concatenateFields(*cloud, *normals, *cloud_with_normals);//连接字段,cloud_with_normals存储有向点云
    
    

    原理

    这篇是我看到的最全讲的最好的感觉,把我零零散散学的都串起来啦,终于知道为什么了!
    PCL:从法线计算到曲率计算并可视化

    ----------------法线求解原理--------------

    表面法线是几何体表面的重要属性,在很多领域都有大量应用,例如:在进行光照渲染时产生符合可视习惯的效果时需要表面法线信息才能正常进行,对于一个已知的几何体表面,根据垂直于点表面的矢量,因此推断表面某一点的法线方向通常比较简单。然而,由于我们获取的点云数据集在真实物体的表面表现为一组定点样本,这样就会有两种解决方法:

    (1)使用曲面重建技术,从获取的点云数据集中得到采样点对应的曲面,然后从曲面模型中计算表面法线;曲面方程f(x,y,z)=0的一个法向量可以表示为n={e(df/dx), e(df/dy), e(df/dz)}.)

    (2)直接从点云数据集中近似推断表面法线。

    下面以已知一个点云数据集,在其中的每个点处直接近似计算表面法线。为例进行展开:

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

    最小二乘法(又称最小平方法)是一种数学优化技术。它通过最小化误差的平方和寻找数据的最佳函数匹配。利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误差的平方和为最小。最小二乘法还可用于曲线拟合。其他一些优化问题也可通过最小化能量或最大化熵用最小二乘法来表达。

    对空间中的一系列散点,寻求一个近似平面:(按最小原则选择的拟合平面为最小二乘拟合平面)

    上述使用最小二乘我们已经可以根据某点的临近点阈,可以拟合出一个平面。接下来就是求平面的法线。表面法线是几何体面的重要属性。而点云数据集在真实物体的表面表现为一组定点样本。对点云数据集的每个点的法线估计,可以看作是对表面法线的近似推断。在PCL库中有专门针对法向量计算的库,但是必须了解计算原理才能记得更加深刻。

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

    下一张图说明怎么是由求法线转换到求最小特征值对应的特征向量就是代表法线。

    类似于上图中的平面方程求解,只是换了一种平面表示方法。(由一般式转换为法线式方程)

      

    由上述推导过程可知,求法线就是求最小特征值对应的特征向量。

    ----

    还可以观察上述右边图片中的A矩阵其实是个协方差矩阵;

    在PCL内估计一点集对应的协方差矩阵,可以使用以下函数调用实现:

    
     
    1. //定义每个表面小块的3x3协方差矩阵的存储对象
    2. Eigen::Matrix3fcovariance_matrix;
    3. //定义一个表面小块的质心坐标16-字节对齐存储对象
    4. Eigen::Vector4fxyz_centroid;
    5. //估计质心坐标
    6. compute3DCentroid(cloud,xyz_centroid);
    7. //计算3x3协方差矩阵
    8. computeCovarianceMatrix(cloud,xyz_centroid,covariance_matrix);

    通常,没有数学方法能解决法线的正负向问题,如上所示,通过主成分分析法(PCA)来计算它的方向也具有二义性,无法对整个点云数据集的法线方向进行一致性定向。图1显示出对一个更大数据集的两部分产生的影响,此数据集来自于厨房环境的一部分,很明显估计的法线方向并非完全一致,图2展现了其对应扩展的高斯图像(EGI),也称为法线球体(normal sphere),它描述了点云中所有法线的方向。由于数据集是2.5维,其只从一个单一的视角获得,因此法线应该仅呈现出一半球体的扩展高斯图像(EGI)。然而,由于定向的不一致性,它们遍布整个球体,如图2所示。

    如果实际知道视点V_{p},那么这个问题的解决是非常简单的。对所有\vec{n}法线定向只需要使它们一致朝向视点方向,满足下面的方程式:

                                                 \vec{n}\cdot (V_{p}-V_{i})>0

    下面的图3展现了上面图1中的数据集的所有法线被一致定向到视点后的结果演示。

    在PCL中对一个已知点的法线进行手动重新定向,你可以使用:

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

    注意:如果数据集是从多个捕获视点中配准后集成的,那么上述法线的一致性定向方法就不适用了。需要使用更复杂的算法。更详细的信息见:http://pointclouds.org/documentation/tutorials/how_features_work.php#id1

    选择合适的尺度

    如之前介绍的,在估计一个点的表面法线时,我们需要从周围支持这个点的邻近点着手(也称作k邻域)。最近邻估计问题的具体内容又提出了另一个问题“合适的尺度”:已知一个取样点云数据集,k的正确取值是多少(k通过pcl::Feature::setKSearch给出)或者确定一个点r为半径的圆内的最近邻元素集时使用的半径r应该取什么值(r通过pcl::Feature::setRadiusSearch给出)。这个问题非常重要,并且在一个点特征算子的自动估计时(例如:用户没有给定阈值)是一个限制因素。为了更好地说明这个问题,以下图示表现了选择更小尺度(如:r值或k取相对小)与选择更大尺度(如:r值或k值比较大)时的两种不同效果。图4和图5分别为近视图和远视图,两图中左边部分展示选择了一个合理的比例因子,估计的表面法线近似垂直于两个平面,即使在互相垂直的边沿部分,可明显看到边沿。如果这个尺度取的太大(右边部分),这样邻近点集将更大范围地覆盖邻近表面的点,估计的点特征表现就会扭曲失真,在两个平面边缘处出现旋转表面法线,以及模糊不清的边界,这样就隐藏了一些细节信息。

    无法深入探究更多讨论,现在可粗略假设,以应用程序所需的细节需求为参考,选择确定点的邻域所用的尺度。简言之,如果杯子手柄和圆柱体部分之间边缘的曲率是重要的,那么需要足够小的尺度来捕获这些细节信息,而在其他不需要细节信息的应用中可选择大的尺度。

    估计法线实例详解:http://pointclouds.org/documentation/tutorials/index.php#features-tutorial

    法线估计类NormalEstimation的实际计算调用程序内部执行以下操作:

    
     
    1. 对点云P中的每个点p
    2. 1 .得到p点的最近邻元素
    3. 2 .计算p点的表面法线n
    4. 3 .检查n的方向是否一致指向视点,如果不是则翻转

    视点坐标默认为(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);
     

    此处,cloud是包含点的输入点云,indices是点的k-最近邻元素集索引,plane_parameters和curvature是法线估计的输出,plane_parameters前三个坐标中,以(nx, ny, nz)来表示法线,第四个坐标D = nc . p_plane (centroid here) + p。输出表面曲率curvature通过协方差矩阵的特征值之间的运算估计得到,如:

                                        \sigma =\frac{\lambda _{0}}{\lambda _{0}+\lambda _{1}+\lambda _{2}}

    使用OpenMP加速法线估计

    对于对运算速度有要求的用户,PCL点云库提供了一个表面法线的附加实现程序,它使用多核/多线程开发规范,利用OpenMP来提高计算速度。它的类命名为pcl::NormaleEstimationOMP,并且它的应用程序接口(API)100%兼容单线程pcl::NormalEstimation,这使它适合作为一个可选提速方法。在8核系统中,可以轻松提速6-8倍。

    -------------------曲率求解-----------------

    曲率大小反映模型表面的凹凸程度。

    利用上面法向量估计的PCA方法,在法向量估算的基础上进行数据点的曲率估算,曲率的估算方法如上式:

    \lambda _{0}入描述了曲面沿法向量的变化,而\lambda _{1}\lambda _{2}表示数据点在切平面上的分布情况。定义下式为数据点g _{i},在k邻域内的曲面变分。

                                                \sigma =\frac{\lambda _{0}}{\lambda _{0}+\lambda _{1}+\lambda _{2}}

    点云模型在数据点的曲率H_{i}可近似为在该点的曲面变分\sigma,即H_{i}\approx\sigma

    该式的基本思想实际上是使用曲面变分来近似曲率信息[1]。

    曲率基础知识:
    平均曲率、主曲率和高斯曲率是曲率的三个基本要素。
    法曲率:曲面在一点沿着不同方向的弯曲程度不同。或者说曲面离开切平面的速度不同。这个弯曲属性可以用这一点的沿着这个方法的法曲率刻画
    主曲率:过曲面上某个点上具有无穷个正交曲率,其中存在一条曲线使得该曲线的曲率为极大,这个曲率为极大值Kmax,垂直于极大曲率面的曲率为极小值Kmin。这两个曲率属性为主曲率。他们代表着法曲率的极值。
    平均曲率:是空间上曲面上某一点任意两个相互垂直的正交曲率的平均值。如果一组相互垂直的正交曲率可表示为K1,K2,那么平均曲率则为:K = (K1 +K2 ) / 2。
    高斯曲率:两个主曲率的乘积即为高斯曲率,又称总曲率,反映某点上总的完全程度。

    
     
    1. #include <iostream>
    2. #include <vector>
    3. #include <pcl/io/pcd_io.h>
    4. #include <pcl/point_types.h>
    5. #include <pcl/features/normal_3d.h>
    6. #include <pcl/features/principal_curvatures.h>
    7. using namespace std;
    8. int main (int argc, char** argv){
    9. pcl::PointCloud<pcl::PointXYZ>:: Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
    10. pcl::io::loadPCDFile<pcl::PointXYZ>( "A3 - Cloud.pcd", *cloud); //读取点云
    11. cout << "Loaded " << cloud->points.size() << " points." << std:: endl; //显示读取点云的点数
    12. // 计算点云的法线
    13. pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normalEstimation;
    14. normalEstimation.setInputCloud (cloud);
    15. //设置邻域点搜索方式
    16. pcl::search::KdTree<pcl::PointXYZ>:: Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
    17. normalEstimation.setSearchMethod (tree);
    18. //定义一个新的点云储存含有法线的值
    19. pcl::PointCloud<pcl::Normal>:: Ptr cloudWithNormals (new pcl::PointCloud<pcl::Normal>);
    20. //设置KD树搜索半径
    21. // normalEstimation.setRadiusSearch (0.03);
    22. normalEstimation.setKSearch( 10);
    23. //计算出来法线的值
    24. normalEstimation.compute (*cloudWithNormals);
    25. // 建立主曲率计算
    26. pcl::PrincipalCurvaturesEstimation<pcl::PointXYZ, pcl::Normal, pcl::PrincipalCurvatures> principalCurvaturesEstimation;
    27. // 提供原始点云(没有法线)
    28. principalCurvaturesEstimation.setInputCloud (cloud);
    29. // 为点云提供法线
    30. principalCurvaturesEstimation.setInputNormals(cloudWithNormals);
    31. // 使用与法线估算相同的KdTree
    32. principalCurvaturesEstimation.setSearchMethod (tree);
    33. //principalCurvaturesEstimation.setRadiusSearch(1.0);
    34. principalCurvaturesEstimation.setKSearch( 10);
    35. // 计算主曲率
    36. pcl::PointCloud<pcl::PrincipalCurvatures>:: Ptr principalCurvatures (new pcl::PointCloud<pcl::PrincipalCurvatures> ());
    37. principalCurvaturesEstimation.compute (*principalCurvatures);
    38. std:: cout << "output points.size: " << principalCurvatures->points.size () << std:: endl;
    39. // 显示和检索第0点的主曲率。
    40. cout << "最大曲率;"<< principalCurvatures->points[ 0].pc1 << endl; //输出最大曲率
    41. cout << "最小曲率:"<< principalCurvatures->points[ 0].pc2 << endl; //输出最小曲率
    42. //输出主曲率方向(最大特征值对应的特征向量)
    43. cout << "主曲率方向;" << endl;
    44. cout << principalCurvatures->points[ 0].principal_curvature_x << endl;
    45. cout << principalCurvatures->points[ 0].principal_curvature_y << endl;
    46. cout << principalCurvatures->points[ 0].principal_curvature_z << endl;
    47. return 0;
    48. }

    [1]
     

    展开全文
  • PCL:从法线计算到曲率计算并可视化

    千次阅读 多人点赞 2020-04-28 16:53:43
    在很多领域都有大量应用,例如:在进行光照渲染时产生符合可视习惯的效果时需要表面法线信息才能正常进行,对于一个已知的几何体表面,根据垂直于点表面的矢量,因此推断表面某一点法线方向通常比较简单。...

    ----------------法线求解原理--------------

    表面法线是几何体表面的重要属性,在很多领域都有大量应用,例如:在进行光照渲染时产生符合可视习惯的效果时需要表面法线信息才能正常进行,对于一个已知的几何体表面,根据垂直于点表面的矢量,因此推断表面某一点的法线方向通常比较简单。然而,由于我们获取的点云数据集在真实物体的表面表现为一组定点样本,这样就会有两种解决方法:

    (1)使用曲面重建技术,从获取的点云数据集中得到采样点对应的曲面,然后从曲面模型中计算表面法线;曲面方程f(x,y,z)=0的一个法向量可以表示为n={e(df/dx), e(df/dy), e(df/dz)}.)

    (2)直接从点云数据集中近似推断表面法线。

    下面以已知一个点云数据集,在其中的每个点处直接近似计算表面法线。为例进行展开:

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

    最小二乘法(又称最小平方法)是一种数学优化技术。它通过最小化误差的平方和寻找数据的最佳函数匹配。利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误差的平方和为最小。最小二乘法还可用于曲线拟合。其他一些优化问题也可通过最小化能量或最大化熵用最小二乘法来表达。

    对空间中的一系列散点,寻求一个近似平面:(按最小原则选择的拟合平面为最小二乘拟合平面)

    上述使用最小二乘我们已经可以根据某点的临近点阈,可以拟合出一个平面。接下来就是求平面的法线。表面法线是几何体面的重要属性。而点云数据集在真实物体的表面表现为一组定点样本。对点云数据集的每个点的法线估计,可以看作是对表面法线的近似推断。在PCL库中有专门针对法向量计算的库,但是必须了解计算原理才能记得更加深刻。

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

    下一张图说明怎么是由求法线转换到求最小特征值对应的特征向量就是代表法线。

    类似于上图中的平面方程求解,只是换了一种平面表示方法。(由一般式转换为法线式方程)

      

    由上述推导过程可知,求法线就是求最小特征值对应的特征向量。

    ----

    还可以观察上述右边图片中的A矩阵其实是个协方差矩阵;

    在PCL内估计一点集对应的协方差矩阵,可以使用以下函数调用实现:

    //定义每个表面小块的3x3协方差矩阵的存储对象
    Eigen::Matrix3fcovariance_matrix;
    //定义一个表面小块的质心坐标16-字节对齐存储对象
    Eigen::Vector4fxyz_centroid;
    //估计质心坐标
    compute3DCentroid(cloud,xyz_centroid);
    //计算3x3协方差矩阵
    computeCovarianceMatrix(cloud,xyz_centroid,covariance_matrix);

    通常,没有数学方法能解决法线的正负向问题,如上所示,通过主成分分析法(PCA)来计算它的方向也具有二义性,无法对整个点云数据集的法线方向进行一致性定向。图1显示出对一个更大数据集的两部分产生的影响,此数据集来自于厨房环境的一部分,很明显估计的法线方向并非完全一致,图2展现了其对应扩展的高斯图像(EGI),也称为法线球体(normal sphere),它描述了点云中所有法线的方向。由于数据集是2.5维,其只从一个单一的视角获得,因此法线应该仅呈现出一半球体的扩展高斯图像(EGI)。然而,由于定向的不一致性,它们遍布整个球体,如图2所示。

    如果实际知道视点V_{p},那么这个问题的解决是非常简单的。对所有\vec{n}法线定向只需要使它们一致朝向视点方向,满足下面的方程式:

                                                 \vec{n}\cdot (V_{p}-V_{i})>0

    下面的图3展现了上面图1中的数据集的所有法线被一致定向到视点后的结果演示。

    在PCL中对一个已知点的法线进行手动重新定向,你可以使用:

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

    注意:如果数据集是从多个捕获视点中配准后集成的,那么上述法线的一致性定向方法就不适用了。需要使用更复杂的算法。更详细的信息见:http://pointclouds.org/documentation/tutorials/how_features_work.php#id1

    选择合适的尺度

    如之前介绍的,在估计一个点的表面法线时,我们需要从周围支持这个点的邻近点着手(也称作k邻域)。最近邻估计问题的具体内容又提出了另一个问题“合适的尺度”:已知一个取样点云数据集,k的正确取值是多少(k通过pcl::Feature::setKSearch给出)或者确定一个点r为半径的圆内的最近邻元素集时使用的半径r应该取什么值(r通过pcl::Feature::setRadiusSearch给出)。这个问题非常重要,并且在一个点特征算子的自动估计时(例如:用户没有给定阈值)是一个限制因素。为了更好地说明这个问题,以下图示表现了选择更小尺度(如:r值或k取相对小)与选择更大尺度(如:r值或k值比较大)时的两种不同效果。图4和图5分别为近视图和远视图,两图中左边部分展示选择了一个合理的比例因子,估计的表面法线近似垂直于两个平面,即使在互相垂直的边沿部分,可明显看到边沿。如果这个尺度取的太大(右边部分),这样邻近点集将更大范围地覆盖邻近表面的点,估计的点特征表现就会扭曲失真,在两个平面边缘处出现旋转表面法线,以及模糊不清的边界,这样就隐藏了一些细节信息。

    无法深入探究更多讨论,现在可粗略假设,以应用程序所需的细节需求为参考,选择确定点的邻域所用的尺度。简言之,如果杯子手柄和圆柱体部分之间边缘的曲率是重要的,那么需要足够小的尺度来捕获这些细节信息,而在其他不需要细节信息的应用中可选择大的尺度。

    估计法线实例详解:http://pointclouds.org/documentation/tutorials/index.php#features-tutorial

    法线估计类NormalEstimation的实际计算调用程序内部执行以下操作:

    对点云P中的每个点p
      1.得到p点的最近邻元素
      2.计算p点的表面法线n
      3.检查n的方向是否一致指向视点,如果不是则翻转

    视点坐标默认为(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);

    此处,cloud是包含点的输入点云,indices是点的k-最近邻元素集索引,plane_parameters和curvature是法线估计的输出,plane_parameters前三个坐标中,以(nx, ny, nz)来表示法线,第四个坐标D = nc . p_plane (centroid here) + p。输出表面曲率curvature通过协方差矩阵的特征值之间的运算估计得到,如:

                                        \sigma =\frac{\lambda _{0}}{\lambda _{0}+\lambda _{1}+\lambda _{2}}

    使用OpenMP加速法线估计

    对于对运算速度有要求的用户,PCL点云库提供了一个表面法线的附加实现程序,它使用多核/多线程开发规范,利用OpenMP来提高计算速度。它的类命名为pcl::NormaleEstimationOMP,并且它的应用程序接口(API)100%兼容单线程pcl::NormalEstimation,这使它适合作为一个可选提速方法。在8核系统中,可以轻松提速6-8倍。

    -------------------曲率求解-----------------

    曲率大小反映模型表面的凹凸程度。

    利用上面法向量估计的PCA方法,在法向量估算的基础上进行数据点的曲率估算,曲率的估算方法如上式:

    \lambda _{0}入描述了曲面沿法向量的变化,而\lambda _{1}\lambda _{2}表示数据点在切平面上的分布情况。定义下式为数据点g _{i},在k邻域内的曲面变分。

                                                \sigma =\frac{\lambda _{0}}{\lambda _{0}+\lambda _{1}+\lambda _{2}}

    点云模型在数据点的曲率H_{i}可近似为在该点的曲面变分\sigma,即H_{i}\approx\sigma

    该式的基本思想实际上是使用曲面变分来近似曲率信息[1]。

    曲率基础知识:
    平均曲率、主曲率和高斯曲率是曲率的三个基本要素。
    法曲率:曲面在一点沿着不同方向的弯曲程度不同。或者说曲面离开切平面的速度不同。这个弯曲属性可以用这一点的沿着这个方法的法曲率刻画
    主曲率:过曲面上某个点上具有无穷个正交曲率,其中存在一条曲线使得该曲线的曲率为极大,这个曲率为极大值Kmax,垂直于极大曲率面的曲率为极小值Kmin。这两个曲率属性为主曲率。他们代表着法曲率的极值。
    平均曲率:是空间上曲面上某一点任意两个相互垂直的正交曲率的平均值。如果一组相互垂直的正交曲率可表示为K1,K2,那么平均曲率则为:K = (K1 +K2 ) / 2。
    高斯曲率:两个主曲率的乘积即为高斯曲率,又称总曲率,反映某点上总的完全程度。

    #include <iostream>
    #include <vector>
    #include <pcl/io/pcd_io.h>
    #include <pcl/point_types.h>
    #include <pcl/features/normal_3d.h>
    #include <pcl/features/principal_curvatures.h>
    using namespace std;
    
    int main (int argc, char** argv){
    
      pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
      pcl::io::loadPCDFile<pcl::PointXYZ>("A3  - Cloud.pcd", *cloud); //读取点云
      cout << "Loaded " << cloud->points.size() << " points." << std::endl;//显示读取点云的点数
      // 计算点云的法线
      pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normalEstimation;
      normalEstimation.setInputCloud (cloud);
      //设置邻域点搜索方式
      pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
      normalEstimation.setSearchMethod (tree);
      //定义一个新的点云储存含有法线的值
      pcl::PointCloud<pcl::Normal>::Ptr cloudWithNormals (new pcl::PointCloud<pcl::Normal>);
      //设置KD树搜索半径
     // normalEstimation.setRadiusSearch (0.03);
      normalEstimation.setKSearch(10);
      //计算出来法线的值
      normalEstimation.compute (*cloudWithNormals);
      // 建立主曲率计算
      pcl::PrincipalCurvaturesEstimation<pcl::PointXYZ, pcl::Normal, pcl::PrincipalCurvatures> principalCurvaturesEstimation;
      // 提供原始点云(没有法线)
      principalCurvaturesEstimation.setInputCloud (cloud);
      // 为点云提供法线
      principalCurvaturesEstimation.setInputNormals(cloudWithNormals);
      // 使用与法线估算相同的KdTree
      principalCurvaturesEstimation.setSearchMethod (tree);
      //principalCurvaturesEstimation.setRadiusSearch(1.0);
      principalCurvaturesEstimation.setKSearch(10);
      // 计算主曲率
      pcl::PointCloud<pcl::PrincipalCurvatures>::Ptr principalCurvatures (new pcl::PointCloud<pcl::PrincipalCurvatures> ());
      principalCurvaturesEstimation.compute (*principalCurvatures);
      std::cout << "output points.size: " << principalCurvatures->points.size () << std::endl;
      // 显示和检索第0点的主曲率。
      cout << "最大曲率;"<< principalCurvatures->points[0].pc1 << endl;//输出最大曲率
      cout << "最小曲率:"<< principalCurvatures->points[0].pc2 << endl;//输出最小曲率
      //输出主曲率方向(最大特征值对应的特征向量)
      cout << "主曲率方向;" << endl;
      cout << principalCurvatures->points[0].principal_curvature_x << endl;
      cout << principalCurvatures->points[0].principal_curvature_y << endl;
      cout << principalCurvatures->points[0].principal_curvature_z << endl;
    
      return 0;
    }
    

    [1]
     

    展开全文
  • 点云法线

    千次阅读 2019-10-20 06:57:29
    对于一个三维空间的正则曲面R(u, v), 点(u, v)处的切平面(Ru, Rv)的法向量即为曲面在点(u, v)的法向量。点云是曲面的一个点采样,采样曲面的法向量就是点云的法向量。 我们给每个点一个线段来显示法线,线段的方向...
  • 在很多领域都有大量应用,例如:在进行光照渲染时产生符合可视习惯的效果时需要表面法线信息才能正常进行,对于一个已知的几何体表面,根据垂直于点表面的矢量,因此推断表面某一点法线方向通常比较简单。...
  • 法线法线贴图

    2021-06-30 12:48:09
    法线法线贴图 法线法线贴图是否作为单独的章节讲解,我是有过犹豫的。其实这部分的内容并没有那么多,也不至于说涉及到非常牛逼的图形学原理。但是,最终我还是决定把这部分列为一个单章,主要理由有两点: 1...
  • OpenGL.Shader:9-学习光照-法线贴图(计算TBN矩阵) 这次文章学习法线贴图,法线贴图在游戏开发和GIS系统开发当中尤为广泛,其表现力特别的强,绘制的效果特别接近真实。更重要的一点就是,我们可以用很少的代价就...
  • 东北天的坐标向量证明 东北天又叫站心切平面坐标系。下图P点的法线为Z轴,指向天顶为正。以子午线方向为X轴,指向北为正。Y轴与x,z轴垂直,构成左手坐标系。如下图所示: 我们想计算X轴,Y轴,Z轴的单位向量。这里...
  • 估计一个点云的表面法线

    千次阅读 2016-08-26 16:59:44
    在很多领域都有大量应用,例如:在进行光照渲染时产生符合可视习惯的效果时需要表面法线信息才能正常进行,对于一个已知的几何体表面,根据垂直于点表面的矢量,因此推断表面某一点法线方向通常比较简单。...
  • openGL系列文章目录 前言 我们在openGL中绘制球体,或者圆环体的时候,经常可以到法线、切线、副切线这几个词,一脸疑惑,特别是副切线,这时什么鬼? 一、法线(normal) ...三维平面法线是垂直于该平面的三维
  • 目录 1、切线 ...切线是数学中以直代曲的思想的重要体现,我们在求解曲线f(x)的方程、与坐标轴围成的面积等等的计算中,往往很多时候难以求出来,并且直接将曲线f(x)与直线g(x)相等是不对的,也
  • 目标:讨论法线贴图的意义,讨论切线空间的意义,推导切线空间的计算公式,根据公式编写代码,将其计算结果与其他美术软件计算的结果进行比较以验证公式的正确性。
  • 法线是描述多边形面向的方向的单位矢量(即,它与多边形上的所有点正交);...对于光照计算,我们需要在三角形网格表面上求每个点的曲面法线,以便我们可以确定光线照射到网格曲面上的点的角度。 为了...
  • 前言法线可以用来计算光照,废话少说进正题吧。正文为了理解接下来的内容,我们需要先看看点乘的计算两个向量的点乘结果表示这两个向量有多相像。下图显示如果两个向量一模一样,则点乘结果为1,相反则为-1,而两个...
  • 2018-01-18 创建人:Ruo_Xiao 邮箱:xclsoftware@163.com 法向量N: 点P: 平面方程:
  • 自动计算顶点缓冲中所有顶点的法线 2010-02-26 15:38:42| 分类: 游戏程序制作|举报|字号 订阅问题当绘制自定义的结构时,你会发现光照不正确。这是因为你没有指定正确的法线向量,显卡要求每个顶点都有法线信息,...
  • 点击上方“3D视觉工坊”,选择“星标”干货第一时间送达曲面法线是几何表面的重要属性,并且在诸如计算机图形应用的许多领域中被大量使用,应用在矫正光源产生的阴影和其他的视觉效果。给定几何表面...
  • 2.7-点云表面法线估算

    2021-04-13 16:10:26
    返回 >>>>>> PCL-3D点云总目录 ...使用表面网格化技术从获取的点云数据集中获取基础表面,然后从网格中计算表面法线; 使用近似值直接从点云数据集中推断表面法线。 我们将使用后者,
  • 法线估计

    千次阅读 2018-04-18 23:06:52
    在很多领域都有大量应用,例如:在进行光照渲染时产生符合可视习惯的效果时需要表面法线信息才能正常进行,对于一个已知的几何体表面,根据垂直于点表面的矢量,因此推断表面某一点法线方向通常比较简单。...
  • 利用两平面的法向量做”叉乘“运算获得两平面交线的方向向量。
  • 法线贴图

    千次阅读 2018-08-08 11:19:58
    1.1.1 手动计算切线向量和双切线向量 1.2 着色器中的法线贴图 1.2.1 使用TBN矩阵将向量从切线空间变换到世界空间 1.2.2 使用TBN矩阵的逆将向量从世界空间变换到切线空间 1.3 提升效果的技巧 — 切空间平滑 1.4 ...
  • unreal 顶点法线与 面法线

    千次阅读 2018-06-23 15:45:14
    当前revit 建筑模型软件导出的模型对象 three.js的json文件,都是面法线。(暂时是这样的,是否能导出顶点法线,后续确定)。 unreal 显示总是发现不对,要么该光照的没关照,或者直角面,背光处却透光了。开始未...
  • 表面点云法线

    2022-04-21 10:36:38
    尽管有许多不同的法线估计方法,我们先了解其中最简单也是最常见的一个,确定表面一点法线的问题近似于估计表面的一个相切面法线的问题,因此转换过来以后就变成一个最小二乘法平面拟合估计问题
  • 求曲面一点s的法线时,通过曲面附近的点拟合一个平面,然后求拟合平面s点的法线。(假设:曲面连续变化) 这里涉及的重要知识点是:哪些可以定义为附近点? 英文文献中指明了几种方法,这里不赘述,只需要知道有...
  • 点到点法式平面投影点的计算

    千次阅读 2017-11-03 14:21:20
    算法概述平面一点O(x0,y0,z0)O(x_0,y_0,z_0)和法向量n→=(n1,n2,n3)\overrightarrow{n}=(n_1,n_2,n_3)定义,平面一点为Pout(xp,yp,zp)P_{out}(x_p,y_p,z_p),求PP到平面的投影点Q的坐标设点Q的坐标为(xQ,yQ,...
  • 目标:赋予材质法线贴图,并能响应光照的变化,体现出凹凸感。场景中只有一个主平行光找了一张法线贴图(网上荡的)在unity里...没有凹凸可言,平面就是平面那就要编个shader来实现这张法线贴图的价值了Shader "Custo...
  • 目的:网格法向量的计算 最近发现一个非常有意思的东西,网上的资料较少,所以记下来供大家查阅, 就是在网格化三维polygon 3d的时候,对于polygon 3d的法向量和网格化为三角形的时候。生成obj文件的时候三角面片的...
  • OpenGL法线贴图Normal Mapping法线贴图Normal Mapping简介法线贴图切线空间手工计算切线和副切线切线空间法线贴图复杂物体最后一件事 法线贴图Normal Mapping简介 我们的场景中已经充满了多边形物体,其中每个都可能...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,931
精华内容 1,972
关键字:

计算平面一点的法线