Android中的人脸检测的示例代码(静态和动态)

(1)背景。

Google 于2006年8月收购Neven Vision 公司 (该公司拥有10多项应用于移动设备领域的图像识别的专利),以此获得了图像识别的技术,并加入到android中。Android 中的人脸识别技术,用到的底层库:android/external/neven/,framework 层:frameworks/base/media/java/android/media/FaceDetector.java。

Java 层接口的限制:A,只能接受Bitmap 格式的数据;B,只能识别双眼距离大于20 像素的人脸像(当然,这个可在framework层中修改);C,只能检测出人脸的位置(双眼的中心点及距离),不能对人脸进行匹配(查找指定的脸谱)。

人脸识别技术的应用:A,为Camera 添加人脸识别的功能,使得Camera 的取景器上能标识出人脸范围;如果硬件支持,可以对人脸进行对焦。B,为相册程序添加按人脸索引相册的功能,按人脸索引相册,按人脸分组,搜索相册。

(2)Neven库给上层提供的主要方法:

A,android.media.FaceDetector .FaceDetector(int width, int height, int maxFaces):Creates a FaceDetector, configured with the size of the images to be analysed and the maximum number of faces that can be detected. These parameters cannot be changed once the object is constructed.

B,int android.media.FaceDetector .findFaces(Bitmap bitmap, Face [] faces):Finds all the faces found in a given Bitmap . The supplied array is populated with FaceDetector.Face s for each face found. The bitmap must be in 565 format (for now).

(3) 静态图片处理代码实例:

通过对位图的处理,捕获位图中的人脸,并以绿框显示,有多个人脸就提示多个绿框。首先新建一个activity,由于位图资源会用代码显示出来,所以不需在layout中使用widget。

package com.example.mydetect2;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.media.FaceDetector; //人脸识别的关键类
import android.media.FaceDetector.Face;
import android.view.View;  

public class MainActivity2 extends Activity { 

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //setContentView(R.layout.activity_main_activity2);
    setContentView(new myView(this));  //使用自建的view来显示
    Log.i("zhangcheng","MainActivity2 run here");
  } 

  private class myView extends View{
    private int imageWidth, imageHeight;
    private int numberOfFace = 5;    //最大检测的人脸数
    private FaceDetector myFaceDetect; //人脸识别类的实例
    private FaceDetector.Face[] myFace; //存储多张人脸的数组变量
    float myEyesDistance;      //两眼之间的距离
    int numberOfFaceDetected;    //实际检测到的人脸数
    Bitmap myBitmap; 

    public myView(Context context){   //view类的构造函数,必须有
      super(context);
      BitmapFactory.Options BitmapFactoryOptionsbfo = new BitmapFactory.Options();
      BitmapFactoryOptionsbfo.inPreferredConfig = Bitmap.Config.RGB_565; //构造位图生成的参数,必须为565。类名+enum
      myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.baby, BitmapFactoryOptionsbfo);
      imageWidth = myBitmap.getWidth();
      imageHeight = myBitmap.getHeight();
      myFace = new FaceDetector.Face[numberOfFace];    //分配人脸数组空间
      myFaceDetect = new FaceDetector(imageWidth, imageHeight, numberOfFace);
      numberOfFaceDetected = myFaceDetect.findFaces(myBitmap, myFace);  //FaceDetector 构造实例并解析人脸
      Log.i("zhangcheng","numberOfFaceDetected is " + numberOfFaceDetected);
    } 

    protected void onDraw(Canvas canvas){      //override函数,必有
      canvas.drawBitmap(myBitmap, 0, 0, null);  //画出位图
      Paint myPaint = new Paint();
      myPaint.setColor(Color.GREEN);
      myPaint.setStyle(Paint.Style.STROKE);
      myPaint.setStrokeWidth(3);     //设置位图上paint操作的参数 

      for(int i=0; i < numberOfFaceDetected; i++){
        Face face = myFace[i];
        PointF myMidPoint = new PointF();
        face.getMidPoint(myMidPoint);
        myEyesDistance = face.eyesDistance();  //得到人脸中心点和眼间距离参数,并对每个人脸进行画框
        canvas.drawRect(      //矩形框的位置参数
            (int)(myMidPoint.x - myEyesDistance),
            (int)(myMidPoint.y - myEyesDistance),
            (int)(myMidPoint.x + myEyesDistance),
            (int)(myMidPoint.y + myEyesDistance),
            myPaint);
      }
    }
  }
}

以上为activity,工程的xml文件没有什么特殊地方。最后得到的结果如下,图片资源是png的也可以。

(4) 动态预览识别人脸代码实例

该过程用于后台工作,没有界面也没有预览。所以没有采用上面那种处理位图资源的方式。Import的类就不列出了,核心的代码和流程如下:

A,打开摄像头,获得初步摄像头回调数据,用到是setpreviewcallback

protected Camera mCameraDevice = null;// 摄像头对象实例
private long mScanBeginTime = 0;  // 扫描开始时间
private long mScanEndTime = 0;  // 扫描结束时间
private long mSpecPreviewTime = 0;  // 扫描持续时间
private int orientionOfCamera ;  //前置摄像头layout角度
int numberOfFaceDetected;  //最终识别人脸数目
public void startFaceDetection() {
    try {
        mCameraDevice = Camera.open(1);   //打开前置
        if (mCameraDevice != null)
          Log.i(TAG, "open cameradevice success! ");
      } catch (Exception e) {       //Exception代替很多具体的异常
        mCameraDevice = null;
        Log.w(TAG, "open cameraFail");
        mHandler.postDelayed(r,5000);  //如果摄像头被占用,人眼识别每5秒检测看有没有释放前置
        return;
    }  

    Log.i(TAG, "startFaceDetection");
    Camera.Parameters parameters = mCameraDevice.getParameters();
    setCameraDisplayOrientation(1,mCameraDevice);       //设置预览方向  

    mCameraDevice.setPreviewCallback(new PreviewCallback(){
      public void onPreviewFrame(byte[] data, Camera camera){
        mScanEndTime = System.currentTimeMillis();  //记录摄像头返回数据的时间
        mSpecPreviewTime = mScanEndTime - mScanBeginTime; //从onPreviewFrame获取摄像头数据的时间
        Log.i(TAG, "onPreviewFrame and mSpecPreviewTime = " + String.valueOf(mSpecPreviewTime));
        Camera.Size localSize = camera.getParameters().getPreviewSize(); //获得预览分辨率
        YuvImage localYuvImage = new YuvImage(data, 17, localSize.width, localSize.height, null);
        ByteArrayOutputStream localByteArrayOutputStream = new ByteArrayOutputStream();
        localYuvImage.compressToJpeg(new Rect(0, 0, localSize.width, localSize.height), 80, localByteArrayOutputStream);  //把摄像头回调数据转成YUV,再按图像尺寸压缩成JPEG,从输出流中转成数组
        byte[] arrayOfByte = localByteArrayOutputStream.toByteArray();
        CameraRelease();  //及早释放camera资源,避免影响camera设备的正常调用
        StoreByteImage(arrayOfByte);
      }
    }); 

    mCameraDevice.startPreview();     //该语句可放在回调后面,当执行到这里,调用前面的setPreviewCallback
    mScanBeginTime = System.currentTimeMillis();// 记录下系统开始扫描的时间
  }

B,设置预览方向的函数说明,该函数比较重要,因为方向直接影响bitmap构造时的矩阵旋转角度,影响最终人脸识别的成功与否

public void setCameraDisplayOrientation(int paramInt, Camera paramCamera){
    CameraInfo info = new CameraInfo();
    Camera.getCameraInfo(paramInt, info);
    int rotation = ((WindowManager)getSystemService("window")).getDefaultDisplay().getRotation(); //获得显示器件角度
    int degrees = 0;
    Log.i(TAG,"getRotation's rotation is " + String.valueOf(rotation));
    switch (rotation) {
      case Surface.ROTATION_0: degrees = 0; break;
      case Surface.ROTATION_90: degrees = 90; break;
      case Surface.ROTATION_180: degrees = 180; break;
      case Surface.ROTATION_270: degrees = 270; break;
    } 

    orientionOfCamera = info.orientation;   //获得摄像头的安装旋转角度
    int result;
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
      result = (info.orientation + degrees) % 360;
      result = (360 - result) % 360; // compensate the mirror
    } else { // back-facing
      result = (info.orientation - degrees + 360) % 360;
    }
    paramCamera.setDisplayOrientation(result); //注意前后置的处理,前置是映象画面,该段是SDK文档的标准DEMO
  }

C,对摄像头回调数据进行转换并最终解成BITMAP后再人脸识别的过程

public void StoreByteImage(byte[] paramArrayOfByte){
    mSpecStopTime = System.currentTimeMillis();
    mSpecCameraTime = mSpecStopTime - mScanBeginTime; 

    Log.i(TAG, "StoreByteImage and mSpecCameraTime is " + String.valueOf(mSpecCameraTime)); 

    BitmapFactory.Options localOptions = new BitmapFactory.Options();
      Bitmap localBitmap1 = BitmapFactory.decodeByteArray(paramArrayOfByte, 0, paramArrayOfByte.length, localOptions);
      int i = localBitmap1.getWidth();
      int j = localBitmap1.getHeight();  //从上步解出的JPEG数组中接出BMP,即RAW->JPEG->BMP
      Matrix localMatrix = new Matrix();
      //int k = cameraResOr;
      Bitmap localBitmap2 = null;
      FaceDetector localFaceDetector = null; 

    switch(orientionOfCamera){  //根据前置安装旋转的角度来重新构造BMP
      case 0:
        localFaceDetector = new FaceDetector(i, j, 1);
            localMatrix.postRotate(0.0F, i / 2, j / 2);
            localBitmap2 = Bitmap.createBitmap(i, j, Bitmap.Config.RGB_565);
        break;
      case 90:
        localFaceDetector = new FaceDetector(j, i, 1);  //长宽互换
            localMatrix.postRotate(-270.0F, j / 2, i / 2); //正90度的话就反方向转270度,一样效果
            localBitmap2 = Bitmap.createBitmap(i, j, Bitmap.Config.RGB_565);
        break;
      case 180:
        localFaceDetector = new FaceDetector(i, j, 1);
            localMatrix.postRotate(-180.0F, i / 2, j / 2);
            localBitmap2 = Bitmap.createBitmap(i, j, Bitmap.Config.RGB_565);
        break;
      case 270:
        localFaceDetector = new FaceDetector(j, i, 1);
            localMatrix.postRotate(-90.0F, j / 2, i / 2);
            localBitmap2 = Bitmap.createBitmap(j, i, Bitmap.Config.RGB_565); //localBitmap2应是没有数据的
        break;
    } 

    FaceDetector.Face[] arrayOfFace = new FaceDetector.Face[1];
      Paint localPaint1 = new Paint();
      Paint localPaint2 = new Paint();
    localPaint1.setDither(true);
      localPaint2.setColor(-65536);
      localPaint2.setStyle(Paint.Style.STROKE);
      localPaint2.setStrokeWidth(2.0F);
      Canvas localCanvas = new Canvas();
      localCanvas.setBitmap(localBitmap2);
      localCanvas.setMatrix(localMatrix);
      localCanvas.drawBitmap(localBitmap1, 0.0F, 0.0F, localPaint1); //该处将localBitmap1和localBitmap2关联(可不要?) 

    numberOfFaceDetected = localFaceDetector.findFaces(localBitmap2, arrayOfFace); //返回识脸的结果
      localBitmap2.recycle();
      localBitmap1.recycle();  //释放位图资源 

    FaceDetectDeal(numberOfFaceDetected);
  } 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

您可能感兴趣的文章:

  • JavaCV实现人脸检测功能
  • opencv 做人脸识别 opencv 人脸匹配分析
  • OpenCV实现人脸识别
  • OpenCV实现人脸检测
  • opencv实现图片与视频中人脸检测功能
  • 基于openCV实现人脸检测
  • 详解android 人脸检测你一定会遇到的坑
  • Android动态人脸检测的示例代码(脸数可调)
  • Android camera实时预览 实时处理,人脸识别示例
  • Java+opencv3.2.0实现人脸检测功能
(0)

相关推荐

  • JavaCV实现人脸检测功能

    本文实例为大家分享了JavaCV实现人脸检测功能的具体代码,供大家参考,具体内容如下 /* * Copyright (C) 2010,2011,2012 Samuel Audet * * FacePreview - A fusion of OpenCV's facedetect and Android's CameraPreview samples, * with JavaCV + JavaCPP as the glue in between. * * This file was based o

  • 基于openCV实现人脸检测

    openCV的人脸识别主要通过Haar分类器实现,当然,这是在已有训练数据的基础上.openCV安装在 opencv/opencv/sources/data/haarcascades_cuda(或haarcascades)中存在预先训练好的物体检测器(xml格式),包括正脸.侧脸.眼睛.微笑.上半身.下半身.全身等. openCV的的Haar分类器是一个监督分类器,首先对图像进行直方图均衡化并归一化到同样大小,然后标记里面是否包含要监测的物体.它首先由Paul Viola和Michael Jon

  • Java+opencv3.2.0实现人脸检测功能

    说到人脸检测,首先要了解Haar特征分类器.Haar特征分类器说白了就是一个个的xml文件,不同的xml里面描述人体各个部位的特征值,比如人脸.眼睛等等.OpenCV3.2.0中提供了如下特征文件: haarcascade_eye.xml haarcascade_eye_tree_eyeglasses.xml haarcascade_frontalcatface.xml haarcascade_frontalcatface_extended.xml haarcascade_frontalface

  • OpenCV实现人脸检测

    前段日子,写了个人脸检测的小程序,可以检测标记图片.视频.摄像头中的人脸.效果还行吧,用的是opencv提供人脸库.至于具体的人脸检测原理,找资料去啃吧. 环境:VS2013+OPENCV2.4.10+Win8.1 一.基于对话框的MFC 首先,新建一个基于对话框的MFC应用程序,命名为myFaceDetect(取消"安全开发周期(SDL)检查"勾选,我自己习惯取消这个). 放置Button,设置Button的ID和Caption. 图片按钮--ID:IDC_FACEDETECT 视频

  • opencv 做人脸识别 opencv 人脸匹配分析

    机器学习 机器学习的目的是把数据转换成信息. 机器学习通过从数据里提取规则或模式来把数据转成信息. 人脸识别 人脸识别通过级联分类器对特征的分级筛选来确定是否是人脸. 每个节点的正确识别率很高,但正确拒绝率很低. 任一节点判断没有人脸特征则结束运算,宣布不是人脸. 全部节点通过,则宣布是人脸. 工业上,常用人脸识别技术来识别物体. 对图片进行识别 复制代码 代码如下: #include "opencv2/core/core.hpp" #include "opencv2/obj

  • Android动态人脸检测的示例代码(脸数可调)

    人脸检测 这里的人脸检测并非人脸识别,但是却可以识别出是否有人,当有人时候,你可以将帧图进行人脸识别(这里推荐Face++的sdk),当然我写的demo中没有加入人脸识别,有兴趣的朋友可以追加.face++ android自带的人脸检测 这里我们用到了人脸检测类为 FaceDetector.这个类提供了强大的人脸检测功能,可以方便我们进行人脸的侦测,因此我们使用他来进行动态的人脸检测,实现原理,其实也挺简单,主要是通过Carmen的回调PreviewCallback 在其中对帧图进行操作,并通过

  • Android camera实时预览 实时处理,人脸识别示例

    Android camera实时预览 实时处理,面部认证. 预览操作是网友共享的代码,我在继承SurfaceView 的CameraSurfaceView 中加入了帧监听事件,每次预览监听前五个数据帧,在处理做一个面部识别. 先看目录关系 自定义控件CameraSurfaceView.java 自定义接口方法CameraInterface.java CameraActivity预览界面. CameraSurfaceView.Java package com.centaur.camera.prev

  • 详解android 人脸检测你一定会遇到的坑

    笔者今年做了一个和人脸有关的android产品,主要是获取摄像头返回的预览数据流,判断该数据流是否包含了人脸,有人脸时显示摄像头预览框,无人脸时摄像头预览框隐藏,看上去这个功能并不复杂,其实在开发过程中,遇到的问题也不多,全部都处理了,在正式推出前,这个产品在公司内部也测试了几个月,也没发现bug,但最近实施人员,在客户公司做实施时,反馈回来各种问题,这些问题有部分是程序bug,也有一部分是和硬件有关,因为测试环境有限,笔者无法对各种型号,各个厂家的硬件进行测试,这篇文章主要是记录,摄像头给我们

  • OpenCV实现人脸识别

    主要有以下步骤: 1.人脸检测 2.人脸预处理 3.从收集的人脸训练机器学习算法 4.人脸识别 5.收尾工作 人脸检测算法: 基于Haar的脸部检测器的基本思想是,对于面部正面大部分区域而言,会有眼睛所在区域应该比前额和脸颊更暗,嘴巴应该比脸颊更暗等情形.它通常执行大约20个这样的比较来决定所检测的对象是否为人脸,实际上经常会做上千次. 基于LBP的人脸检测器基本思想与基于Haar的人脸检测器类似,但它比较的是像素亮度直方图,例如,边缘.角落和平坦区域的直方图. 这两种人脸检测器可通过训练大的图

  • opencv实现图片与视频中人脸检测功能

    本文实例为大家分享了opencv实现人脸检测功能的具体代码,供大家参考,具体内容如下 第一章:反思与总结 上一篇博客我相信自己将人脸检测中的AdaBoost算法解释的非常清晰了,以及如何训练人脸检测的强分类器:人脸检测中AdaBoost算法详解.事后,自我感觉对这个人脸检测还是不够具体,所以自己抽了一下午的时间用opencv实现图片与视频中的人脸检测,下面是我用vs2013加opencv4.9来实现的.做一下声明,我的代码是参考OpenCV实现人脸检测的一个博客写的,非常感谢这位博主,我学到了很

随机推荐