如何提取出MeshLab中计算法线的功能---详细过程记录

一、概述

最近复现了几个点云相关的算法,复现完成后进行测试。由于算法的输入要求点云具有法线,所以一开始进行测试的时候,利用MeshLab对点云进行了法线的计算。但是后来在对算法封装的时候,在内部用了PCL的NormalEstimation来计算点云法线。封装完成后进行测试时发现输出的结果与之前测试相比差了一些。后来排查问题的时候发现原因就是出在法线计算上。在对比了PCL计算的法线与MeshLab计算的法线后得到结论:PCL计算的法线没有MeshLab计算的法线精准。所以问题来了,就要去看MeshLab的源码,把MeshLab中如何计算法线的功能提取出来,再与算法一起进行封装。大概花了一天半的时间,终于把MeshLab中计算法线的功能给提取了出来,这里做个记录,以后提取其余的功能也是一样。

二、定位计算法线的功能模块

一开始想着可能要编译整个MeshLab的源码了,但是来来回回搞了很久也没成功,所以我打算另辟蹊径,动起了大脑。

  1. 首先打开MeshLab,然后依次点击 F i l t e r s → P o i n t   S e t → C o m p u t e   n o r m a l s   f o r   p o i n t   s e t s Filters \rightarrow Point\ Set\rightarrow Compute\ normals\ for\ point\ sets FiltersPoint SetCompute normals for point sets,当最后把鼠标挪到 c o m p u t e   n o r m a l s   f o r   p o i n t   s e t s compute\ normals\ for\ point\ sets compute normals for point sets 选项上时,会弹出来一个小窗口,在小窗口的最下方标识了 f i l t e r _ m e s h i n g . d l l filter\_meshing.dll filter_meshing.dll。如下图所示。
    在这里插入图片描述
    这个不就说明了所要找的计算法线的功能在 f i l t e r _ m e s h i n g filter\_meshing filter_meshing这个模块吗。

  2. 在MeshLab的源码(没有源码的话肯定就要先下载下来)中找到 f i l t e r _ m e s h i n g filter\_meshing filter_meshing文件夹,路径一般都是

.\src\meshlabplugins\filter_meshing
  1. 然后可以用QT或者有QT插件的VS打开里面的 f i l t e r _ m e s h i n g . p r o filter\_meshing.pro filter_meshing.pro文件,打开后就能看到如下图所示的目录结构。
    在这里插入图片描述
    点进 m e s h f i l t e r . h meshfilter.h meshfilter.h,发现里面跟法线相关的就只有两个枚举类型 F P _ N O R M A L _ E X T R A P O L A T I O N ,   F P _ N O R M A L _ S M O O T H _ P O I N T C L O U D FP\_NORMAL\_EXTRAPOLATION,\ FP\_NORMAL\_SMOOTH\_POINTCLOUD FP_NORMAL_EXTRAPOLATION, FP_NORMAL_SMOOTH_POINTCLOUD。顾名思义,第一个枚举类型名字就是“法线推导”。然后到 m e s h f i l t e r . c p p meshfilter.cpp meshfilter.cpp中找所有与 F P _ N O R M A L _ E X T R A P O L A T I O N FP\_NORMAL\_EXTRAPOLATION FP_NORMAL_EXTRAPOLATION相关的代码。
  2. 进入 m e s h f i l t e r . c p p meshfilter.cpp meshfilter.cpp中ctrl+F查找关键字,能够找到如下图所示部分。
    在这里插入图片描述
    可以看到,“Compute normals for point sets”这句话应该就是对应着第1步中的那个选项,可以确定计算法线的模块就在这里面八九不离十了。
  3. 继续在当前这个文件中查找关键字。
    在这里插入图片描述
    一直找到这里,看到了【PointCloudNormal】这个字样,立刻就反应过来,这里就是计算点云法线了!简单看一下代码就能知道,里面的 p . f i t t i n g A d j N u m 、 p . s m o o t h i n g I t e r N u m 、 p . v i e w P o i n t 、 p . u s e V i e w P o i n t p.fittingAdjNum、p.smoothingIterNum、p.viewPoint、p.useViewPoint p.fittingAdjNump.smoothingIterNump.viewPointp.useViewPoint 这四个参数,正好就是对应着在MeshLab中计算法线的窗口里需要填的四个参数,如下图。
    在这里插入图片描述
    那么那个 t r i : : P o i n t C l o u d N o r m a l < ∗ ∗ ∗ > : : C o m p u t e ( ) tri::PointCloudNormal<***>::Compute() tri::PointCloudNormal<>::Compute()就是计算法线的函数了。按住ctrl键点击 C o m p u t e Compute Compute就能定位到 vcglib 文件夹下,那么就说明,MeshLab中计算法线也只不过是调用的VCGLib的库而已。这样就好做多了,定位到此就结束了。

三、调用VCGLib库计算法线

3.1 包含VCGLib目录

首先用VS新建一个空项目,然后右击源文件,导入 ‘.\vcglib\wrap\ply\ply.cpp’ 文件,如果不导入这个文件的话,最后运行就会出现一堆如下图所示的错误。
在这里插入图片描述
然后新建一个 pointset_normal.cpp 文件,叫其他名字当然也行。
在这里插入图片描述
然后再项目属性中,将vcglib根目录以及eigenlib目录包含进来,如下图。注:如果不包含eigenlib目录,编译时可能会出现无法打开源文件 <Eigen/Eigen>之类的错误
在这里插入图片描述
这样环境配置就完成了。

3.2 计算法线

3.2.1 代码

一开始不知道怎么样用这个VCGLib,但是在 vcglib\apps\sample 文件夹下有很多示例代码,多跑几个代码看一看就知道怎么样用了。计算法线并保存到本地的代码如下所示。

#include<vcg/complex/complex.h> //这个一般都要有,否则编译会有很多错误

#include <vcg/complex/algorithms/update/color.h>
#include <vcg/complex/algorithms/pointcloud_normal.h>
#include <wrap/io_trimesh/import.h>
#include <wrap/io_trimesh/export.h>

class MyFace;
class MyVertex;

struct MyUsedTypes : public vcg::UsedTypes<	vcg::Use<MyVertex>::AsVertexType, vcg::Use<MyFace>::AsFaceType> {};

class MyVertex : public vcg::Vertex< MyUsedTypes, vcg::vertex::Coord3f, vcg::vertex::Normal3f, vcg::vertex::Color4b, vcg::vertex::BitFlags  > {};
class MyFace : public vcg::Face < MyUsedTypes, vcg::face::VertexRef, vcg::face::Normal3f, vcg::face::Color4b, vcg::face::BitFlags > {};
class MyMesh : public vcg::tri::TriMesh< std::vector<MyVertex>, std::vector<MyFace> > {};


int  main()
{
	MyMesh m;

	vcg::tri::io::ImporterPLY<MyMesh>::Open(m, "00000000_00_world.ply");

	vcg::tri::PointCloudNormal<MyMesh>::Param p;
	p.fittingAdjNum = 40;
	p.useViewPoint = true;
	vcg::tri::PointCloudNormal<MyMesh>::Compute(m, p);
	vcg::tri::io::PlyInfo pi;
	pi.mask = vcg::tri::io::Mask::IOM_VERTNORMAL;
	vcg::tri::io::ExporterPLY<MyMesh>::Save(m, "00000000_00_world_normal.ply", true, pi);

	return 0;
}

3.2.2 结果展示并验证

找一个点云文件,先用MeshLab计算一下法线保存,然后再利用上面这个代码计算一下法线并进行对比。注意:在用两种方式计算法线时,参数要一致才能对比。

计算的法线如图,上下分别为MeshLab计算的法线和代码计算的法线,可以看出来是一模一样的。
在这里插入图片描述
在这里插入图片描述
进一步验证,利用记事本分别打开这两个点云文件,可以看到:

在这里插入图片描述
这两个的文件完全一致,说明我们调用的VCGLib计算得到的法线与MeshLab计算的法线是一致的。

  • 15
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值