Android中 Face ServiceFaceDetector簡單一實例,androidFace Service
Android SDK從1.0版本中(API level 1)就已經整合了簡單的Face Service功能,通過調用FaceDetector 我們可以在Android平台上實現Bitmap多Face Service(一張圖中可以有多個人臉)。它尋找人臉的原理是:找眼睛。它返回的人臉資料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內建的Face Service,需要將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 API 臉部偵測(Face Detect)
- 用AndroidSDK中的Face Detector實現Face Service
- Face++ 官網