码迷,mamicode.com
首页 > 移动开发 > 详细

Android中 人脸识别FaceDetector简单实例

时间:2015-06-18 17:27:35      阅读:256      评论:0      收藏:0      [点我收藏+]

标签:facedetect   人脸识别   人脸检测   face++   

  Android SDK从1.0版本中(API level 1)就已经集成了简单的人脸识别功能,通过调用FaceDetector 我们可以在Android平台上实现Bitmap多人脸识别(一张图中可以有多个人脸)。它查找人脸的原理是:找眼睛。它返回的人脸数据face,通过调用public float eyesDistance (),public void getMidPoint (PointF point),我们可以得到探测到的两眼间距,以及两眼中心点位置(MidPoint)。public float confidence () 可以返回该人脸数据的可信度(0~1),这个值越大,该人脸数据的准确度也就越高。
 


流程
1. 读取一张图片至Bitmap (从Resource中,或是从手机相册中选取)
2. 使用FaceDetector API分析Bitmap,将探测到的人脸数据以FaceDetector.Face存储在一个Face list中;
3.将人脸框显示在图片上。

源码
activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="10dp" >

    <Button
        android:id="@+id/btn_select"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="选择图片" />

    <Button
        android:id="@+id/btn_detect"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:text="检测人脸" />

    <ImageView
        android:id="@+id/image"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_marginTop="5dp" />

</LinearLayout>

MainActivity.java

package com.example.faceandroidtest;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.database.Cursor;
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.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {

    private static final int REQUEST_CODE_SELECT_PIC = 120;
    private static final int MAX_FACE_NUM = 10;//最大可以检测出的人脸数量
    private int realFaceNum = 0;//实际检测出的人脸数量

    private Button selectBtn;
    private Button detectBtn;
    private ImageView image;
    private ProgressDialog pd;

    private Bitmap bm;//选择的图片的Bitmap对象
    private Paint paint;//画人脸区域用到的Paint

    private boolean hasDetected = false;//标记是否检测到人脸

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();

        paint = new Paint();
        paint.setColor(Color.BLUE);
        paint.setStrokeWidth(2);
        paint.setStyle(Paint.Style.STROKE);//设置话出的是空心方框而不是实心方块

        pd = new ProgressDialog(this);
        pd.setTitle("提示");
        pd.setMessage("正在检测,请稍等");
    }

    /**
     * 控件初始化
     */
    private void initView(){
        selectBtn = (Button) findViewById(R.id.btn_select);
        selectBtn.setOnClickListener(this);
        detectBtn = (Button) findViewById(R.id.btn_detect);
        detectBtn.setOnClickListener(this);
        image = (ImageView) findViewById(R.id.image);
    }

    /**
     * 从图库选择图片
     */
    private void selectPicture(){
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_GET_CONTENT);
        intent.setType("image/*");
        startActivityForResult(intent, REQUEST_CODE_SELECT_PIC);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode == REQUEST_CODE_SELECT_PIC && resultCode == Activity.RESULT_OK){
            //获取选择的图片
            Uri selectedImage = data.getData();
            String[] filePathColumn = { MediaStore.Images.Media.DATA };
            Cursor cursor = getContentResolver().query(selectedImage,
                    filePathColumn, null, null, null);
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            String selectedImagePath = cursor.getString(columnIndex);
            bm = BitmapFactory.decodeFile(selectedImagePath);
            //要使用Android内置的人脸识别,需要将Bitmap对象转为RGB_565格式,否则无法识别
            bm = bm.copy(Bitmap.Config.RGB_565, true);
            cursor.close();
            image.setImageBitmap(bm);
            hasDetected = false;
        }
    }

//  private void selectPicture(){
//      bm = BitmapFactory.decodeResource(getResources(), R.drawable.test1);
//      bm = bm.copy(Bitmap.Config.RGB_565, true);
//        image.setImageBitmap(bm);
//        hasDetected = false;
//  }


    /**
     * 检测人脸
     */
    private void detectFace(){
        if(bm == null){
            Toast.makeText(this, "请先选择图片", Toast.LENGTH_SHORT).show();
            return ;
        }
        if(hasDetected){
            Toast.makeText(this, "已检测出人脸", Toast.LENGTH_SHORT).show();
        }else{
            new FindFaceTask().execute();
        }
    }

    private void drawFacesArea(FaceDetector.Face[] faces){
        Toast.makeText(this, "图片中检测到" + realFaceNum + "张人脸", Toast.LENGTH_SHORT).show();
        float eyesDistance = 0f;//两眼间距
        Canvas canvas = new Canvas(bm);
        for(int i = 0; i < faces.length; i++){
            FaceDetector.Face face = faces[i];
            if(face != null){
                PointF pointF = new PointF();
                face.getMidPoint(pointF);//获取人脸中心点
                eyesDistance = face.eyesDistance();//获取人脸两眼的间距
                //画出人脸的区域
                canvas.drawRect(pointF.x - eyesDistance, pointF.y - eyesDistance, pointF.x + eyesDistance, pointF.y + eyesDistance, paint);
                hasDetected = true;
            }
        }
        //画出人脸区域后要刷新ImageView
        image.invalidate();
    }

    /**
     * 检测图像中的人脸需要一些时间,所以放到AsyncTask中去执行
     * @author yubo
     *
     */
    private class FindFaceTask extends AsyncTask<Void, Void, FaceDetector.Face[]>{

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pd.show();
        }

        @Override
        protected Face[] doInBackground(Void... arg0) {
            //最关键的就是下面三句代码
            FaceDetector faceDetector = new FaceDetector(bm.getWidth(), bm.getHeight(), MAX_FACE_NUM);
            FaceDetector.Face[] faces = new FaceDetector.Face[MAX_FACE_NUM]; 
            realFaceNum = faceDetector.findFaces(bm, faces);
            if(realFaceNum > 0){
                return faces;
            }
            return null;
        }

        @Override
        protected void onPostExecute(Face[] result) {
            super.onPostExecute(result);
            pd.dismiss();
            if(result == null){
                Toast.makeText(MainActivity.this, "抱歉,图片中未检测到人脸", Toast.LENGTH_SHORT).show();
            }else{
                drawFacesArea(result);
            }
        }

    }

    public void onClick(View arg0) {
        switch(arg0.getId()){
            case R.id.btn_select://选择图片
                selectPicture();
                break;
            case R.id.btn_detect://检测人脸
                detectFace();
                break;
        }
    }

}

在源码中先将MAX_FACE_NUM最大可以检测出的人脸数量设为5。

private static final int MAX_FACE_NUM = 5;//最大可以检测出的人脸数量

检测结果
技术分享

猜测应该是选取人群中识别率最高的5个人头像,因为最大可以检测出的人脸数量为5,所以只显示识别率最高的前5个人头像。

当将MAX_FACE_NUM最大可以检测出的人脸数量设为10。

private static final int MAX_FACE_NUM = 10;//最大可以检测出的人脸数量

同一张图片检测结果
技术分享

参考引用

Android中 人脸识别FaceDetector简单实例

标签:facedetect   人脸识别   人脸检测   face++   

原文地址:http://blog.csdn.net/wtyvhreal/article/details/46548403

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!