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

本文详细记录了作者在复现点云算法过程中,对比PCL与MeshLab法线计算的差异,最终通过剖析MeshLab源码,提取并使用VCGLib库实现精确法线计算的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述

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

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

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

  1. 首先打开MeshLab,然后依次点击 Filters→Point Set→Compute normals for point setsFilters \rightarrow Point\ Set\rightarrow Compute\ normals\ for\ point\ setsFiltersPoint SetCompute normals for point sets,当最后把鼠标挪到 compute normals for point setscompute\ normals\ for\ point\ setscompute normals for point sets 选项上时,会弹出来一个小窗口,在小窗口的最下方标识了filter_meshing.dllfilter\_meshing.dllfilter_meshing.dll。如下图所示。
    在这里插入图片描述
    这个不就说明了所要找的计算法线的功能在filter_meshingfilter\_meshingfilter_meshing这个模块吗。

  2. 在MeshLab的源码(没有源码的话肯定就要先下载下来)中找到filter_meshingfilter\_meshingfilter_meshing文件夹,路径一般都是

.\src\meshlabplugins\filter_meshing
  1. 然后可以用QT或者有QT插件的VS打开里面的filter_meshing.profilter\_meshing.profilter_meshing.pro文件,打开后就能看到如下图所示的目录结构。
    在这里插入图片描述
    点进meshfilter.hmeshfilter.hmeshfilter.h,发现里面跟法线相关的就只有两个枚举类型 FP_NORMAL_EXTRAPOLATION, FP_NORMAL_SMOOTH_POINTCLOUDFP\_NORMAL\_EXTRAPOLATION,\ FP\_NORMAL\_SMOOTH\_POINTCLOUDFP_NORMAL_EXTRAPOLATION, FP_NORMAL_SMOOTH_POINTCLOUD。顾名思义,第一个枚举类型名字就是“法线推导”。然后到meshfilter.cppmeshfilter.cppmeshfilter.cpp中找所有与FP_NORMAL_EXTRAPOLATIONFP\_NORMAL\_EXTRAPOLATIONFP_NORMAL_EXTRAPOLATION相关的代码。
  2. 进入meshfilter.cppmeshfilter.cppmeshfilter.cpp中ctrl+F查找关键字,能够找到如下图所示部分。
    在这里插入图片描述
    可以看到,“Compute normals for point sets”这句话应该就是对应着第1步中的那个选项,可以确定计算法线的模块就在这里面八九不离十了。
  3. 继续在当前这个文件中查找关键字。
    在这里插入图片描述
    一直找到这里,看到了【PointCloudNormal】这个字样,立刻就反应过来,这里就是计算点云法线了!简单看一下代码就能知道,里面的 p.fittingAdjNum、p.smoothingIterNum、p.viewPoint、p.useViewPointp.fittingAdjNum、p.smoothingIterNum、p.viewPoint、p.useViewPointp.fittingAdjNump.smoothingIterNump.viewPointp.useViewPoint 这四个参数,正好就是对应着在MeshLab中计算法线的窗口里需要填的四个参数,如下图。
    在这里插入图片描述
    那么那个tri::PointCloudNormal<∗∗∗>::Compute()tri::PointCloudNormal<***>::Compute()tri::PointCloudNormal<>::Compute()就是计算法线的函数了。按住ctrl键点击ComputeComputeCompute就能定位到 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计算的法线是一致的。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值