PCL: Surface模块之Moving Least Squares(移动最小二乘法)

转自:https://blog.csdn.net/u012337034/article/details/37534869

参考文献:

           关于此类的详细信息和学术上的理论推导大家可以查看Marc Alexa的文章“Computing and Rendering Point Set Surfaces”。

用法小结:

       虽说此类放在了Surface下面,但是通过反复的研究与使用,我发现此类并不能输出拟合后的表面,不能生成Mesh或者Triangulations,只是将点云进行了MLS的映射,使得输出的点云更加平滑。

       因此,在我看来此类应该放在Filter下。通过多次的实验与数据的处理,我发现此类主要适用于点云的光顺处理,当然输入的点云最好是滤过离群点之后的点集,否则将会牺牲表面拟合精度的代价来获得输出点云。

详细分析:

参数输入输出:

       此类由基类CloudSurfaceProcessing派生,生成对象的方式也很简单,如下:

Pcl::MovingLeastSquares<PointInT, PointOutT> mls

       其中PointInT决 定了输入点云类型,PointOutT为点云输出类型(当法线估计标志位设置为true时,输出向量必须加上normals,这一点我们将会在成员函数里介绍)。

成员函数简介:

       这里我就不一一介绍所有的成员函数了,只是把常用的成员函数给列出来,并给出其的使用方法。

  1. inline void setComputeNormals(bool compute_normals)  我们都知道表面重构时需要估计点云的法向量,这里MLS提供了一种方法来估计点云法向量。(如果是true的话注意输出数据格式)。

  2. inline void setSearchMethod(const KdTreePtr&tree)  使用kdTree加速搜索

  3. inline void setPolynomialOrder(int order)  MLS拟合曲线的阶数,这个阶数在构造函数里默认是2,但是参考文献给出最好选择3或者4,当然不难得出随着阶数的增加程序运行的时间也增加。

  4. inline voidsetPolynomailFit(bool polynomial_fit)  对于法线的估计是有多项式还是仅仅依靠切线。

  5. inline void setSearchRadius(double radius)  确定搜索的半径。也就是说在这个半径里进行表面映射和曲面拟合。从实验结果可知:半径越小拟合后曲面的失真度越小,反之有可能出现过拟合的现象。

           这里是阶数为2,搜索半径为20的情况,可见奶粉罐侧面的凹陷已不见

    这里是阶数为4,搜索半径为8的情况,较真实的还原了实际

  6. inline void setUpsamplingMethod(UpsamplingMethodmethod)  这个函数比较特殊,他会调用不同的枚举变量, 每个枚举变量有对应的几个不同的函数,因此这里我将一一解释。经过试验证明:这个upsampling函数只能增加密度较小区域的密度对于holes的填补却无能为力(本来想着用之填补点云缺失的部分,却发现此函数并没有那么强大)。接下来将会一一介绍四个不同的方法。

    a)       NONE——将不会进行upsampling

    b)       SAMPLE_LOCAL_PLANE——这个方法就是参考论文中采用的方法,当然此方法所需的计算强度也相当庞大。若使用此方法,将需要调用两个函数:

    A.     Inline voidsetUpsamplingRadius(double radius) 此函数规定了点云增长的区域。可以这样理解:把整个点云按照此半径划分成若干个子点云,然后一一索引进行点云增长。

    B.     Inline voidsetUpsamlingStepSize(double size) 对于每个子点云处理时迭代的步长。

    c)       RANDOM_UNIFORM_DENSITY——也是使用上面子点云的原理,只不过它使得稀疏区域的密度增加,从而使得整个点云的密度均匀。它需要调用函数:inline void setPointDensity(int desired_num_po-ints_in_radius) 注意此函数输入整型变量,意为半径内点的个数。(这个半径应该是search的半径,不需要重新设置)。

    d)      VOXEL_GRID_DILATION——这个方法有两个步骤:首先将点云以voxels分割,然后进行迭代使得voxels的数目增加。它的结果是:填充空洞和平均化点云的密度。它需要调用的函数为:

    A.     Inline voidsetDilationVoxelSize(float voxel_size) 设定voxel的大小。

    B.     Inline voidsetDilationIterations(int iterations) 设置迭代的次数。

  7.  Void process(PointCloudOut&output) 此类的最后一个函数,将会输出处理后的点云。

  8. 当然还有其他的一些函数,我就不在这里一一进行介绍了,留给读者们自己开发吧。 :)

效果展示:

        我使用的PCL版本为1.6.0 all-in-one,IDE为vs2010。源码和源点云文件我已上传到CSDN(点此下载)。成功的把3000多点云数据Upsampling到了数万组。下面上效果图(明显比上述两幅图片更加密集)。对了我的邮箱为littletinygo@sina.com,希望与大家多多交流共同进步。

    





  • 3
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值