人像瘦脸效果实现(网格液化)——OpenGL实现

一、网格液化形变

1.液化

    网格液化形变是指,事先将图片划分成若干个网格,再对其中某一些网格的坐标进行变换,以达到图像形变的效果。
    网格可以是四边形,或三角形,在计算机图形当中用三角形比较多,因为大多数底层绘制都是以三角形作为最基础的绘制单元进行绘制。OpenGL也是如此。
    这个液化在Photoshop里的“液化”功能可以最简单直观体验。

2.网格的变化

    这个“网格的变化”可以被记录并保存。可以这样理解:有一张“标准的网格图”,每次液化形变都同时会作用到这张标准网格图当中。
    当下次需要应用相同的形变时,读取这张形变后的“标准网格图”,按照标准网格图进行新的图像绘制即可。

  • 人像瘦脸效果实现(网格液化)——OpenGL实现_第1张图片

  • 标准网格图:

  • 人像瘦脸效果实现(网格液化)——OpenGL实现_第2张图片

  • 液化后的网格图:

  • 人像瘦脸效果实现(网格液化)——OpenGL实现_第3张图片

二、利用网格液化实现瘦脸效果

1.划分人脸网格

    一般来说,在进行瘦脸效果之前,都需要进行人脸检测,得到人脸部位的若干人脸点。(这一步一般在渲染之前就已经完成,由人脸SDK完成)。目前主流人脸检测都是基于深度学习算法,各大厂自研或使用第三方算法,如商汤等。

  • 人脸检测点位例子:
  • 人像瘦脸效果实现(网格液化)——OpenGL实现_第4张图片

2.划分人脸网格

    OpenGL是基于三角形进行绘制图像的,在绘制人脸网格的时候,可以将人脸的区域划分成若干个三角形,然后将贴纸绘制在这些三角形当中。
    将这些离散的零散的点位,按照一定规则划分成不重叠的三角形,这叫“三角剖分算法”。三角剖分算法有很多。可以参考:三角剖分算法

  • 三角剖分后的人脸三角形:
  • 人像瘦脸效果实现(网格液化)——OpenGL实现_第5张图片

3.定义标准人脸网格,在标准人脸网格里进行瘦脸需要的网格偏移和计算

    在瘦脸之前,需要先定义一个标准模特的人脸网格(一般使用标准模特图进行人脸检测即可)。瘦脸的网格计算需要在标准人脸网格下进行计算,对其中的某一些网格点进行偏移。例如需要瘦脸,就移动脸周围一圈的网格,如果需要大眼,就移动眼睛周围一圈的网格。
    在实际绘制时,将实际人脸点与标准人脸点一一匹配对应进行绘制,就能将计算偏移后的网格绘制出来,就得到了瘦脸的结果图。

    一般来说,为了保护非人脸区域也受到了形变的影响(理论上应该只改变人脸区域,其他区域保持不动),会在人脸周围外一圈计算或插值出新的一圈“保护网格”,在保护网格外的区域则完全不参与形变。

  • 蓝色为原始标准人脸网格,红色为外圈保护网格:
  • 人像瘦脸效果实现(网格液化)——OpenGL实现_第6张图片
  • 瘦脸的变化,本质上是网格的液化形变:

  • 人像瘦脸效果实现(网格液化)——OpenGL实现_第7张图片

三、液化瘦脸中需要注意的一些坑

1.多部位瘦脸时,不同部位相互影响的问题

  • 在单独调整不同部位的瘦脸形变时,可能会出现相互影响的情况,例如“瘦脸”效果和“大眼”效果,在网格变化时可能会影响到彼此的网格。
  • 在这里有2种解决方案:
    • 1.如果必须使用同一张网格,每个部位选择的点和网格不重复。如果点和网格不够多,那么需要在现有网格的基础上差值或推算出更多更精细的点位和网格。
    • 2.如果不是必须使用同一张网格,则可以每个部位单独计算出独立的网格,这样不同部位网格单独计算,不会相互影响。

2.多人脸,且人脸靠得近时,不同人脸的形变会相互影响

  • 当两个人脸形变网格靠的足够近时,会不可避免地出现形变网格互相重叠的情况,在对一个人瘦脸时会对另一个人的脸也造成形变的影响。
  • 解决方案和思路如下:
    • 细化人脸周围网格,把外圈形变的网格控制在比较小的范围。也可以识别和计算人脸距离,根据人脸距离动态调整这个形变范围

效果图:

人像瘦脸效果实现(网格液化)——OpenGL实现_第8张图片

源代码工程:https://github.com/sysu-huangwei/Facelift

文档:https://blog.csdn.net/q345911572/article/details/128758125

你可能感兴趣的:(OpenGL,图像算法,OpenGL,OpenGLES,图像处理,图形渲染)