这个demo是我去年毕业刚工作的时候要搞人脸识别的时候搞的。好奇其中的原理于是就去github上搞了个MTCNN+MobileFaceNet的demo(没记错的话是这个),刚拿来的时候是只有1:1比对和检测的,然后我加入了人脸对齐、1:N识别和红外活体检测。但是有个问题,红外活体检测只是针对我自己的设备的,因为数据集是采录自我的设备,不保证在其他设备上识别准确。

这里的前段推断框架用的是腾讯的NCNN,图像处理用的OpenCV4Android 3.4.3,部分工程结构参考了虹软的方式。我觉得虹软这种直接把人脸特征值文件保存下来的方式在对于随时更新用户人脸信息上是非常方便的,只需要下载对应的特征值文件就可以了,而且也可以很方便的进行管理。

GitHub地址:https://github.com/YuGongCharley/MTCNN_facenet_Android.git

---------------------------------------------------------------效果---------------------------------------------------------------

1:1比对

1:N静态识别

近红外活体检测

---------------------------------------------------------------准备工作---------------------------------------------------------------

这个demo里用到了ndk,我用的是16b的ndk包,>16b的版本可能会有问题,所以推荐使用16b的包,没有的同学直接百度ndk下载就行;

另外还需要CMake,这个在Android Studio里直接勾选安装就行:

---------------------------------------------------------------正文---------------------------------------------------------------

大致的流程是:检测人脸->得到人脸坐标和五官坐标->人脸对齐->取出特征值->和其他人脸的特征值做比对->得出相似度

首先应用启动时需要对用到的模型进行初始化:

try {copyBigDataToSD("det1.bin");  //mtcnn人脸检测模型copyBigDataToSD("det2.bin");copyBigDataToSD("det3.bin");copyBigDataToSD("det1.param");copyBigDataToSD("det2.param");copyBigDataToSD("det3.param");copyBigDataToSD("recognition1.bin");  //facenet人脸特征值模型copyBigDataToSD("recognition1.param");copyBigDataToSD("nir_nfd_gn7.bin");   //googlenet 近红外活体检测模型copyBigDataToSD("nir_nfd_gn7.param");} catch (IOException e) {e.printStackTrace();}//TODO; model initFile sdDir = Environment.getExternalStorageDirectory();//get directoryString sdPath = sdDir.toString() + "/facem/";FaceEngine.FaceModelInit(sdPath);  //模型初始化 传入根目录路径
//TODO: 将模型考入SD卡public void copyBigDataToSD(String strOutFileName) throws IOException {Log.i(TAG, "start copy file " + strOutFileName);File sdDir = Environment.getExternalStorageDirectory();//get directoryFile file = new File(sdDir.toString()+"/facem/");if (!file.exists()) {file.mkdir();}String tmpFile = sdDir.toString()+"/facem/" + strOutFileName;File f = new File(tmpFile);if (f.exists()) {Log.i(TAG, "file exists " + strOutFileName);return;}InputStream myInput;java.io.OutputStream myOutput = new FileOutputStream(sdDir.toString()+"/facem/"+ strOutFileName);myInput = this.getAssets().open(strOutFileName);byte[] buffer = new byte[1024];int length = myInput.read(buffer);while (length > 0) {myOutput.write(buffer, 0, length);length = myInput.read(buffer);}myOutput.flush();myInput.close();myOutput.close();Log.i(TAG, "end copy file " + strOutFileName);}

这里我用copyBigDataToSD方法将这些模型文件拷贝到本地,然后通过调用本地模型文件初始化模型。

第一次模型初始化成功后可能会有检测不到的情况,再来一次就好了。

  • 人脸检测:

人脸检测分为最大人脸检测(MaxFaceDetect)和多人脸检测(FaceDetect)两个方法:

//TODO: 人脸检测
public static native int[] FaceDetect(byte[] imageData, int imageWidth, int imageHeight, int imageChannel);//TODO: 检测最大脸
public static native int[] MaxFaceDetect(byte[] imageData, int imageWidth, int imageHeight, int imageChannel);

这里是将图像的每一个像素提取出来转为byte数组传入,jni里会将它转为ncnn框架需要的ncnn:Mat类型。我之后还试过直接把Bitmap直接传入jni做转换也是可以的,这次没有用,后面有时间可以加上。人脸检测返回的是人脸位置和双眼、鼻、两嘴角共五个点的位置,我们需要这五个点来对人脸做截取和正脸对齐的操作。

  • 人脸对齐:

人脸对齐由于需要将人脸图截取对齐后再传回java部分,这里就直接用传递内存地址的方式直接对内存里的图片做修改,同时还需要传入人脸检测返回的对应的人脸坐标。

    //TODO: 人脸对齐 正脸public static native String FaceAlign(long frame, float[] landmarks);

由于没思路我就去找了找,还真让我找着了(https://github.com/WilliamEricCheung/FaceDetector)。人脸对齐这里作者充分发挥了OpenCV的能力,通过各种数学计算对人脸图像进行截取和矫正,说实话,这部分的算法我看的有点懵,到现在还在研究中,等研究明白了会写一篇文章说一下我的理解,也希望有大神可以指点一下,谢谢。

  • 人脸识别

人脸识别分为1:1比对和1:N比对两种方式:

//TODO: 人脸比对public static native double FaceCompare(byte[] faceData1, int w1, int h1, byte[] faceDate2, int w2, int h2);//TODO: 人脸识别public static native String Recognize(byte[] faceData, int w, int h, String featurePath, double threshold);

1:1比对,分别提取两幅人脸图的人脸特征值通过KNN、K近邻域或称为欧式距离算法计算两幅人脸的相似度

1:N比对,基本原理和1:1比对是一样的,一副主要的人脸和数据库中的其他人脸特征值分别比较,取出比值最大的那个人脸信息返回输出。

  • 人脸添加/注册

这个相对来说不是很复杂,其实除了不需要比对其他步骤和人脸比对是一样的。只不过提取出人脸特征值后作为二进制文件保存到一个指定路径下,而且这个路径保证和1:N识别制定的路径是一个路径就行:

//TODO: 添加人脸public static native boolean AddFace(byte[] faceData, int w, int h, String featurePath, String id);

---------------------------------------------------------------结尾(一些废话)---------------------------------------------------------------

这个demo其实是我当时拿来熟悉整个流程和思路以及验证一些想法的,而且因为是刚开始工作时写的,里面有一些的方法在多个类里都有重复,这一点现在想想应该都归到一个静态的工具类里。现在再回来改他可能要花上一些功夫稍微重构一下了,所以只好慢慢来。

这个demo给我最大的帮助我想可能不是多么复杂深奥的算法,也不是人脸识别的模型要怎么训练。而是在刚工作的时候,对整体项目的认知还没有的时候了解到了一个相对完整的安卓ndk项目开发步骤,以及jni开发的步骤和思路。在这个demo里我学会了jni开发;学会了c++多线程以及jni多线程回调;学会使用cmake编译动态库和静态库(.so和.a),这些是我之前在学校上课和做练习一点都没有接触过的。甚至在这个demo之后成功编写了linux平台的人脸注册程序供公司小程序进行调用,用来接收上传的人脸图片并注册,这个程序从2019年7月到现在一直在稳定运行。

Android端基于MTCNN和mobilefacenet的人脸识别相关推荐

  1. 基于MTCNN和Arc-Loss的人脸识别(详细版)

    文章目录 一.人脸识别介绍 1.1 发展历史 1.2 什么是人脸识别? 二:人脸识别步骤 2.1 人脸侦测 2.2 特征提取 2.3 特征对比 三:人脸识别难点 四:人脸检测原理 五:YOLO和MTC ...

  2. 【项目实战】Python基于MTCNN+FaceNet+SVM进行人脸识别项目实战

    说明:这是一个机器学习实战项目(附带数据+代码+文档+视频讲解),如需数据+代码+文档+视频讲解可以直接到文章最后获取. 1.项目背景 人脸识别的现代研究始于20世纪60年代末.在近20年,随着计算机 ...

  3. 基于MTCNN卷积神经网络的人脸识别

    该文作者开源了测试代码,源代码可以在我之前的文章中或者Github中去下载,我对源代码的数据输入部分做了一些改动以更方便的实现人脸检测,即将  facedetect_mtcnn.py主函数文件更改为如 ...

  4. Android基于虹软SDK实现离线人脸识别

    一.需求 Android端实现离线人脸识别功能,即对比两张人脸是否是同一个人. 二.解决方案 选用虹软人脸识别SDK来实现人脸特征数据比对. 三.步骤 1. 打开虹软开发者中心 开发者中心 2. 新建 ...

  5. android 混音 源码,FFmpegAndroid android 端基于 FFmpeg 实现音频剪切、拼接、转码、混音、编解码;视频剪切、水印、截图、转码、编 @codeKK c开源站...

    android 端基于 FFmpeg 库的使用 添加编译 ffmpeg.shine.mp3lame.x264 源码的参考脚本 目前音视频相关处理: 音频剪切.拼接 音频混音 音频转码 音视频合成 音频 ...

  6. 【毕业设计_课程设计】基于mtcnn的实时高精度人脸检查算法实现

    文章目录 0 前言 1 简介 2 模型理解 3 环境说明 4 代码介绍 5 下载数据 6 运行 7 效果展示 8 最后 0 前言 基于mtcnn的实时高精度人脸检查算法实现 提示:适合用于课程设计或毕 ...

  7. 基于SeetaFace+VS2017+Qt的人脸识别

    1 目的 目前计算机视觉技术已经比较成熟,相关的开源项目与算法很多,可以将这些开源算法进行整合,进而做成一个小项目,以供日后学习与研究.本实验主要将利用人脸识别开源项目SeetaFace,结合使用Op ...

  8. C语言实现基于翔云平台的人脸识别demo2(树莓派)

    C语言实现基于翔云平台的人脸识别demo2(树莓派3B) 实现目标 树莓派安装mjpg-streamer 在树莓派下依次执行以下指令 修改start.sh文件(用来开启摄像头进行监控) A:树莓派摄像 ...

  9. 基于深度神经网络的遮挡人脸识别算法的研究(小白初学)

    基于深度神经网络的遮挡人脸识别算法的研究(小白初学) 研究背景 在自然条件下人脸面部的光照变化.角度变化.表情变化以及存在遮挡物,使得采集到的人脸图像存在人脸特征的损失.因此研究遮挡人脸识别算法提高识 ...

最新文章

  1. spring 中读取properties 文件
  2. DL之RNN:循环神经网络RNN的简介、应用、经典案例之详细攻略
  3. OpenFeign组件的使用(使用nacos作为服务注册中心)
  4. leetcode 289. Game of Life | 289. 生命游戏(Java)
  5. vs2010本地调试打不开网页
  6. PWM信号作用示例——调节台灯亮度
  7. Linux 系统中 Redis 的安装及其使用
  8. html怎么用小小的图片铺满作为背景,多种背景图片随机切换的应用
  9. HelloDjango 启动!免费带你学Django全栈!
  10. php 运行thinkphp,thinkPHP cli命令行运行PHP代码
  11. shell换行合并多个文件_shell两个文件去重的多种姿势
  12. CH582 BLE 5.0 使用 LE Coded 广播和连接
  13. python代码图片头像_Python爬取堆糖网优美古风头像(附源码)
  14. java 里面 todo 作用
  15. Torah RVP Claiming Tutorial
  16. kpi绩效考核流程图_KPI绩效考核的步骤
  17. 还有比元宇宙更牛的商业模式吗?
  18. 2023Java 并发编程面试题
  19. PyQT之多窗口切换
  20. NDIS开发[网络驱动开发] NDIS开发1

热门文章

  1. wsimport不是内部或外部命令
  2. java版-wifi无线网络搭建
  3. VSCode 中 git 如何新建分支
  4. 【开店宝典】Lazada怎么入驻?
  5. 双击鼠标HOOK学习
  6. 提示工程之提示介绍【一】
  7. 3d建模师会因为年龄大而淘汰吗?没有自学能力,入行都是问题!
  8. 将我理解的web3.0讲给你听
  9. C++ 内存分配与内存对齐
  10. Glide Demo及自定义