当前位置: 首页 > news >正文

人脸活体识别4:Android实现人脸眨眼 张嘴 点头 摇头识别(可实时检测)

人脸活体识别4:Android实现人脸眨眼 张嘴 点头 摇头识别(可实时检测)

目录

人脸活体识别4:Android实现人脸眨眼 张嘴 点头 摇头识别(可实时检测)

1. 前言

2.人脸活体识别方法

(1)基于人脸动作的检测​​

(2)​​基于红外的活体识别​​

(3)基于深度的活体识别​​

 3.人脸检测模型

 4. 活体识别模型

(1) 将Pytorch模型转换ONNX模型

(2) 将Pytorch模型转换为NCNN模型

5. 活体识别Android部署

(1) Android部署NCNN模型

(2) Android编译异常解决方法

6.活体识别效果(Android版本)

7. 项目Android源码下载


1. 前言

人脸活体识别技术是确保人脸识别系统安全性的关键,主要用于区分真实人脸与伪造攻击(如照片、视频、3D面具等)。本项目基于深度学习技术,构建了一套高鲁棒性的面部活体检测系统,可精准识别眨眼(闭眼)、张嘴、点头(低头)、摇头(侧脸)等生物特征动作,可有效防范照片、视频、3D面具等伪造攻击等多种场景,​​可应用于金融支付、远程身份核验(如银行开户)等场景。

整套项目分为人脸活体识别数据集说明,模型开发和训练,模型边缘侧部署C++/Android等多个章节,本篇是项目《​​​​人脸活体识别》系列文章之《Android实现人脸眨眼 张嘴 点头 摇头识别》;为了方便后续模型工程化和Android平台部署,项目对活体识别模型进行轻量化,并提供Python/C++/Android多个版本;

整套活体识别系统,在普通Android手机上可以达到实时的检测效果,CPU(4线程)约40ms左右,GPU约30ms左右 ,基本满足业务的性能需求。准确率还挺高的,采用轻量级mobilenet_v2模型的人脸活体识别准确率也可以高达99.9661%左右,满足业务性能需求。

模型input sizeTest准确率
Mobilenet112×11299.9661
Resnet18112×11299.9322
MobileVit112×11299.9322

     

【尊重原创,转载请注明出处】https://blog.csdn.net/guyuealian/article/details/148774240

 【Android APP Demo体验】https://download.csdn.net/download/guyuealian/91133467


 更多人脸识别和活体识别文章,请参考:

  1. 人脸活体识别1:眨眼 张嘴 点头 摇头人脸数据集
  2. 人脸活体识别2:Pytorch实现人脸眨眼 张嘴 点头 摇头识别(含训练代码和数据集)
  3. 人脸活体识别3:C/C++实现人脸眨眼 张嘴 点头 摇头识别(可实时检测)
  4. 人脸活体识别4:Android实现人脸眨眼 张嘴 点头 摇头识别(可实时检测)
  5. 人脸识别2:InsightFace实现人脸识别Face Recognition(含源码下载)
  6. 人脸识别3:C/C++ InsightFace实现人脸识别Face Recognition(含源码)
  7. 人脸识别4:Android InsightFace实现人脸识别Face Recognition(含源码)

2.人脸活体识别方法

人脸活体识别的方法有很多,如基于人脸动作的活体识别​,基于红外的活体识别,基于深度的活体识别等等方法。

(1)基于人脸动作的检测​​

    要求用户配合完成随机指令动作(如眨眼、点头、张嘴、摇头等),通过计算机视觉算法(如光流法、关键点跟踪)分析动作的自然性和时序连贯性。

优点​​:实现简单,能有效抵御照片和静态视频攻击。​​

缺点​​:依赖用户配合,体验较差;可能被高仿动态视频(如Deepfake)欺骗。

(2)​​基于红外的活体识别​​

​​     利用红外摄像头捕捉人脸的红外反射特性或热辐射分布,如采用红外光谱分析​​,活体皮肤对特定波长红外光的吸收/反射模式与非活体不同。​​

优点​​:无需用户配合,可抵御照片、视频及部分3D面具攻击。

缺点​​:设备成本较高;受环境温度影响(如低温可能降低检测精度)。

(3)基于深度的活体识别​​

    通过3D深度摄像头(如结构光、ToF)获取人脸的三维几何信息(如鼻梁高度、曲面曲率),非活体(照片、屏幕)缺乏真实的深度结构。​​

优点​​:防御能力最强,可识别高级3D头套攻击。

​​缺点​​:硬件成本高,需专用3D传感器。

本项目实现方案是采用基于人脸动作的活体识别方法,即先采用通用的人脸检测模型,进行人脸检测定位人脸区域,然后按照一定规则裁剪人脸检测区域,再训练一个人脸活体识别分类器,完成人脸活体识别的任务。人脸动作主要包含:眨眼(闭眼)、张嘴、点头(低头)、摇头(侧脸)。


 3.人脸检测模型

本项目人脸检测训练代码请参考:https://github.com/Linzaer/Ultra-Light-Fast-Generic-Face-Detector-1MB 

这是一个基于SSD改进且轻量化后人脸检测模型,很slim,整个模型仅仅1.7M左右,在普通Android手机都可以实时检测。人脸检测方法在网上有一大堆现成的方法可以使用,完全可以不局限我这个方法。

当然可以基于YOLOv5训练一个人脸检测模型:人脸检测和行人检测2:YOLOv5实现人脸检测和行人检测(含数据集和训练代码)


 4. 活体识别模型

关于人脸活体识别模型训练,请参考《人脸活体识别2:Pytorch实现人脸眨眼 张嘴 点头 摇头识别(含训练代码和数据集)》

整套活体识别系统,在NCNN加速下,可以达到实时的检测效果,基本满足业务的性能需求。下表格给出MobilenetResnet18MobileVit模型识别的准确率:

模型input sizeTest准确率
Mobilenet112×11299.9661
Resnet18112×11299.9322
MobileVit112×11299.9322

模型训练完成后,需要将Pytorch模型转换为NCNN格式,转换方法请参考如下

考虑到端上硬件处理性能比较弱鸡,项目C++和Android部署仅使用Mobilenet模型。

(1) 将Pytorch模型转换ONNX模型

项目Python源码提供了转换工具,可实现将Pytorch的模型转换为ONNX模型文件,且文件会默认保存在Pytorch的模型文件同一目录下。

python libs/convertor/convert2onnx.py

(2) 将Pytorch模型转换为NCNN模型

你也可以一步到位,使用PNNX工具,直接将Pytorch模型直接转换为NCNN文件

python libs/convertor/convert2ncnn.py

NCNN转换工具说明,请参考:

  • https://github.com/Tencent/ncnn/wiki/use-ncnn-with-pytorch-or-onnx
  •  将ONNX模型转换为NCNN模型,请参考NCNN官方说明:GitHub - Tencent/ncnn: ncnn is a high-performance neural network inference framework optimized for the mobile platform

5. 活体识别Android部署

项目实现了Android版本的活体识别,模型部署框架采用NCNN,支持多线程CPU和GPU加速推理,在普通手机上可以实时处理。

(1) Android部署NCNN模型

模型推理采用NCNN,图像处理和Android核心算法部分均采用C++实现,上层Java通过JNI接口调用C++算法。

如果你想在这个Android Demo部署你自己训练的模型,你可将训练好的Pytorch模型转换ONNX ,再转换成NCNN模型,然后把原始的模型替换成你自己的TNCNN模型即可。

package com.cv.dl.model;import android.graphics.Bitmap;public class Detector {static {System.loadLibrary("cvdl-lib");}/**** 初始化检测模型* @param root:模型文件的根目录,放在assets文件夹下* @param det_model: 检测模型(不含后缀名)* @param rec_model: 识别模型(不含后缀名)* @param model_type:模型类型* @param num_thread:开启线程数* @param useGPU:是否开启GPU进行加速*/public static native void init(String root, String det_model, String rec_model, int model_type, int num_thread, boolean useGPU);/**** 进行检测(用于静态图)* @param bitmap 图像(bitmap),ARGB_8888格式* @param score_thresh:置信度阈值* @param iou_thresh:  IOU阈值* @return*/public static native FrameInfo[] detect(Bitmap bitmap, float score_thresh, float iou_thresh);}

JNI接口

#include <jni.h>
#include <string>
#include <fstream>
#include "src/classifier.h"
#include "src/object_detection.h"
#include "src/Types.h"
#include "debug.h"
#include "android_utils.h"
#include "opencv2/opencv.hpp"
#include "file_utils.h"using namespace dl;
using namespace vision;static ObjectDetection *detector = nullptr;
static Classifier *recognize = nullptr;JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {return JNI_VERSION_1_6;
}JNIEXPORT void JNI_OnUnload(JavaVM *vm, void *reserved) {}extern "C"
JNIEXPORT void JNICALL
Java_com_cv_dl_model_Detector_init(JNIEnv *env,jclass clazz,jstring root,jstring det_model,jstring rec_model,jint model_type,jint num_thread,jboolean use_gpu) {if (detector != nullptr) {delete detector;detector = nullptr;}std::string parent = env->GetStringUTFChars(root, 0);std::string det_model_ = env->GetStringUTFChars(det_model, 0);std::string rec_model_ = env->GetStringUTFChars(rec_model, 0);string det_pam_file = path_joint(parent, det_model_ + ".param");string det_bin_file = path_joint(parent, det_model_ + ".bin");string rec_pam_file = path_joint(parent, rec_model_ + ".param");string rec_bin_file = path_joint(parent, rec_model_ + ".bin");DeviceType device = use_gpu ? GPU : CPU;LOGW("parent         : %s", parent.c_str());LOGW("useGPU         : %d", use_gpu);LOGW("device_type    : %d", device);LOGW("model_type     : %d", model_type);LOGW("num_thread     : %d", num_thread);DetParam det_param = MODEL_TYPE[model_type];//模型参数detector = new ObjectDetection(det_bin_file, det_pam_file, det_param, num_thread, device, -1);RecParam rec_param = REC_MODEL;recognize = new Classifier(rec_bin_file, rec_pam_file, rec_param, num_thread, device);}extern "C"
JNIEXPORT jobjectArray JNICALL
Java_com_cv_dl_model_Detector_detect(JNIEnv *env, jclass clazz, jobject bitmap,jfloat score_thresh, jfloat iou_thresh) {cv::Mat bgr;BitmapToMatrix(env, bitmap, bgr);int src_h = bgr.rows;int src_w = bgr.cols;// 检测区域为整张图片的大小FrameInfo resultInfo;// 开始检测detector->detect(bgr, &resultInfo, score_thresh, iou_thresh);recognize->detect(bgr, &resultInfo);int nums = resultInfo.info.size();LOGW("image is (%d,%d,%d),score_thresh=%3.3f, iou_thresh=%3.3f, object nums: %d\n", bgr.cols,bgr.rows, bgr.channels(), score_thresh, iou_thresh, nums);auto BoxInfo = env->FindClass("com/cv/dl/model/FrameInfo");auto init_id = env->GetMethodID(BoxInfo, "<init>", "()V");auto box_id = env->GetMethodID(BoxInfo, "addBox", "(FFFFIFLjava/lang/String;)V");auto ky_id = env->GetMethodID(BoxInfo, "addKeyPoint", "(FFF)V");auto po_id = env->GetMethodID(BoxInfo, "addPolygon", "(FFFI)V");jobjectArray ret = env->NewObjectArray(resultInfo.info.size(), BoxInfo, nullptr);for (int i = 0; i < nums; ++i) {auto info = resultInfo.info[i];env->PushLocalFrame(1);//jobject obj = env->AllocObject(BoxInfo);jobject obj = env->NewObject(BoxInfo, init_id);// set bbox//LOGW("rect:[%f,%f,%f,%f] label:%d,score:%f \n", info.rect.x,info.rect.y, info.rect.w, info.rect.h, 0, 1.0f);jstring name = env->NewStringUTF(info.name.c_str());env->CallVoidMethod(obj, box_id, info.x1, info.y1, info.x2 - info.x1, info.y2 - info.y1,info.category.label, info.category.score, name);// set keypointfor (const auto &kps: info.points) {//LOGW("point:[%f,%f] score:%f \n", lm.point.x, lm.point.y, lm.score);env->CallVoidMethod(obj, ky_id, (float) kps.x, (float) kps.y, 1.0f);}// set contours// LOGW("jni contours.size=%d\n", info.segInfo.contours.size());for (int group = 0; group < info.segInfo.contours.size(); ++group) {for (const auto &kps: info.segInfo.contours.at(group)) {//LOGW("jni contours group=%d,point:[%f,%f]\n", group, (float)kps.x, (float)kps.y);env->CallVoidMethod(obj, po_id, (float) kps.x, (float) kps.y, 1.0f, group);}}obj = env->PopLocalFrame(obj);env->SetObjectArrayElement(ret, i, obj);}return ret;
}

(2) Android编译异常解决方法

参考解决方法:Android项目常见问题解决办法


6.活体识别效果(Android版本)

活体识别Android APP在普通Android手机上可以达到实时的检测和识别效果,CPU(4线程)约40ms左右,GPU约30ms左右 ,基本满足业务的性能需求。

 【Android APP Demo体验】https://download.csdn.net/download/guyuealian/91133467

     


7. 项目Android源码下载

  【Android APP Demo体验】https://download.csdn.net/download/guyuealian/91133467

如需下载项目源码,请WX关注【AI吃大瓜】,回复【活体识别】即可下载

项目资源内容包含:

  1. 提供轻量化人脸检测模型
  2. 提供轻量化人脸活体识别模型(Mobilenet),支持眨眼(闭眼)、张嘴、点头(低头)、摇头(侧脸)动作识别,识别准确率可以高达99.9661%左右。
  3. 提供整套人脸活体识别Android Demo项目源码
  4. Android Demo源码可用于二次开发
  5. Android Demo在普通手机CPU/GPU上可以实时检测,CPU约40ms,GPU约30ms左右
  6. Android Demo支持图片、视频和摄像头测试
  7. 所有依赖库都已经配置好,可直接build运行,若运行出现异常,请参考Android项目常见问题解决办法
http://www.dtcms.com/a/265081.html

相关文章:

  • ESP32-s3摄像头驱动开发实战:从零搭建实时图像显示系统
  • sklearn机器学习概述及API详细使用指南
  • LeetCode Hot 100 滑动窗口 【Java和Golang解法】
  • 90.xilinx复位低电平(一般使用低电平复位)
  • 单链表和双向链表
  • python自动化运维
  • Redis基础(2):Redis常见命令
  • 多模态DeepSeek大模型的本地化部署
  • Colormind:优秀大模型赋能国产求解器,打造自主可控建模平台
  • 数学建模_拟合
  • 【Erdas实验教程】026:遥感图像辐射增强(去条带处理)
  • IDEA2025 Version Control 窗口 local changes显示
  • JavaScript 性能优化实战:减少 DOM 操作引发的重排与重绘
  • 操作系统考试大题-处理机调度算法-详解-2
  • 代码实现特殊的字段的基本功能
  • 用Rust编写的开源支付解决方案——Hyperswitch
  • springboot集成达梦数据库,取消MySQL数据库,解决问题和冲突
  • nohup java -jar 命令启动jar包,项目仍然会挂掉或者停止运行的解决方案
  • C++——手撕智能指针、单例模式、线程池、String
  • Vue + RuoYi 前后端分离入门手册
  • [深度学习环境踩坑记录]ubuntu22.04安装RTX3060驱动,黑屏、桌面只有壁纸和鼠标,一顿折腾
  • javaWeb02-Tomcat
  • java.sql.SQLSyntaxErrorException: Unknown column ‘user_name‘ in ‘field list‘
  • YOLOv11剪枝与量化(一)模型压缩的必要性
  • Qt写入excel
  • 整流电路Multisim电路仿真实验汇总——硬件工程师笔记
  • Rust实现FasterR-CNN目标检测全流程
  • 教程:国内如何免费用Claude4+GPT4o生成高质量科研绘图
  • vue动态绑定样式
  • Kalibr解毒填坑(一):相机标定失败