人脸活体识别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 size | Test准确率 |
Mobilenet | 112×112 | 99.9661 |
Resnet18 | 112×112 | 99.9322 |
MobileVit | 112×112 | 99.9322 |
【尊重原创,转载请注明出处】https://blog.csdn.net/guyuealian/article/details/148774240
【Android APP Demo体验】https://download.csdn.net/download/guyuealian/91133467
更多人脸识别和活体识别文章,请参考:
- 人脸活体识别1:眨眼 张嘴 点头 摇头人脸数据集
- 人脸活体识别2:Pytorch实现人脸眨眼 张嘴 点头 摇头识别(含训练代码和数据集)
- 人脸活体识别3:C/C++实现人脸眨眼 张嘴 点头 摇头识别(可实时检测)
- 人脸活体识别4:Android实现人脸眨眼 张嘴 点头 摇头识别(可实时检测)
- 人脸识别2:InsightFace实现人脸识别Face Recognition(含源码下载)
- 人脸识别3:C/C++ InsightFace实现人脸识别Face Recognition(含源码)
- 人脸识别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加速下,可以达到实时的检测效果,基本满足业务的性能需求。下表格给出Mobilenet,Resnet18和MobileVit模型识别的准确率:
模型 | input size | Test准确率 |
Mobilenet | 112×112 | 99.9661 |
Resnet18 | 112×112 | 99.9322 |
MobileVit | 112×112 | 99.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吃大瓜】,回复【活体识别】即可下载
项目资源内容包含:
- 提供轻量化人脸检测模型
- 提供轻量化人脸活体识别模型(Mobilenet),支持眨眼(闭眼)、张嘴、点头(低头)、摇头(侧脸)动作识别,识别准确率可以高达99.9661%左右。
- 提供整套人脸活体识别Android Demo项目源码
- Android Demo源码可用于二次开发
- Android Demo在普通手机CPU/GPU上可以实时检测,CPU约40ms,GPU约30ms左右
- Android Demo支持图片、视频和摄像头测试
- 所有依赖库都已经配置好,可直接build运行,若运行出现异常,请参考Android项目常见问题解决办法