大家新年快乐!!过年总是这么短暂,新年新气象,这篇文章本年年前准备发的,过年嘛,总会懒一些,哈哈哈哈。今天我们来简单实现一个嘴唇的贴纸功能,先看看效果。
其实大部分APP的完整功能包含脸部,鼻子,眼镜等的完整渲染,不过原理都类似,我就只用一个嘴唇来抛砖引玉了。看这篇文章之前,需要了解NDK、OpenGL ES的基本知识。
相机采集并渲染画面有很多种方式,但是我们因为要做画面的处理,肯定是选择自己拿到纹理来进行渲染。关于渲染的过程可以看这篇文章。 Android采集并使用OpenGL ES预览摄像头画面 。
通过OpenGL ES渲染,我们可以看到摄像头采集的画面了,然后我们要唇部的渲染肯定要只要人脸关键点的位置了,这里就需要人脸检测了,人脸检测市面上收费的有什么face++,商汤等等。这里我用的是这个
https://github.com/zeusees/HyperLandmark
速度还蛮快的,学习肯定是够用了,感谢提供的支持。我们可以看一下它的106个标点。
这样我们就可以知道采集之后的人脸数据了。
上面的东西准备完毕之后,我们还需要美妆的素材。这些东西可真是不好找,好在在腾讯爸爸的目录下搜刮了一个。大概看一下目录。一个滤镜是由多个图片素材和背景音乐组合而成的,管理他们的就是params.json这个文件了,当然今天我们大部分都用不到。
看一下lian.png,其实渲染上去就是我们平时使用的整体美妆这种效果。
json文件,可以找到脸部关键点的位置,为了节省篇幅,下面我省略了其他部分。
{
"minAppVersion": 400,
"blendAlpha": 1.0,
"featureType": 0,
"grayScale": 0,
"blendMode": 1,
"useMesh": 1,
"facePoints": [
145, 468,
150, 498,
156, 528,
162, 561,
169, 595,
175, 622,
181, 649,
191, 695,
203, 716,
214, 738,
238, 776,
258, 793,
277, 811,
311, 843,
351, 868,
398, 876,
445, 866,
491, 841,
528, 807,
543, 788,
558, 769,
585, 734,
595, 712,
605, 690,
611, 668,
618, 645,
624, 619,
630, 592,
631, 558,
633, 524,
638, 504,
643, 484,
199, 446,
239, 444,
280, 448,
321, 456,
362, 458,
327, 433,
283, 425,
239, 425,
595, 445,
555, 444,
515, 452,
484, 457,
438, 460,
464, 435,
508, 422,
559, 422,
241, 506,
260, 518,
285, 522,
309, 520,
336, 511,
317, 493,
287, 483,
263, 489,
291, 504,
291, 502,
558, 501,
537, 516,
511, 523,
487, 521,
460, 512,
481, 492,
508, 484,
534, 488,
508, 502,
508, 500,
370, 512,
366, 600,
340, 649,
370, 668,
400, 672,
428, 666,
458, 647,
432, 601,
430, 513,
400, 636,
312, 719,
489, 717,
335, 743,
364, 759,
399, 766,
434, 758,
464, 741,
442, 736,
401, 741,
352, 736,
346, 713,
379, 710,
401, 714,
421, 713,
454, 713,
442, 729,
400, 731,
354, 727,
341, 733,
461, 728,
400, 512,
404, 460,
400, 692,
205, 205,
398, 275,
598, 197,
400, 356
]
,
"shaderType": 8,
"maxFaceCount": 2,
"detectorFlag": 2
,
"faceExchangeImage": "lian.png"
....
]}
这些都准备好了之后,想必大家都知道该如何渲染了吧。我们只需要将对应位置渲染到我们检测到的人脸位置即可,也就是先绘制人脸,再绘制图片,纹理的颜色点和人脸检测点一一对应采集即可。这里就来到我们传统的OpengGL绘制三角形时间,因为人脸点比较固定,我们将点一起传入之后,使用下标绘制的方式最好。这里我主要提两点需要注意的地方。
OpenGL不开启混合会导致后面渲染的完全覆盖掉之前的,这里我们使用的是
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
具体关于混合的选项,可以参考这里
https://learnopengl-cn.github.io/04 Advanced OpenGL/03 Blending/
我们不用每次去进行三角分割计算,只需要把索引点保存为数组,再绘制即可。我们将下图红线中的点来绘制三角形,将三角形索引点保存。这里我多绘制了下巴部分的三角形是因为如果只画嘴唇部位的三角形,会有棱角感,而且牙齿会显示不完整,所以我多绘制了下巴部分的三角形,一般来说是可以整张脸绘制的。
文章这里就结束了,感谢大家的阅读,代码因为一开始写的时候有一些健壮性的问题,功能虽然是实现了,可是有部分其他问题,之后我整理之后会放出来。代码大家可以参考https://github.com/CainKernel/CainCamera 这位大神的代码,非常不错的人脸滤镜功能。