原理: 通过android 系统自带的谷歌人脸识别获取响应的图片,保存在本地,然后跟先前的照片作比较,相似度大于0.8可以算为同一个人

java 部分代码:

public class FaceRecActivity extends ListActivity implements SurfaceHolder.Callback {private SurfaceView surfaceView;private SurfaceHolder mHolder;private FaceCompare mFaceCompareMain;private Button button;private Button resultBtn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_face);initView();}private int screenWidth, screenHeight;private void initView() {surfaceView = findViewById(R.id.surface);mHolder = surfaceView.getHolder();mHolder.addCallback(this);Display display = getWindowManager().getDefaultDisplay();screenWidth = display.getWidth();screenHeight = display.getHeight();button = findViewById(R.id.recapture_btn);resultBtn = findViewById(R.id.result_btn);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {if (mCamera != null) {try {mCamera.startPreview();mCamera.startFaceDetection();} catch (Exception e) {e.printStackTrace();}}}});resultBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {String path = getExternalFilesDir("file").getPath();Log.e("-->m", "--->" + mFaceCompareMain.getCompareResult(path + "/userface", path + "/face1"));}});mFaceCompareMain = new FaceCompare(this);}private Camera mCamera;private boolean isLoadFinish = false;@Overridepublic void surfaceCreated(SurfaceHolder surfaceHolder) {isLoadFinish = true;startCamera();}private void startCamera() {if (isLoadFinish) {int frontId = findCamera(true);if (frontId == -1) {frontId = findCamera(false);}if (frontId != -1) {mCamera = Camera.open(frontId);}try {mCamera.setFaceDetectionListener(new MyFaceDetectorListener());mCamera.setPreviewDisplay(mHolder);} catch (Exception e) {e.printStackTrace();}}}@Overridepublic void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {if (mHolder.getSurface() == null) {return;}try {mCamera.stopPreview();} catch (Exception e) {e.printStackTrace();}try {mCamera.setPreviewDisplay(mHolder);//获取当前预览框的宽高int measuredWidth = surfaceView.getMeasuredWidth();int measuredHeight = surfaceView.getMeasuredHeight();//设置相机预览图宽高setCameraParms(mCamera, measuredWidth, measuredHeight);mCamera.startPreview();//开启脸部探测startFaceDetection(); // re-start face detection feature} catch (Exception e) {e.printStackTrace();}}@Overridepublic void surfaceDestroyed(SurfaceHolder surfaceHolder) {releaseCamera();}private void releaseCamera() {if (mCamera != null) {mCamera.stopFaceDetection();mCamera.stopPreview();mCamera.release();mCamera = null;}}/*** 启动脸部检测,如果getMaxNumDetectedFaces()!=0说明不支持脸部检测*/public void startFaceDetection() {// Try starting Face DetectionCamera.Parameters params = mCamera.getParameters();// start face detection only *after* preview has startedif (params.getMaxNumDetectedFaces() > 0) {// mCamera supports face detection, so can start it:mCamera.startFaceDetection();} else {Log.e("tag", "startFaceDetection: " + "不支持");}}private int findCamera(boolean isFront) {Camera.CameraInfo cameraInfo = new Camera.CameraInfo();int count = Camera.getNumberOfCameras();for (int i = 0; i < count; i++) {Camera.getCameraInfo(i, cameraInfo);if (isFront) {if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {return i;}} else {if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {return i;}}}return -1;}private class MyFaceDetectorListener implements Camera.FaceDetectionListener {@Overridepublic void onFaceDetection(Camera.Face[] faces, Camera camera) {if (faces.length > 0) {Camera.Face face = faces[0];RectF rectF = mFaceCompareMain.transForm(face, surfaceView);//限制头像位置if (rectF.left >= screenWidth * 0.2 && rectF.right <= screenWidth * 0.8 && rectF.top >= screenHeight * 0.2 && rectF.bottom <= screenHeight * 0.8) {camera.takePicture(null, null, fjpgCallback);camera.stopFaceDetection();}}}}private Camera.PictureCallback fjpgCallback = new Camera.PictureCallback() {public void onPictureTaken(byte[] data, Camera camera) {Bitmap bitmap = mFaceCompareMain.rotateMyBitmap(BitmapFactory.decodeByteArray(data, 0, data.length));//获得压缩后的图片Bitmap bitmap2 = mFaceCompareMain.compressImage(mFaceCompareMain.transImage(bitmap, 480, 720, 100));mFaceCompareMain.saveBitmap(bitmap2, getExternalFilesDir("file").getPath());}};private void setCameraParms(Camera camera, int width, int height) {// 获取摄像头支持的pictureSize列表Camera.Parameters parameters = camera.getParameters();parameters.setJpegQuality(100);// 对焦if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {// 连续对焦parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);}//旋转90度,获取正向预览camera.setDisplayOrientation(90);camera.cancelAutoFocus();camera.setParameters(parameters);}@Overrideprotected void onDestroy() {super.onDestroy();releaseCamera();}
}

识别区代码:

package com.smartTransferBox.assembly.util;import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.hardware.Camera;
import android.view.SurfaceView;import org.opencv.core.Mat;
import org.opencv.core.MatOfFloat;
import org.opencv.core.MatOfInt;
import org.opencv.core.MatOfRect;
import org.opencv.core.Rect;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;public class FaceCompare {//初始化人脸探测器private CascadeClassifier faceDetector;private Context mContext;static {System.loadLibrary("opencv_java3");}public FaceCompare(Context context) {mContext = context;copyToSD();}private void copyToSD() {InputStream inputStream;try {File filePath = mContext.getExternalFilesDir("file");String fileName = "haarcascade_frontalface_alt.xml";inputStream = mContext.getResources().getAssets().open(fileName);if (filePath == null || !filePath.exists()) {filePath.mkdirs();}File faceFile = new File(filePath.getPath() + "/" + fileName);if (faceFile.exists()) {return;}FileOutputStream fileOutputStream = new FileOutputStream(filePath.getPath() + "/" + fileName);byte[] buffer = new byte[1024];int count = 0;while ((count = inputStream.read(buffer)) > 0) {fileOutputStream.write(buffer, 0, count);}fileOutputStream.flush();fileOutputStream.close();inputStream.close();} catch (IOException e) {e.printStackTrace();}}public double getCompareResult(String path1, String path2) {return compare_image(path1, path2);}private double compare_image(String img_1, String img_2) {try {Mat mat_1 = conv_Mat(mContext, img_1);Mat mat_2 = conv_Mat(mContext, img_2);Mat hist_1 = new Mat();Mat hist_2 = new Mat();//颜色范围MatOfFloat ranges = new MatOfFloat(0f, 256f);//直方图大小, 越大匹配越精确 (越慢)MatOfInt histSize = new MatOfInt(1000);Imgproc.calcHist(Arrays.asList(mat_1), new MatOfInt(0), new Mat(), hist_1, histSize, ranges);Imgproc.calcHist(Arrays.asList(mat_2), new MatOfInt(0), new Mat(), hist_2, histSize, ranges);// CORREL 相关系数return Imgproc.compareHist(hist_1, hist_2, Imgproc.CV_COMP_CORREL);} catch (Exception e) {e.printStackTrace();}return 0;}private Mat conv_Mat(Context context, String img_1) {if (faceDetector == null) {faceDetector = new CascadeClassifier(context.getExternalFilesDir("file").getPath() + "/haarcascade_frontalface_alt.xml");}Mat image0 = Imgcodecs.imread(img_1);Mat image = new Mat();//灰度转换Imgproc.cvtColor(image0, image, Imgproc.COLOR_BGR2GRAY);MatOfRect faceDetections = new MatOfRect();//探测人脸faceDetector.detectMultiScale(image, faceDetections);// rect中是人脸图片的范围for (Rect rect : faceDetections.toArray()) {//切割rect人脸Mat mat = new Mat(image, rect);return mat;}return null;}public Bitmap transImage(Bitmap bitmap, int width, int height, int quality) {int bitmapWidth = bitmap.getWidth();int bitmapHeight = bitmap.getHeight();// 缩放图片的尺寸float scaleWidth = (float) width / bitmapWidth;float scaleHeight = (float) height / bitmapHeight;Matrix matrix = new Matrix();matrix.postScale(scaleWidth, scaleHeight);// 产生缩放后的Bitmap对象Bitmap resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmapWidth, bitmapHeight, matrix, false);if (!bitmap.isRecycled()) {bitmap.recycle();//记得释放资源,否则会内存溢出}return resizeBitmap;}//压缩图片public Bitmap compressImage(Bitmap image) {ByteArrayOutputStream baos = new ByteArrayOutputStream();image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中int options = 100;while (baos.toByteArray().length / 1024 > 100) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩baos.reset();//重置baos即清空baosimage.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中options -= 10;//每次都减少10}ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片return bitmap;}public void saveBitmap(Bitmap bitmap, String path) {File file = new File(path + "/userface");try {FileOutputStream fileOutputStream = new FileOutputStream(file);bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);fileOutputStream.flush();fileOutputStream.close();} catch (Exception e) {e.printStackTrace();}}public RectF transForm(Camera.Face face, SurfaceView surfaceView) {Matrix matrix = new Matrix();// Need mirror for front camera.matrix.setScale(-1f, 1f);// This is the value for android.hardware.Camera.setDisplayOrientation.matrix.postRotate(90);// Camera driver coordinates range from (-1000, -1000) to (1000, 1000).// UI coordinates range from (0, 0) to (width, height).matrix.postScale(surfaceView.getWidth() / 2000f, surfaceView.getHeight() / 2000f);matrix.postTranslate(surfaceView.getWidth() / 2f, surfaceView.getHeight() / 2f);RectF srcRect = new RectF(face.rect);RectF dstRect = new RectF(0f, 0f, 0f, 0f);matrix.mapRect(dstRect, srcRect);return dstRect;}//选择获取的图片保持为正向public Bitmap rotateMyBitmap(Bitmap bmp) {Matrix matrix = new Matrix();matrix.postRotate(-90);Bitmap nbmp2 = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);return nbmp2;}}

布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><SurfaceViewandroid:id="@+id/surface"android:layout_width="match_parent"android:layout_height="match_parent" /><Buttonandroid:id="@+id/recapture_btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="bottom"android:text="重拍" /><Buttonandroid:id="@+id/result_btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="bottom|right"android:text="获取结果" />
</FrameLayout>

so库是sdk自带的

总结而言 为了高精确度,需要将人脸限制在一个区域以便得到的图片可以大致相同,后面再通过opencv库得到相似度。如果不限制区域,容易出现人脸获取到,但是无法获取特征值之类的情况。至于优化方面可以将识别模块的代码转为Jni,可以更节省时间。

android opencv单机版人脸识别+比对相关推荐

  1. android opencv NDK人脸识别和对比

    } env->ReleaseStringUTFChars(name, filePath); return 0; } 人脸对比 /** *人脸对比 */ extern "C" ...

  2. Android之OpenCv简单人脸识别功能(Bitmap)

    Android之OpenCv简单人脸识别功能 OpenCv的下载 下载地址 - https://opencv.org/releases/ doc 文档目录 samples 示例代码 sdk 编译后的动 ...

  3. 基于Android端的照片比对系统,基于Android系统的人脸识别系统

    [文章摘要] 当前随着基于Android系统的移动终端设备的广泛应用,以及图像采集设备的普遍集成,使得Android系统的图像采集设备除了具有照相.摄像功能以外,正在扩展新的实用型功能.其中,利用An ...

  4. 人脸识别4:Android InsightFace实现人脸识别Face Recognition(含源码)

    人脸识别4:Android InsightFace实现人脸识别Face Recognition(含源码) 目录 人脸识别4:Android InsightFace实现人脸识别Face Recognit ...

  5. Java借助OpenCV实现人脸识别登录完整示例

    Java借助OpenCV实现人脸识别登录完整示例 OpenCV 效果预览 概述 下载与安装 目录说明 OpenCV的基本使用 项目集成 图片人脸检测 人脸对比相似度 识别视频中的人脸 摄像头识别人脸 ...

  6. Android园区部队人脸识别源码门禁项目讲解

    Android园区部队人脸识别源码门禁项目讲解 这边搞人脸识别相关项目有一段时间,今天抽时间讲述一个经典的人脸识别项目:部队人脸识别门禁系统. 大家都知道部队对人员管理安全要求是相当高的,很多保密的技 ...

  7. 怎样使用OpenCV进行人脸识别

    不断维护的地址:http://plzcoding.com/face-recognition-with-opencv/ 怎样使用OpenCV进行人脸识别 本文大部分来自OpenCV官网上的Face Re ...

  8. Java使用OpenCV实现人脸识别

    通过OpenCV实现人脸识别,包括图片,视频,摄像头中人脸识别. 首先看一下效果(在网上随便找的一张图片): 下面开始说一下如何实现的: 第一步:  需要安装OpenCV 下载链接:https://o ...

  9. python使用opencv实现人脸识别系统

    1.首先安装过python环境,在这里就不过说    检测是否安装成功如下,在cmd中输入Python     2.安装numpy 现在开始安装numpy,打开cmd,输入pip install nu ...

最新文章

  1. 设计-直接不等于简单
  2. boost::geometry模块实现显示不同类型的点的测试程序
  3. impala元数据放到mysql_impala系列: 同步Hive元数据和收集统计信息
  4. integer是值传递还是引用传递_值传递与引用传递
  5. CXF整合Spring开发WebService
  6. GO_00:Mac之Item2的配置安装
  7. MySQL数据库修改密码忘记密码
  8. mysql 创建用户并赋予用户权限
  9. autocad.net QQ群:193522571 判断string中是否包含集合中所有的字符串
  10. C++ Primer 第5版--练习8.4
  11. pr视频剪辑中工具栏功能详解
  12. 50 行代码,实现中英文翻译
  13. 使用Matlab利用加权平均法将RGB彩图灰度化
  14. (五)工作中,工作外
  15. AQS源码解析 7.共享模式_CyclicBarrier重复屏障
  16. MatchNet: Unifying Feature and Metric Learning for Patch-Based Matching
  17. js 数组 pop,push,unshift,splice,shift
  18. Minecraft 1.12.2 彩色渐变字体0.3 掉落物光束
  19. 答题微信小程序实现(4):数据库题库的调用/上一题、下一题/题量length的获取
  20. npm scripts

热门文章

  1. html3d模型制作,数百个 HTML5 例子学习 HT 图形组件 – 3D 建模篇
  2. 职场规划——自信和谦虚
  3. 【BERT-多标签文本分类实战】之七——训练-评估-测试与运行主程序
  4. Netsh命令详解与使用方法
  5. 在Elasticsearch中实现统计异常检测器——第二部分
  6. AMD GPU模式设置(2):初始化和运行时
  7. JS数组转字符串(3种方法) arrays.join(“-“)把数组使用-分割为字符串
  8. Android studio插件GsonFormat,返回json快速创建实体对象
  9. Ajax:ajax跨域解决方案代理机制原理及实现
  10. chown 命令使用方法