https://github.com/ShiqiYu
=================================================
知乎关于人脸识别实时滤镜讨论:
映客直播中 人脸特效是基于人脸识别还是AR?有什么可以使用的SDK么?
链接:https://www.zhihu.com/question/52892092/answer/205076802
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
本人来说说该这是如何实现的吧。关键字:人脸检测+图片 + opengles。
我来说说Android上面是如何实现的吧。通过Camera接口获取预览数据,然后将图像所在的Surface绑定到opengles 的EGLSurface中,opengles通过从Surface中读取EXTERNAL_OES类型的纹理Texture到帧缓冲区Framebuffer中(即将相机的图像帧读入FBO中),然后就是通过opengles将png 或者其他格式的图片贴纸读入生成相应的纹理Texture。有了贴纸的Texture,接下来就是将贴纸绘制到帧缓冲区Framebuffer中。绘制完成,通过eglSwapBuffers将EGLSurface中渲染完成的帧交换显示到前台,这就是问题中所贴出来的预览界面。
上面流程几乎所有有贴纸特效的相机、直播推流端等应用都基本走的流程,不管是不是用ffmpeg做推流,特效这块,基本上都需要接入opengles来做渲染,一方面是减少CPU使用,降低能耗,降低发热量,另一方面是渲染速度,gpu专门做渲染这一块的,在实时渲染方面,CPU软实时渲染的效率是完全不够的。这个过程需要什么支撑?那就是人脸检测技术,我将贴纸纹理渲染到预览帧中,需要拿到准确的人脸关键点,这个是必须的。人脸检测基本上都是用opencv来检测的,也有第三方的SDK可以接入,比如Face++,美颜相机等存在贴纸特效的应用几乎都在用这个,可以免费试用,自己从头开发的话,准确率和检测时间是个大问题,人脸关键字检测的算法比较成熟了,但传统的算法跑在手机上还是做一些调整的,尤其是这种实时渲染的,得至少控制在一帧(16ms)内,因为除了检测,我们还需要做其他的渲染,比如美颜、美白、磨皮、瘦脸等,哪怕是用opengles来做,也是勉强够用而已。举个例子,美颜相机的贴纸相机,在1080P分辨率的手机上,默认Texture 的大小也仅仅是480 x 864(存在虚拟键)、540 x 960(不存在虚拟键),也就是说,预览帧的分辨率是这么大的,而不是屏幕的1080P(目前市面上的美颜类相机,预览帧(Camera PreviewSize)几乎没有达到1080P的,都是渲染完成后在放大的。除了美颜相机, Camera360的预览texture是764 x 1024, 全屏是720 x 1280,但显示则是1080 x 1440、1080 x 1920,各家的相机流程差不多,渲染方案的话有单FBO 和多FBO两种,Camera360 就是单一FBO渲染的,美颜相机则是多FBO渲染的)。渲染完成后再放大显示到屏幕上的,因为美颜相机处理做贴纸,还做了实时美颜、磨皮、美白、瘦脸、瘦下巴、放大眼睛等操作,这些操作都是非常耗时的,哪怕是这样,美颜相机在红米Note2 上渲染出来的实时预览帧率也只面前到20帧,Nexus 5X 实时预览帧率大约23帧左右。大部分手机的预览帧率最大支持值在30fps左右,能够拿来做渲染的时间还是非常不足的。
那么有没有相关的开源项目呢?有的,比如比较出名的相机项目MagicCamera就是其中一个,github地址: wuhaoyu1990/MagicCamera 你可以参考下。贴纸跟滤镜的渲染过程是一样的,其中多了个人脸关键点检测,也就是说,在用opengles绘制贴纸之前,需要做相关的定位、贴纸的三维位置调整,比如人脸朝向,贴纸要跟着人脸朝向绘制,否则方向是不对的。人脸朝向的话,也有专门的算法,但是如果要做到实时渲染,那么在人脸检测之后再做人脸朝向的话,效率就太低了,这里面可以用检测的关键点简单结算得到朝向的,比如简单地用人的眼睛位置,通过Math.atan2(distX, distY),通过眼睛中心点的距离(distX, distY)算方位角,虽然准确率不够,而且考虑的因素也不全,但在实时渲染预览情况下也没有更好的办法,因为你首先得保证预览的帧率。得到人脸朝向的方位角后,我们就可以拿着这个方位角对贴纸的位置绕Y轴旋转,通过对投影矩阵旋转得到三维物体在二维平面上的坐标位置,再对贴纸进行渲染。这样就能够做到立体感的贴纸了。
基本上做完上面的一些处理,