大家还记得我们上文中讲过的那个由大量体素组成的立方体TSDF场吧。不记得的话,可以翻到上文重写阅读一遍详解kinectfusion之四基于TSDF场的点云融合-CSDN博客
这个TSDF场中每个体素都包含三个属性值,TSDF值,权重和颜色信息。其中,tsdf值代表当前体素离物体真正的表面的距离。
本文的目的就是要找到tsdf值为0的那些点坐标,并且把这些点坐标连起来构成一个网格。备注,这里的网格是每三个点确定的三角形依次相连,最终构成的形状即网格。大致的样子如下图所示。
实现方法最经典的就是marching cubes了。
为了更容易理解marching cubes,我们先从2d处理讲起,也就是 marching squares。
现在有一个不规则的片状物体,如下图所示。
1)为了能数字化表示这个不规则的2d片状物体,我们先用2d方块分割处理一下。
2)直观上,很容易判断哪些方块的顶点落在了不规则物体的内部,哪些顶点在外部。结果如下
3)那么,找出有这样属性的小方块的边哈,就是一端落在物体内部,一端落在物体外部,那么这个边上必有一点是落在物体表面。
4)这里有人可能会问,如何确定方块的边上粉色点的坐标呢?这里是由线性插值法来确定的。
已知方块的边上的端点坐标为点和点,和分为和的tsdf值,还已知粉色点的tsdf值为0,求粉色点坐标为
5)当确定了方块与物体交点坐标后,用直线连接起交点即可。如下图所示。依次处理完所有的方块,就生成了数字化,可近似表示片状物体轮廓的表示。
下面我们根据2d的处理过程,依次讲解在3d场景下,如果找到可近似表示三维物体表面的方法。
1)我们在上一篇中已经介绍了TSDF场,就是大量带有tsdf值的体素(立方体)来虚拟地分割处理一下。
2)3d场景中也要找到横跨三维物体内部和外部的特殊体素。确定的结果就像下图中红色和蓝色顶点。确定的方法也很简单,就是检查体素8个顶点位置的tsdf值是不是符号相异,也就是有正有负,如果是,就说明这个体素是横跨三维物体内部和外部的。
3)找到上述这种特殊体素后,体素的12条边上肯定有若干条边是穿过了三维物体表面。那么,横跨物体内部与外部的边上,必有一点是落在了物体表面。
4)怎么求解呢?道理与2d场景类似的。
5)在2d中直接交点相连就构成了物体与方块相交的线段;在3d中物体与体素相交的是面片。如下图所示。
依次处理完所有的特殊体素,得到每个体素与物体表面相交的面片,连接起来,就构成了数字化表达物体表面的网格。如下图所示。
上述主要通过图文的方式,用简单的语言,讲述了marching cubes要完成的内容。为了方便大家理解开源代码中看到的marching cubes相关代码,再多讲述一点。
首先,每个体素有8个顶点和12条边,依次对体素的顶点和边编号。
其次,8个顶点根据是否处于物体内部,可组合出2^8=256种情况。举例说明如下
再次,根据顶点是否位于物体内部的状态,可以构建一个0-255的索引。索引由八位二进制构成,每一位是一个顶点的状态,如下图所示。这也是开源代码里常用数组名edgeTable来表示的内容。
还有,每个索引对应的网格表示方法,写在了triTable里。
triTable[3] = {1,8,3,9,8,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}
这个数组表示,边的编号为1、8、3构成一个三角面片,边的编号为9、8、1构成一个三角面片,也就是说,这个体素里有两个三角面片。