基于深度学习的人脸表情识别的AR川剧变脸(二)
创始人
2024-02-06 05:07:20
0

在一中,我们训练了一个,可以识别angry、disgust、fear、happy、sad、surprised、normal七种人脸表情。

本文将建立在表情识别的基础上,设计一款AR变脸效果的软件,通过前置摄像头获取人脸图像,使用训练好的模型进行人脸表情识别,然后根据不同的表情,实现不同脸谱的渲染。

软件效果截图如下,首先右上角有按钮,FPS打开则显示当前帧数,Emotion打开则显示当前表情识别结果,Mask打开则渲染脸谱效果。
动图效果放在文末。
在这里插入图片描述

1、模型转换

我们的模型使用Keras训练,但是这样的模型是无法直接在Android移动端使用的,所以需要转换为Android可用的。

幸运的是TensorFlow的TensorFlow Lite(tflite)可以在Android上使用,如果能将模型转换为tflite,则就可以将模型移植到Android。
在这里插入图片描述

因为Keras以及被包含在TensorFlow里了,所以转换也非常方便:

from keras.models import Model,load_model
import tensorflow as tf# keras模型的文件按路径
model=load_model(r"keras.hdf5",compile=False)   # keras.hdf5是Keras训练好的模型converter =tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()open("output.tflite", 'wb').write(tflite_model)  # 转换成功后会得到output.tflite文件,这个就是转换后的模型,可以在Android中使用

2、Android部署

现在我们得到了模型文件,那么在Android部署还需要一个推理框架:tensorflow.lite

在Android中模型部署,将表情识别写成一个类:TFLiteClassificationUtil,在这个类里主要有两个方法,preProcess用于预处理:当我们从前置摄像头拿到人脸图像后,需要进行图像缩放、类型变换、维度变换、灰度变换等处理,让输入符合模型的要求,predict用于预测:也就是接收一个图像数据,使用我们的tflite模型进行预测得到结果并返回。

package com.google.ar.core.examples.java.augmentedfaces;import android.graphics.Bitmap;import org.tensorflow.lite.DataType;
import org.tensorflow.lite.Interpreter;
import org.tensorflow.lite.nnapi.NnApiDelegate;
import org.tensorflow.lite.support.tensorbuffer.TensorBuffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;import java.io.File;public class TFLiteClassificationUtil {private Interpreter tflite;private final TensorBuffer outputProbabilityBuffer;private static final int NUM_THREADS = 4;int[] imageShape;   //用以储存model的input_shape    [1,n,n,channel]/*** @param modelPath model path*/public TFLiteClassificationUtil(String modelPath) throws Exception {File file = new File(modelPath);if (!file.exists()) {throw new Exception("model file is not exists!");}try {Interpreter.Options options = new Interpreter.Options();// 使用多线程预测options.setNumThreads(NUM_THREADS);// 使用Android自带的API或者GPU加速NnApiDelegate delegate = new NnApiDelegate();
//            GpuDelegate delegate = new GpuDelegate();options.addDelegate(delegate);tflite = new Interpreter(file, options);// 获取输入,shape为{1, height, width, 3}String input="conv2d_input";String output="Identity";imageShape = tflite.getInputTensor(tflite.getInputIndex(input)).shape();DataType imageDataType = tflite.getInputTensor(tflite.getInputIndex(input)).dataType();// 获取输入,shape为{1, NUM_CLASSES}int[] probabilityShape = tflite.getOutputTensor(tflite.getOutputIndex(output)).shape();DataType probabilityDataType = tflite.getOutputTensor(tflite.getOutputIndex(output)).dataType();outputProbabilityBuffer = TensorBuffer.createFixedSize(probabilityShape, probabilityDataType);// 添加图像预处理方式//about input/output more info: https://www.tensorflow.org/lite/inference_with_metadata/lite_support} catch (Exception e) {e.printStackTrace();throw new Exception("load model fail!");}}private ByteBuffer preProcess(Bitmap bitmap) {// 设置想要的大小(也即是model的input shape)int newWidth = imageShape[1];int newHeight = imageShape[2];bitmap=Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, false);//buffer初始化    //定义一个Buffer,可以直接加载run()ByteBuffer inputBuffer = ByteBuffer.allocateDirect(4 * 1 * newWidth * newHeight * 1);inputBuffer.order(ByteOrder.nativeOrder());inputBuffer.rewind();// The bitmap shape should be 28 x 28int[] pixels=new int[newWidth * newHeight];bitmap.getPixels(pixels, 0, newWidth, 0, 0, newWidth, newHeight);for(int i =0;iint pixel = pixels[i];float avg = (((pixel >> 16) & 0xFF) * 38 + ((pixel >> 8) & 0xFF) * 75 + (pixel & 0xFF) * 15) >> 7;  //RGB图像转灰度图,pixels是多字节直接换算后的整数,所以还是用位运算更直接简便inputBuffer.putFloat(avg);}return inputBuffer;}// 执行预测float[] predict(Bitmap bmp) throws Exception {   //传入一张bitmap图ByteBuffer inputImageBuffer= preProcess(bmp);try {tflite.run(inputImageBuffer, outputProbabilityBuffer.getBuffer().rewind());   //开始推理} catch (Exception e) {throw new Exception("predict image fail! log:" + e);}float[] results = outputProbabilityBuffer.getFloatArray();int l = getMaxResult(results);return new float[]{l, results[l]};}// 获取概率最大的标签public static int getMaxResult(float[] result) {float probability = 0;int r = 0;for (int i = 0; i < result.length; i++) {if (probability < result[i]) {probability = result[i];r = i;}}return r;}}

3、脸谱AR

既然表情识别问题解决了,现在来解决脸谱AR的实现。

首先Android软件的整体框架:
在这里插入图片描述

其中AR使用Google ARCore框架实现,下图是ARCore的流程图,通过拿去摄像头图像数据、位置分析、渲染效果,不断重复,就感觉实现了AR效果。
在这里插入图片描述

结合本设计,最后设计的流程图如下所示:
在这里插入图片描述
Tflite魔抗就是表情识别。获取图像数据后,分析人脸表情,根据不同表情加载不同的脸谱样式,然后给人脸渲染上脸谱。

比如,下面的代码就是通过不同表情类别(0~6表示),渲染不同的脸谱

switch (maxIndex) {case 0:augmentedFaceRenderer_0.draw(projectionMatrix, viewMatrix, modelMatrix, colorCorrectionRgba, face);break;case 1:augmentedFaceRenderer_1.draw(projectionMatrix, viewMatrix, modelMatrix, colorCorrectionRgba, face);break;case 2:augmentedFaceRenderer_2.draw(projectionMatrix, viewMatrix, modelMatrix, colorCorrectionRgba, face);break;case 3:augmentedFaceRenderer_3.draw(projectionMatrix, viewMatrix, modelMatrix, colorCorrectionRgba, face);break;case 4:augmentedFaceRenderer_4.draw(projectionMatrix, viewMatrix, modelMatrix, colorCorrectionRgba, face);break;case 5:augmentedFaceRenderer_5.draw(projectionMatrix, viewMatrix, modelMatrix, colorCorrectionRgba, face);break;case 6:augmentedFaceRenderer_6.draw(projectionMatrix, viewMatrix, modelMatrix, colorCorrectionRgba, face);break;
}

4、演示效果

通过变换不同的表情,实现脸谱变脸:

脸谱AR演示_x264

相关内容

热门资讯

向英雄致敬的句子 向英雄致敬的句子  导语:当困难来临时是你们站在了一线,重重的困难阻扰都打不倒你那颗顽强的心。我们非...
唯美优美句子 唯美优美句子大全  1、生活是蜿蜒在山中的小径,坎坷不平,沟崖在侧。摔倒了,要哭就哭吧,怕什么,不心...
问候早上好的暖心简短句子 问候早上好的暖心简短句子(精选90句)  无论是在学校还是在社会中,大家都接触过很多优秀的句子吧,句...
描写人物外貌的好段 描写人物外貌的好段  外貌最常用于描述人的外表,容貌。也形容空间以及物体的外观结构,容貌。下面,小编...
爱自己的经典语句 关于爱自己的经典语句(精选145句)  在平平淡淡的学习、工作、生活中,大家一定都接触过一些名人语句...
描写月亮很圆的句子 描写月亮很圆的句子大全  无论是在学校还是在社会中,许多人都接触过一些比较经典的句子吧,句子由词或词...
英语句子在线翻译   你勇敢,世界就会让步。如果有时它战胜你,你要不断地勇敢再勇敢,它就会屈服。下面的是小编分享的与英...
人生大起大落的感悟句子 人生大起大落的感悟句子  所有的胜利,与征服自己的胜利比起来,都是微不足道。所有的失败,与失去自己的...
描写菊花的句子 描写菊花的句子(精选125句)  在现实生活或工作学习中,大家都知道一些经典的句子吧,句子可分为单句...
飞鸟集好词好句 飞鸟集精选好词好句  无论是在学校还是在社会中,大家或多或少都接触过一些经典的好词好句吧,好词好句的...
励志句子带图片 励志句子带图片  生活可能面目狰狞,但一定要以漂亮的姿态去迎战,励志句子带图片。下面是由应届毕业生小...
描写春分时节的句子 描写春分时节的句子  在我们平凡的日常里,大家总免不了要接触或使用句子吧,句子是能够表达一个相对完整...
搞笑绕口令笑破肚皮 搞笑绕口令笑破肚皮  绕口令是民间汉语语言游戏,将声母、韵母或声调极易混同的字,组成反复、重叠、绕口...
用满意造句 用满意造句  在平日的学习、工作和生活里,大家总少不了接触一些耳熟能详的句子吧,根据句子的语气用途不...
描写人生很累很辛苦的句子 描写人生很累很辛苦的句子集锦  在日常生活或是工作学习中,大家一定没少看到经典的句子吧,句子能表达一...
优秀作品傅雷家书摘抄_优秀句... 傅家雷书是我国文学艺术翻译家傅雷及夫人19541966年间写给孩子傅聪、傅敏等的家信摘编,该书是一本...
初中作文优美语段「摘抄」 初中作文优美语段「摘抄」  摘抄即从文刊、文件等里阅读 ,再把语言优美,值得品析,值得学习的词语,句...
早安最美句子 早安最美句子  在平平淡淡的日常中,大家都听说过或者使用过一些比较经典的句子吧,句子是能够表达一个相...
生日快乐经典句子 生日快乐经典句子(精选80句)  在日常的学习、工作、生活中,大家都接触过很多优秀的句子吧,借助句子...
天冷加衣的温馨句子 天冷加衣的温馨句子  天冷加衣的句子有哪些?天气变冷了加衣服,想要发表说说表达此时的感情,下面这些天...