【Let It Be Color!——3D重建之纹理重建】02-基于映射的纹理重建算法(上)

景末 发表于 2020/08/27 20:41:24 2020/08/27
【摘要】 1 引言在上一篇博文中,我们已经提到过纹理重建的主流方案可以分成基于融合和基于映射的方法。其中,基于映射的方法可能是更可靠的,这其中有论文地位的佐证,此外一些优秀的开源项目,例如OpenMVS,在进行纹理重建时也是采用的此种方法。从本篇博文开始,我们将开始对基于映射的方法进行详细的梳理,考虑到整体长度,这一内容可能会被拆分到数篇博文中,笔者将尝试结合论文(Waechter2014)和开源工程...

1 引言

在上一篇博文中,我们已经提到过纹理重建的主流方案可以分成基于融合和基于映射的方法。其中,基于映射的方法可能是更可靠的,这其中有论文地位的佐证,此外一些优秀的开源项目,例如OpenMVS,在进行纹理重建时也是采用的此种方法。从本篇博文开始,我们将开始对基于映射的方法进行详细的梳理,考虑到整体长度,这一内容可能会被拆分到数篇博文中,笔者将尝试结合论文(Waechter2014)和开源工程(MVS-Texturing)尽可能提纲挈领地叙述这一过程,以帮助读者从开源工程庞大的代码量中解放出来。

2 方法原理

在进行纹理重建时,首先我们当然需要对输入输出的形式和内容有所理解。相信很多稍微接触过3D重建的读者都对.ply、.obj等文件格式并不陌生,因此笔者并不打算在这里浪费过多的笔墨,我们只需要从数据的内容上理解即可。

首先是输入。显然我们手里有一个经过重建得到的3D网格(mesh),其中包含了数以万计甚至百万计的顶点(vertex)和面片(face),每个vertex由一组三维坐标确定(世界坐标系下),每个face由三个vertex的索引号组成(三角形face);此外,我们手里还有一组用于重建该网格的图像,以及,在生成网格的过程中,主要是第一步SfM中,所估计到的对应于每一张图像的相机内外参。

然后是输出。一个可渲染的模型除了vertex和face以外还至少需要包含每一个顶点所对应的纹理坐标(texcoord)以及该坐标所对应的纹理图(atlas)。在渲染模型时,每一个face的颜色会根据三个顶点所对应的texcoord到atlas中找到对应像素,然后将三个像素确定的区域扣出来贴到face上。而对于一个face而言,显然它所对应的颜色能够在输入图像中找到。

也就是说,根本上,纹理重建就是根据mesh、images及其对应的内外参来生成atlas的过程,衔接输入输出的最基本单元是face,核心步骤是为每一个face从输入的images中寻找一个最佳的区域来体现它的颜色,并将这一区域塞到atlas中。

但是在实际操作过程中,我们并不是直接将face对应的颜色区域贴到atlas中,而是将一些连续的faces组合成为一个patch(或在某些论文中称为chart),再将patch贴到atlas中。这样做的原因我想一方面是考虑到算法效率,另一方面是为了尽量减少不同image组合时产生的接缝(seam),事实上,seam问题正是基于映射的方法的短板,所有基于映射的纹理重建算法都花了很多的功夫在处理seam上,这一内容我们会在后面介绍。

image.png

综上所述,基于映射的纹理重建原理可以用下图来表示。这里将每一幅image和它所对对应的内外参(主要是外参,因此用位姿pose来指代这一内容)称为一个view;参考相机内外参可以针对每个face找到最优的view,用label记录该view索引号;将连续使用同一label的faces组合,形成一个patch,找到该patch的边界,从对应的image中截取出该区域,贴到atlas中,并记录每一个顶点对应的texcoord。接下来,我们将依次对这些步骤进行介绍。

3 视角选择

视角选择过程是纹理重建算法的第一步,该步骤的主要目的在于针对每一个face选择一个合适的view来决定该face的颜色表达。从直观上想,该标签至少应该满足以下条件:

1. 该视角下,该face可见;

2. 该视角下,能够看见该face的正面;

3. 该视角下,该face的法线方向接近于平行视线方向(即正视该face);

4. 该视角的图像范围包括该face所在的区域(即照片上有这个face的表面)

综合上述条件,直观地,有的算法选择使用face映射在视角中的三角形面积作为选择视角的判别依据;有的算法则选择使用视线与face法线的夹角来作为判别依据。此外,考虑到在满足上述条件的基础上,所对应的视角应当能够尽可能表达足够丰富的内容以满足不忽略模型表面纹理细节的需求,因此还有的算法选择使用视角中face映射部分的梯度大小来作为判别依据。假设Q表示这些依据的量化值,若从全局的角度来看,则只需满足:

image.png

其中,f_i表示一个face,用l_i表示该face所对应的view标签。

可见,这事实上是一个优化问题,只需针对每个f_i,找到使得E_d达到最小的l_j即可。然而,在实际执行这一步的时候,考虑到接缝的问题,应当尽可能地为相邻的face选择同一个view,因此,在E_d之后,往往还会向优化式中添加一个惩罚项:

image.png

其中,adjacencies表示f_i与f_j相邻,S表示施加的惩罚函数,有的算法采用边界顶点的颜色值或灰度值的差的平方;有的算法中则直接规定选择同一view为0,否则为1。

综上所述,一般执行视角选择步骤的过程就是优化:

image.png

若将所有的face看作是节点,而将face与face的相邻关系看作是节点与节点的边,则整个mesh可以被简化成一个无向图模型。针对这样一个模型,结合上述目标函数,这可以被描述为马尔科夫随机场(MRF)的优化问题。目前已经有相对成熟的解决该问题的算法,直接应用即可为所有的face找到对应的标签。

4 贴图生成

为每一个face选择了view之后,可以将连成片的且对应于同一个view的face看做是一个patch,以patch为单位执行后续的操作一方面可以降低计算的开销,另一方面也增强了颜色的连续性,避免接缝对于最终呈现效果的影响。在实现的过程中,为了改善接缝的问题,通常还需要对缝隙附近的像素值进行调整,这一过程可以分为全局调整和局部调整两个阶段,这项技术将在下一篇博文中进行介绍,本博文暂且跳过这一过程,先描述纹理重建的骨干步骤,及贴图生成。

在拥有了patch以后,接下来只需要将patch分别放到atlas中,再将mesh的顶点对应到atlas的像素即可。具体地,针对每一个patch,从对应的view中提取到patch的范围,形成一个新的小图像,并通过该view的内外参数即patch对应的位置计算patch包含的每一个顶点在小图像中的图像坐标;接下来,新建一个图像(即纹理图),将每个patch对应的小图像放进新图像中,这一过程可以看作是一个装箱(bin packing)问题,采用装箱问题的算法可以计算出patch在新图像中的位置,从而将顶点的图像坐标从patch的小图像转移到新图像中,该坐标即为顶点的纹理坐标。若一个纹理图已经放满,新建一个纹理图即可。

至此,我们已经得到了纹理贴图和纹理坐标,接下来只需将这些信息写进文件即可。这一过程涉及到各种文件格式的解析,不再赘述。


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区),文章链接,文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:cloudbbs@huaweicloud.com进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。