Android下的人脸识别——FaceDetector的使用

来源:互联网 发布:郑州java培训机构排名 编辑:程序博客网 时间:2024/06/06 01:27

这一篇要记录的是Android平台中的人脸识别技术,这里所说的人脸识别是Android系统内置的人脸识别API——FaceDetector,该API可以通过少量代码完成人脸识别,但是这种识别是最基本的识别,即只能识别出图像中的人脸,仅此而已,不能做更精确的识别(比如判断人脸的身份),下面记录我使用FaceDetector的过程:

首先来一张图:


我们的代码即将完成上图中的功能,选择图片后,点击检测人脸,就会在图片上绘制出人脸的区域来,下面是主要代码:

1、布局文件activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:padding="10dp"    android:orientation="vertical" >    <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:text="检测人脸"    android:layout_marginTop="5dp"    /><ImageView     android:id="@+id/image"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:layout_marginTop="5dp"    /></LinearLayout>
2、MainActivity.java代码

package com.example.testfacedetector;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 = 5;//最大可以检测出的人脸数量private int realFaceNum = 0;//实际检测出的人脸数量private Button selectBtn;private Button detectBtn;private ImageView image;private ProgressDialog pd;private Bitmap bm;//选择的图片的Bitmap对象private Paint paint;//画人脸区域用到的Paintprivate boolean hasDetected = false;//标记是否检测到人脸@Overrideprotected 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);}@Overrideprotected 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 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;}}//画出人脸区域后要刷新ImageViewimage.invalidate();}/** * 检测图像中的人脸需要一些时间,所以放到AsyncTask中去执行 * @author yubo * */private class FindFaceTask extends AsyncTask<Void, Void, FaceDetector.Face[]>{@Overrideprotected void onPreExecute() {super.onPreExecute();pd.show();}@Overrideprotected 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;}@Overrideprotected void onPostExecute(Face[] result) {super.onPostExecute(result);pd.dismiss();if(result == null){Toast.makeText(MainActivity.this, "抱歉,图片中未检测到人脸", Toast.LENGTH_SHORT).show();}else{drawFacesArea(result);}}}@Overridepublic void onClick(View arg0) {switch(arg0.getId()){case R.id.btn_select://选择图片selectPicture();break;case R.id.btn_detect://检测人脸detectFace();break;}}}

注释已经写得很详细了,代码也不多,但是这里的人脸识别太过基础,识别率很低,正脸识别起来基本没问题,一旦不是正脸,或者有多张脸的图像,识别起来就不行了

3、添加权限

最后别忘了在AndroidManifest.xml文件中添加必要的权限,因为我们的代码中有访问文件系统的操作,需要加入如下权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


源码下载点这里



0 0
原创粉丝点击