在我的博客 【我的Android进阶之旅】在Android中使用MediaPipe库在实时视频源上实现人脸网格Face Mesh的绘制
里面有简单介绍:最终要实现 增强人脸Augmented Faces
的话,里面有个重要步骤是使用UV贴图来绘制面部图案。
增强人脸Augmented Faces
的架构
程序的架构如图所示,过程描述如下:
Camera
,获得相机画面MediaPipe
加载人脸识别模型,并生成Face Mesh
Face Mesh
生成三角网格,并进行UV贴图
,绘制面部图案人脸特征点
计算出Matrix
,和面部动作识别
加载3D模型
,并对其应用Matrix
,使其出现在正确的位置在上一篇博客 【我的Android进阶之旅】在Android中使用MediaPipe库在实时视频源上实现人脸网格Face Mesh的绘制里面简单介绍了一下 UV Map,如下所示:
UV
是二维纹理坐标,U
代表水平方向,V
代表垂直方向。
UV Map
用来描述三维物体表面
与图像纹理(Texture)
的映射关系,有了UV Map
,我们就可以将二维的图像纹理粘贴到三维的物体表面。
关于UVMap的更多资料可以参考下面的视频
但是还不够深入,所以想在这篇文章重新介绍一下UVMap。
UV
是二维纹理坐标,U
代表水平方向,V
代表垂直方向。它定义了图片上每个点的位置的信息。这些点与3D
模型是相互联系的, 以决定表面纹理贴图的位置。
UV
就是将图像上每一个点精确对应到模型物体的表面. 在点与点之间的间隙位置由软件进行图像光滑插值处理。这就是所谓的UV贴图
。
UV Map
用来描述三维物体表面
与图像纹理(Texture)
的映射关系,有了UV Map
,我们就可以将二维的图像纹理粘贴到三维的物体表面。
简单的来说,就是将三维物体上的点映射到二维空间上。
我们可以将三维物体上的任意一个点都映射到一个2维平面之上,举一个简单例子,地球仪
:
倘若拥有从3维World space
到2维Texture space
的一个映射关系,那么只需要将每个点的颜色信息即漫反射系数存储在2维的Texture
之上,每次利用光照模型进行计算的时候根据映射关系就能查到这个点的漫反射系数是多少,所有点计算完之后,结果就像最左边的screen space
之中,整个Texture
被贴在了模型之上。
有了Texture
,有了映射关系,对渲染结果会有一个非常大提升,因为很多fancy
的效果都可以通过texture
的设计得到(当然这属于美术的活儿了,咱们用就行了)。可以看这样一个有点丑的例子。
可以看到在利用texture
渲染之后,这个独眼怪物丑的更有特点了。
我们平时经常接触的三维模型
,不管他是多复杂,都是由很多个面(即Mesh
)来组成。
但是在模型不只是用来看外形,还需要在模型上制作贴图
,让模型
看起来更生动。
但是模型
本身是三维
的,图片
却只能作为二维
的方式存储,UVMap
其实只是三维转换到二维
的一种解决办法。
例如:左侧就是切割好的三维模型
,右侧则是把切好的部件以二维
的方式平铺开的样子。
如果还没理解,这里有个更生动的gif
可以参考。
这个3D模型
展开之后的UV贴图
UV坐标为纹理坐标,在纹理空间中,任意一个二维坐标都在【0,1】内。
纹理坐标的U和V的最大值均为1,每张纹理图Texture map的(u,v)坐标均可存储在三维Mesh的各个顶点信息中,这个存储操作即为两者之间的映射关系。
在UV坐标系(或者UVW坐标系)中,显示器水平方向是U(大小0-1),显示器竖直方向是V(大小0-1),(W的方向垂直于显示器表面) 纹理的映射是将纹理图贴到多边形表面的过程。
映射就是通过(u,v)坐标去查找对应的颜色值,例如下图:
上面的图是一个很简单的示意图,其中(0,0)点和(1,1)点可能根据引擎或者其他的规定,位置会有变化,但是大体来说基本上都是这样的。如果你的UV是(0.1, 0.1)取得颜色值就是绿色,如果你的UV是 (0.2, 0.8)取得颜色值就是粉色,如果你的UV是(0.7, 0.2)取得颜色值就是蓝色,如果你的UV是(0.9,0.9) 取得颜色值就是黄色。
一般来说,最合理的UV分布取决于纹理类型、模型构造、模型在画面中的比例、渲染尺寸等,但有一些基本的原则要注意:
Mesh用于描述物体的形状。使用三角面来存储。
储存的信息: