一般的特效渲染引擎都包含对人脸进行形变的功能,能够对图片或实时相机流数据中的人脸进行形变,以实现脸部美型或者夸张搞笑的脸部形变效果。形变方式通常有两种:分次渲染和位移向量图。分次渲染是每次网格点位置调整后都先将结果渲染出来,作为下一次形变的原始图像输入;位移向量图可以先将多次的网格形变统一计算处理,最后再将最终的形变效果渲染出来。位移向量图的实现方式效率较高,但是在Android平台上会有顶点着色器纹理采样点个数限制的兼容性问题,本文就对此兼容性问题进行讨论。
形变基本原理
特效渲染引擎对人脸进行形变的功能,基本原理是将图片划分成一个个很小的网格,在OpenGL渲染管线的顶点着色器阶段对网格顶点坐标进行变换调整,然后在片段着色器阶段对新网格位置填入原网格纹理像素值,实现形变的效果。基本原理如下图所示:
以上图为例,我们首先将输入图像进行划分,分成大量细小的网格,然后以人脸某些定位点为基准,划分其影响范围(一般为圆形),以网格的顶点作为输入,对在影响范围内的网格点进行偏移。在此例中,对额头部分的网格点向中间挤压,脸部的风格点向外拉伸。然后在片段着色器阶段对新网格位置填入原网格纹理像素值,就形成了头尖脸大的形变效果。
两种实现方式
因为shader
中数组长度的限制,形变滤镜一次可处理的人脸定位点个数有限,对复杂形变一般需要多次形变滤镜渲染才可完成。在多次形变滤镜渲染时,根据处理的步骤不同,形变分为两种实现方式:分次渲染和位移向量图。下面分别进行介绍:
-
分次渲染。多次形变滤镜渲染步骤中,在每次处理时,形变网格点位置变化后都直接作用于原图,并生成结果图,然后下次形变滤镜处理以上次形变的结果图作为输入。假设我们输入图像的分辨率为
1080 * 1920
,将图像划分为50 * 66
的网格,需要进行3次形变渲染,我们的处理步骤如下图所示:其中绿色表示
vertex shade
r处理,即对50 * 66
的网格点进行变换偏移,蓝色表示fragment shader
处理,即根据变换后的网格点生成处理图像。每次渲染都直接将当次形变结果生成结果图,并作为下一次处理的输入。 -
位移向量图。位移向量图是指把网格点的偏移量数据存储在fragment shader处理后的像素数据中,其处理后代表的图像并不是形变后的结果图,而只是临时保存网格顶点偏移量,实际观察时并不能从位移向量图像中看到什么。位移向量图的形式如下图所示: