最近,研究了下人脸识别换装,确定了技术方案和技术路线,并最终实现了想要达成的效果,现将制作过程中遇到的问题以及实现的过程记录下来,以便回顾总结的同时,也和其他想实现人脸识别换装的同学分享下经验,避免踩坑。
本项目主要是在Android系统上实现人脸换装的效果,实现路径如下:
1.技术选型;
2.人脸识别算法实现;
3.人脸识别后抠图;
4.目标图片人脸识别;
5.匹配目标图片脸部特征点,实现换装效果;
技术选型
这里的技术选型主要讲的是人脸识别技术,不涉及项目的架构实现等技术。接到人脸识别需求时,我首先想到的是在线的人脸识别API,如百度、讯飞、阿里等都有相关人脸识别API,这些API返回的数据类型基本都是人脸各个器官部位的特征点,根据脸部区域可以将图抠出来。但,在线API对网络环境有一定要求,为了不受网络环境限制,于是,只能舍弃在线获取API方案,转而寻找离线方案。
这里我调研了几种方案,先简单分享下:
1.MediaPipeUnityPlugin
功能强大,能力多,但是需要花费的工作量也大,感兴趣的同学,可以下载研究下https://download.csdn.net/download/liuleitheone/897775622.Opencv for Unity
最终技术选型,为此方案https://download.csdn.net/download/liuleitheone/89777634
3.去其他方案
如 Single Face Tracker Plugin Lite Version;
Kinect for Unity等,感兴趣的可以研究下。
技术实现
Opencv中有个接口,可以实现将Texture2D转为Mat类型,即可以作为材质应用到物体上。
创建人脸识别并返回特征点,具体实现如下,上代码:
代码段一
/// <summary>/// 创建人脸识别并返回人脸特征/// </summary>/// <param name="imgTexture">识别的人脸信息</param>/// <returns></returns>public void OnDetectfacePoint(Texture2D imgTexture, Texture2D targetTex = null, Action callback = null){gameObject.transform.localScale = new Vector3(imgTexture.width, imgTexture.height, 1);Debug.Log("Screen.width " + Screen.width + " Screen.height " + Screen.height + " Screen.orientation " + Screen.orientation);meshOverlay.UpdateOverlayTransform(gameObject.transform);meshOverlay.Reset();float width = 0;float height = 0;width = gameObject.transform.localScale.x;height = gameObject.transform.localScale.y;float widthScale = (float)Screen.width / width;float heightScale = (float)Screen.height / height;if (widthScale < heightScale){Camera.main.orthographicSize = (width * (float)Screen.height / (float)Screen.width) / 2;}else{Camera.main.orthographicSize = height / 2;}Mat rgbaMat = new Mat(imgTexture.height, imgTexture.width, CvType.CV_8UC4);OpenCVForUnity.UnityUtils.Utils.texture2DToMat(imgTexture, rgbaMat);Debug.Log("rgbaMat ToString " + rgbaMat.ToString());if (faceLandmarkDetector == null)faceLandmarkDetector = new FaceLandmarkDetector(sp_human_face_68_dat_