由于个人的兴趣,自己写了一个人脸识别、对比的demo,这个demo中用到的人脸识别不是Android SDK中自带的FaceDetector而是使用的Face++提供的人脸识别和人脸探测的API,这个demo不仅实现了人脸探测和人脸对比,而且实现的效果是比较绚丽的,先给大家看一下效果图。
  
  

**

点击下载

**

一、基础知识

  Face++人脸识别的三个核心概念:Image,Face和FaceId。
  
  Image指用户或应用程序给Face++API提供的图片,以供后续检测/识别使用。用户可以通过制定的url或在程序中上传(通过HTTP POST提交图片的二进制文件)提供Image。

  Face指Image中检测出得人脸。一张Image中可能包含多个Face,但是在我写的Demo中只用到一个Face。
  FaceId指上传到Face++服务器后,服务器返回的人脸标示符,在后面的对比中可以直接使用FaceId进行对比。

  属性动画这里使用的第三方的库:NineOldAndroids。NineOldAndroids是一个乡下兼容的动画库,主要的使低于API 11的系统也能够使用View的属性动画。以下是官网的描述:

Android library for using the Honeycomb (Android 3.0) animation API on all versions of the platform back to 1.0!Animation prior to Honeycomb was very limited in what it could accomplish so in Android 3.x a new API was written. With only a change in imports, we are able to use a large subset of the new-style animation with exactly the same API.

  View的属性动画在Android API 11及其以后才支持,该库的作用就是让API 11以下的系统也能够正常的使用属性动画。它的雷鸣、用法与官方都一样,只是包名不一样。使用该库,你就可以在API版本很低的情况下也能够使用各种属性动画,让你的应用更加有动感、平滑。官方地址:NineOldAndroids。

  EventBus指的是一个发布/订阅的时间总线,EventBus包含4个成分:发布者,订阅者,事件,总线。4者之间的关系大体如下:

  订阅者可以订阅多个事件,发送者可以发布任何事件,发布者同时也可以是订阅者。使用EventBus的优点是:独立出一个发布订阅模块,调用者可以通过使用这个模块,屏蔽一些线程切换的问题,简单地实现发布订阅功能。另个一优点是解耦合,是类之间的耦合降低。
  xUtils的BitmapUtils,它替我们考虑所有图片加载的情况,大体来说就是使用了三级缓存来加载网络图片和本地图片,让我们的程序不会因为图片造成内存溢出的BUG。

二、人脸识别、比对的流程

ps:四张作为对比样本的图片,是从网络上抓取下来的,当然也可以是从本地去拿,这里偷懒了,没有做。
1、首先选取一张照片(从手机相册或者拍摄得到),然后点击开始比对。
2、使用FaceDetecter(线上或者离线)API分析bitmap,将探测到的人脸存储到Face中。
3、根据Face中的数据,将人脸部分提取出来,然后逐一跟之前的四张图片进行对比。
4、将对比的结果显示出来。

三、项目讲解

1、项目的机构

虽然结构稍微有点复杂,但是很清晰,有四个包,分别是:适配器、Event数据类型、activity、使用到的一些工具以及一些自定义的view(主要是用来对图片进行动画时使用到的)。

2、主要代码分析
因为本篇主要讲解的是人脸识别,那FacePlusPlusHelper肯定是最重要的,我把Face++的API中的几个我使用的方法封装的这个类中。

/*** Created by Android Studio. author: liyachao Date: 15/11/7 Time: 14:32*/
public class FacePlusPlusHelper {/*** 这里最好换成自己的apikey和apiSecret*/private static final String apiKey = "000feb0633099eb6167e7ad3270b5338";private static final String apiSecret = "pB_jtq-piOg9euRbQysSP65FlfcyGMmn";public static final int METHOD_ONE = 50001;public static final int METHOD_TWO = 50002;public static final int METHOD_THREE = 50003;private FaceDetecter detecter;private Context context;private Handler detectHandler;private HandlerThread detectThread;private EventBean bean;public FacePlusPlusHelper(Context context) {this.context = context;detectThread = new HandlerThread("detect");detectThread.start();detectHandler = new Handler(detectThread.getLooper());bean = new EventBean();if (!MyUtils.isCPUInfo64()) {detecter = new FaceDetecter();detecter.init(context, apiKey);}}public void stopThread() {detectHandler.removeCallbacksAndMessages(null);}/*** 探测选取的图片是否有脸** @param bitmap*/public void faceDetect(final Bitmap bitmap) {detectHandler.post(new Runnable() {@Overridepublic void run() {if (detecter == null) {HttpRequests httpRequests = new HttpRequests(apiKey, apiSecret, true, false);byte[] bytes = MyUtils.bitmapToBytes(bitmap);PostParameters parameters = new PostParameters();parameters.setImg(bytes);try {JSONObject rst = httpRequests.detectionDetect(new PostParameters().setImg(bytes));int count = rst.getJSONArray("face").length();if (count == 0) {bean.setIsCorrect(false);bean.setMode(METHOD_ONE);EventBus.getDefault().post(bean);} else {float x = (float) rst.getJSONArray("face").getJSONObject(0).getJSONObject("position").getJSONObject("center").getDouble("x");float y = (float) rst.getJSONArray("face").getJSONObject(0).getJSONObject("position").getJSONObject("center").getDouble("y");//get face sizefloat w = (float) rst.getJSONArray("face").getJSONObject(0).getJSONObject("position").getDouble("width") * 0.5f;float h = (float) rst.getJSONArray("face").getJSONObject(0).getJSONObject("position").getDouble("height") * 0.5f;Face face = new Face();face.left = (x - w) / 100f;face.right = (x + w) / 100f;face.top = (y - h) / 100f;face.bottom = (y + h) / 100f;bean.setIsCorrect(true);bean.setFace(face);bean.setMode(METHOD_ONE);EventBus.getDefault().post(bean);}} catch (Exception e) {e.printStackTrace();}} else {Log.i("double", "bitmap is null11: " + (detecter.findFaces(bitmap) == null));final Face[] faceinfo = detecter.findFaces(bitmap);// 进行人脸检测if (faceinfo == null) {bean.setIsCorrect(false);bean.setMode(METHOD_ONE);EventBus.getDefault().post(bean);} else {bean.setIsCorrect(true);bean.setFace(faceinfo[0]);bean.setMode(METHOD_ONE);EventBus.getDefault().post(bean);}}}});}/*** 得到对比图片的faceid** @param bitmap 需要对比的图片*/public void getFaceId(final Bitmap bitmap) {detectHandler.post(new Runnable() {@Overridepublic void run() {HttpRequests httpRequests = new HttpRequests(apiKey, apiSecret, true, false);byte[] bytes = MyUtils.bitmapToBytes(bitmap);try {PostParameters parameters = new PostParameters();parameters.setImg(bytes);JSONObject rst = httpRequests.detectionDetect(new PostParameters().setImg(bytes));Log.i("double", "getFaceId: " + rst.toString());int count = rst.getJSONArray("face").length();if (count == 0) {bean.setIsCorrect(false);bean.setMode(METHOD_TWO);EventBus.getDefault().post(bean);} else {String detectFaceId = rst.getJSONArray("face").getJSONObject(0).getString("face_id");bean.setIsCorrect(true);bean.setFaceId(detectFaceId);bean.setMode(METHOD_TWO);EventBus.getDefault().post(bean);}} catch (Exception e) {bean.setIsCorrect(false);bean.setMode(METHOD_TWO);bean.setDescribe(e.toString());EventBus.getDefault().post(bean);e.printStackTrace();}}});}/*** 对比两个图片中脸部的相似度** @param faceId1 已经得到的Faceid* @param url     需要对比的url*/public void comparisonFace(final String faceId1, final String url) {detectHandler.post(new Runnable() {@Overridepublic void run() {HttpRequests httpRequests = new HttpRequests(apiKey, apiSecret, true, false);try {long timeStart = System.currentTimeMillis();JSONObject rst = httpRequests.detectionDetect(new PostParameters().setUrl(url));int count = rst.getJSONArray("face").length();if (count == 0) {bean.setIsCorrect(false);bean.setMode(METHOD_THREE);bean.setDescribe("没有探测到脸");EventBus.getDefault().post(bean);} else {String faceId2 = rst.getJSONArray("face").getJSONObject(0).getString("face_id");PostParameters parameters = new PostParameters();parameters.addAttribute("face_id1", faceId1);parameters.addAttribute("face_id2", faceId2);JSONObject result = httpRequests.recognitionCompare(parameters);if (result == null || result.toString().equals("")) {bean.setIsCorrect(false);bean.setMode(METHOD_THREE);EventBus.getDefault().post(bean);} else {double similarity = result.getDouble("similarity");long timeEnd = System.currentTimeMillis();if (timeEnd - timeStart < 2000) {Thread.sleep(2000 - (timeEnd - timeStart));}bean.setIsCorrect(true);bean.setDescribe(similarity + "");bean.setMode(METHOD_THREE);EventBus.getDefault().post(bean);}}} catch (Exception e) {bean.setIsCorrect(false);bean.setMode(METHOD_THREE);bean.setDescribe(e.toString());EventBus.getDefault().post(bean);e.printStackTrace();}}});}/*** 释放引擎*/public void release() {if (detecter != null)detecter.release(context);}}

  首先提取一些需要用到的常量,因为整个类中主要有三个方法:探测脸部,请求FaceId,脸部对比,所以需要用三种类型代表不同的方法,方便在EventBus中做区分。
  22~23行代码初始化了一个线程,用来请求网络(因为请求网络是耗时的操作,因此需要开启线程,不能在UI线程中直接请求,否则会造成程序崩溃),初始化了FaceDetecter(Face++的离线包),大家可以看到我这里做了一个手机CPU是否为64位的判断,因为Face++离线包中没有做64位的so,所以如果手机64位的还直接调用Face++的离线包,会有Bug。如果手机是64位,则直接请求网络来探测脸部。
  剩下的三个方法都在程序中做了注释,大家应该可以看懂。
  大家可以看到,在请求网络成功时,我这里没有使用到回调,而是使用的EventBus,和回调是一个效果。
  剩下的代码,就不一一讲解了,项目中的代码不难,如果感兴趣的朋友可以和我讨论。

四、总结

  这个Demo中运用到的知识点还是比较多的,很多地方都没有讲到,不过我相信对于大家来说,都应该能够看懂,如果有什么不清楚的地方,可以留言,互相讨论。
  如果其中有什么不对或者不足的地方,希望大家能提出来。

Android人脸对比相关推荐

  1. Android手把手教你使用阿里云接口实现人脸定位、人脸检测、人脸对比功能。

    前言 现如今,人工智能越来越火,以至于我们必须了解和掌握它,今天我们就来结合阿里云的接口来实现人脸定位,人脸检测等功能. 废话不多说,先上效果图: 随便在网上找了三张图片进行检测,检测结果只显示了每一 ...

  2. Android 人脸照片对比,人脸对比

    1.首先在百度云平台,注册账号,并且进行企业验证 https://console.bce.baidu.com/#/index/overview 2.进入人脸识别主页,创建应用 3.创建SDK授权应用 ...

  3. android 人脸 sdk,Android 基于人脸识别 SDK使用总结

    体验了虹软 开放人脸识别的SDK引擎(免费的哦),刚好有Android版的.下面来说说Android版的SDK使用心得: ArcFace 虹软人脸认知引擎简介 目前开放的版本有人脸比对(1:1)和人脸 ...

  4. Android人脸比对技术

    安卓人脸对比识别技术,人脸活体检测识别技术产品背景 随着深度学习方法的应用,安卓人脸对比识别技术技术的识别率已经得到质的提升,目前我司的安卓人脸对比识别技术率已经达到99%.安卓人脸对比识别技术技术与 ...

  5. 基于android系统的人脸检测系统设计 论文,基于Android人脸识别系统设计与实现.doc...

    基于Android人脸识别系统设计与实现 基于Android人脸识别系统设计与实现 摘要:人脸识别是公共安全领域的研究重点.随着移动互联网的快速发展,移动式终端人脸识别应用日益广泛.探讨人脸识别在An ...

  6. Android 人脸识别

    Android人脸识别技术,可以参考下面的网站. http://www.faceplusplus.com.cn/ 本项目使用的就是该网站的api. 项目具体使用的技术代码 /*** 用来压缩图片的方法 ...

  7. opencv 训练人脸对比_【项目案例python与人脸识别】基于OpenCV开源计算机视觉库的人脸识别之python实现...

    " 本项目是一个基于OpenCV开源库使用python语言程序实现人脸检测的项目,该项目将从[项目基础知识](即人脸识别的基本原理).[项目实践](人脸识别所需要的具体步骤及其python程 ...

  8. [计算机视觉]人脸应用:人脸检测、人脸对比、五官检测、眨眼检测、活体检测、疲劳检测

    人脸应用在计算机视觉体系中占很大一块,在深度学习火起来之前,基于传统机器学习的人脸应用就已经很成熟了,有很多商用应用场景.本文用一个可以实际运行的Demo来说明人脸应用中常见的技术概念,包含'人脸检测 ...

  9. python人脸对比相似度_python人脸对比

    import sys import ssl from urllib import request,parse # client_id 为官网获取的AK, client_secret 为官网获取的SK ...

最新文章

  1. flask貌似html文件里只能用flask指定的路径格式,css文件里则可用相对路径
  2. python网络编程知识点_python 网络编程要点
  3. oracle 实现ID自增
  4. webmin mysql_MySQL+Webmin轻松创建数据库
  5. 记录学习——算法时间复杂度求法
  6. java lambda 原理_Java Lambda表达式原理及多线程实现
  7. 廖雪峰Python 2.X 教程
  8. 【约束优先级问题二】动态高度cell
  9. 「技术架构」技术风险管理权威指南
  10. ERP与MES的区别与联系
  11. Secure CRT 乱码 问题
  12. 微信小程序中使用阿里巴巴字体图标
  13. 计算机教研组工作计划表,2017学年第一学期信息技术教研组工作计划
  14. 微信小程序悬浮按钮-点击传参
  15. SpringBoot学习-用户注册登录
  16. 海底捞只要“面子”,不要“里子”?
  17. OV4689 和IMX179的dts中节点的区别,以及dts节点的注释说明,基于rv1108平台
  18. 高德离线地图vue-amap的api文档(2):创建地图,撒点等等
  19. CSS的选择器和常用样式(id,class,组合,字体,背景,宽度,高度,颜色等CSS样式)
  20. 计算机毕设(附源码)JAVA-SSM基于web的烟草售卖系统

热门文章

  1. 唯品会 测试岗(9.15)
  2. Python的输入输出(来自菜鸟教程)
  3. 保护 IT 基础设施的多层安全技术-扩展检测与响应 (XDR)
  4. Taming Transformers for High-Resolution Image Synthesis 论文阅读
  5. flink forward Asia 2020线上峰会
  6. “软硬兼施”:长沙软件业再出发
  7. Acunetix 登录凭证无效
  8. python抓取腾讯视频弹幕_Python爬虫练习:腾讯视频弹幕数据采集
  9. Air Jordan XIV Retro(乔丹14代复刻篮球鞋)实战
  10. matlab求解方程