基于深度学习的人脸表情识别的AR川剧变脸(二)

news2025/1/18 6:58:20

在一中,我们训练了一个,可以识别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 28
        int[] pixels=new int[newWidth * newHeight];

        bitmap.getPixels(pixels, 0, newWidth, 0, 0, newWidth, newHeight);


        for(int i =0;i<newWidth * newHeight;i++){
            int 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/23755.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

航空摄影与正射摄影的区别

航空摄影 航空摄影是一种摄影&#xff0c;可以在其中从空中捕捉远处的图像。航空摄影的主题可以涵盖许多不同的领域&#xff0c;例如军事侦察、地质、农业等。但它也可以使用不同的技术手段&#xff0c;如无人机、直升机或飞机。本指南将简要概述航空摄影&#xff0c;如何在 G…

百趣代谢组学文献分享:代谢组学中复溶溶剂究竟如何选?

今天&#xff0c;BIOTREE 技术支持工程师Novenia 将和奋斗在实验室的小伙伴们分享一篇关于代谢组学实验过程中溶剂选择的文章Tuning Metabolome Coverage in Reversed Phase LC−MS Metabolomics of MeOH Extracted Samples Using the Reconstitution Solvent Composition。这是…

Canal1.1.6安装部署

什么是Canal 阿里巴巴 B2B 公司&#xff0c;因为业务的特性&#xff0c;卖家主要集中在国内&#xff0c;买家主要集中在国外&#xff0c;所以衍生出了同步杭州和美国异地机房的需求&#xff0c;从 2010 年开始&#xff0c;阿里系公司开始逐步的尝试基于数据库的日志解析&#…

反函数求导:自然对数 ln是怎么得到的;为什么自然对数的导数是 1/ x;arcsin 和 arccos 的导数求算

参考视频&#xff1a;MIT微积分 如何得到的自然对数 lnlnln 首先我们知道以 eee 为底的指数函数 exe^xex 其次&#xff0c;我们引入反函数&#xff08;逆函数&#xff09;的概念 f−1(y)f^{-1}(y)f−1(y) 对于任意的 xxx 如果 f(x)yf(x)yf(x)y 那么 xf−1(x)xf^{-1}(x)xf−1(…

Redis的优惠券秒杀问题(七)在集群模式下的问题

Redis的优惠券秒杀问题&#xff08;七&#xff09;在集群模式下的问题 问题描述 伪集群模式搭建 &#xff08;1&#xff09;IDEA启动镜像 &#xff08;2&#xff09;修改nginx配置 &#xff08;3&#xff09;验证nginx是否启动成功 BUG复现 &#xff08;1&#xff0…

零入门容器云网络-4:基于DNAT技术使得外网可以访问本宿主机上veth-pair链接的内部网络

已发表的技术专栏&#xff08;订阅即可观看所有专栏&#xff09; 0  grpc-go、protobuf、multus-cni 技术专栏 总入口 1  grpc-go 源码剖析与实战  文章目录 2  Protobuf介绍与实战 图文专栏  文章目录 3  multus-cni   文章目录(k8s多网络实现方案) 4  gr…

数据结构:堆

文章目录一.堆的概念和性质二.堆的结构三.堆的实现3.1结构体声明3.2堆初始化3.3释放堆3.4打印堆3.5插入3.6删除3.7取堆顶元素3.8堆的元素个数3.9判空3.10补充四.建堆4.1向上调整建堆4.2向下调整建堆五.排序5.1升序5.2降序六.TOP-K问题一.堆的概念和性质 堆的概念&#xff1a; …

数据存储方式——KVELL:快速持续键值存储的设计与实现

文章目录前言一、背景1.当前流行的两种存储范式2.SSD性能的发展IOPS延迟和带宽吞吐量降低I / O突发3.NVMe ssd上当前KVs的问题3.1 CPU是瓶颈CPU是LSM KVs的瓶颈CPU是B树KVs的瓶颈3.2 LSM和B树KVs的性能波动二、KVELL1.KVs设计原则1.1 不共享1.2 不要在磁盘上排序&#xff0c;而…

Spring——IOC容器部分核心接口

Spring——IOC容器部分核心接口一、简介二、IOC容器核心接口1.BeanDefinition2.BeanDefinitionReader3.BeanDefinitionRegistry4.BeanFactory5.ApplicationContext6.BeanPostProcessor7.BeanFactoryPostProcessor8.BeanDefinitionRegistryPostProcessor9.总结一、简介 以下接口…

vim工具的使用

目录 vim的基本模式 vim三种基本模式(命令模式、底行模式、输入模式) 命令模式 vim正常(命令行)模式命令集 插入模式 底行模式 保存&退出 分屏 替换 执行shell指令 vim底行模式命令集 vim配置 配置文件的位置 配置文件的原理 如何配置 解决sudo无法使用的情…

[附源码]计算机毕业设计JAVA基于协同过滤算法的网上招聘系统

[附源码]计算机毕业设计JAVA基于协同过滤算法的网上招聘系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a…

【教学类-16-01】20221121《数字卡片9*2》(中班)

作品展示&#xff1a; ​ 打印墨水不够了​ 铅笔描边 ​ 剪开 ​ 每个人是A4 一半的大小 ​ 背景需求&#xff1a; 在数字像素图的基础上&#xff0c;我决定制作1-9的数字卡片&#xff0c;空心数字&#xff08;华文彩云&#xff09;涂色&#xff0c;卡片左上角写学号。——…

go使用grpc实现go与go,go与C#相互调用

protoc下载 protoc是protobuf的编译工具&#xff0c;能根据.proto文件生成为各种语言的源文件。 原始的protoc集成了如下语言的转换&#xff1a; cc#javaobjectcphppythonruby 但是没有集成go的转换工具。go的转换工具是在protoc的基础上使用插件的方式运行。 protoc 的下载地…

linux NC命令的本质

NC是一个可以模拟tcp&#xff0c;udp&#xff0c;server,client 的协议&#xff0c; 1-它可以实现两个主机的聊天 server: nc -lp 1234 client : nc 192.168.1.10 1234 以上两个命令就可以实现实时数据传输了&#xff0c;是不是很有意思&#xff0c;但是这个是怎么实现的呢&am…

软考信息安全工程师必会--3000+字文章浅析DES加密算法

目录 前言 什么是DES加密算法 整体流程 IP置换 子密钥K 压缩置换1 循环左移 拓展置换2 拓展置换E S盒代替 S1盒 S2盒 S3盒 S4盒 S5盒 S6盒 S7盒 S8盒 P盒置换 末置换 前言 &#x1f340;作者简介&#xff1a;被吉师散养、喜欢前端、学过后端、练过CTF、玩过DOS…

flink1.10中三种数据处理方式的连接器说明

第一种 Streaming&#xff08;DataStream API&#xff09; 流式处理的所有的连接器如上图&#xff0c;常用的是kafka、Elasticsearch、Hadoop FileSystem Kafka连接器 依赖 <dependency><groupId>org.apache.flink</groupId><artifactId>flink-connec…

2022-11-21 mysql列存储引擎-架构实现缺陷梳理-P1

1. 前言 发现和指出问题为了&#xff1a;更好的解决问题和避免问题的再次发生 项目在演进&#xff0c;代码不停地在堆砌。如果代码的质量一直不被重视&#xff0c;代码总是会往越来越混乱的方向演进。当混乱到一定程度之后&#xff0c;量变引起质变&#xff0c;项目的维护成本…

二叉树和堆

二叉树和堆什么是树树的一些专业术语树的表示二叉树的概念什么是二叉树特殊的二叉树二叉树的性质堆的概念堆的表示方式堆的实现堆的初始化及销毁堆的插入堆的删除堆的判空与获取堆顶元素堆的主要应用堆排序利用堆数据结构建堆利用向上调整算法来建堆利用向下调整算法建堆TopK问…

计算机毕业设计——校园二手市场

一.项目介绍 系统包含 普通用户 和 管理员 两种角色 普通用户 浏览其他用户发布的二手物品&#xff0c;修改个人信息、查看订单&#xff08;买的、卖的&#xff09;、 发布闲置、查看我的闲置、查看我的关注、跳转后台、更改用户名等功能 管理员用户登录 操作用户管理、商品管理…

中学物理教学参考杂志社中学物理教学参考编辑部2022年第21期目录

前沿导航_课改在线《中学物理教学参考》投稿&#xff1a;cn7kantougao163.com 问题导向式学习 提升学生思维品质——以“自由落体运动”教学为例 汪欣; 1-2 物理实验探究式复习模式研究——以“机械能守恒定律”为例 王栋; 3-4 初中物理作业设计类型及其实施策略 马…