Face Detection in Android

In this blog post, I would like explain how to detect the faces in the photograph.

The application will detect the number of faces in the image and draws a rectangle around each face in the image. To do face detection we use android.media.FaceDetector class which identifies the location of the face in a bitmap.

So lets Start: 1. Create a new project File -> Android Project. While creating a new project give activity name as AndroidFaceDetection(AndroidFaceDetection.java) and copy this code:

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import android.app.Activity;
import android.content.ContentValues;
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.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class AndroidFaceDetection extends Activity {
 private static final int SELECT_GALLERY_CODE = 1;
 private static final int TAKE_PICTURE_CODE = 2;

 Button bTakePic, bSelectPic;
 static ImageView imgView;
 // private MyImageView imgView;
 public int imageWidth;
 public int imageHeight;
 public int numberOfFace = 5;
 public FaceDetector myFaceDetect;
 public FaceDetector.Face[] myFace;
 float myEyesDistance;
 int numberOfFaceDetected;
 Bitmap mFaceBitmap;
 InputStream stream;
 int[] fpx = null;
 int[] fpy = null;
 Canvas canvas = new Canvas();
 Paint myPaint = new Paint();
 ContentValues values;
 Uri imageUri;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 // TODO Auto-generated method stub
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main);
 bTakePic = (Button) findViewById(R.id.takePicture);
 bSelectPic = (Button) findViewById(R.id.selectPicture);
 imgView = (ImageView) findViewById(R.id.imageView1);

 bSelectPic.setOnClickListener(new View.OnClickListener() {

 @Override
 public void onClick(View v) {
 // TODO Auto-generated method stub
 Intent intent = new Intent();
 intent.setType("image/*");
 intent.setAction(Intent.ACTION_GET_CONTENT);
 intent.addCategory(Intent.CATEGORY_OPENABLE);
 startActivityForResult(intent, SELECT_GALLERY_CODE);
 }
 });
 bTakePic.setOnClickListener(new View.OnClickListener() {

 @Override
 public void onClick(View v) {
 // TODO Auto-generated method stub
 values = new ContentValues();
 values.put(MediaStore.Images.Media.TITLE, "New Picture");
 values.put(MediaStore.Images.Media.DESCRIPTION, "From your Camera");
 imageUri = getContentResolver().insert(
 MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
 intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
 
 startActivityForResult(intent, TAKE_PICTURE_CODE);
 }
 });

 }

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 if (requestCode == SELECT_GALLERY_CODE
 && resultCode == Activity.RESULT_OK) {
 try {
 // We need to recyle unused bitmaps
 if (mFaceBitmap != null) {
 mFaceBitmap.recycle();
 }

 stream = getContentResolver().openInputStream(data.getData());
 Bitmap b = BitmapFactory.decodeStream(stream);

 mFaceBitmap = b.copy(Bitmap.Config.RGB_565, true);
 b.recycle();
 imgView.setImageBitmap(mFaceBitmap);
 DetectFaces();
 stream.close();

 } catch (FileNotFoundException e) {
 e.printStackTrace();
 } catch (IOException e) {
 e.printStackTrace();
 }
 } else if (TAKE_PICTURE_CODE == requestCode) 
 if (resultCode == Activity.RESULT_OK) {

 try {
 Bitmap b = MediaStore.Images.Media.getBitmap(
 getContentResolver(), imageUri);
 mFaceBitmap = b.copy(Bitmap.Config.RGB_565, true);
 b.recycle();
 imgView.setImageBitmap(mFaceBitmap);
 DetectFaces();
 } catch (Exception e) {
 e.printStackTrace();
 }

 }
 super.onActivityResult(requestCode, resultCode, data);
 }
 

 public void DetectFaces() {
 // TODO Auto-generated method stub

 imageWidth = mFaceBitmap.getWidth();
 imageHeight = mFaceBitmap.getHeight();
 imgView.setImageBitmap(mFaceBitmap);

 myFace = new FaceDetector.Face[numberOfFace];
 myFaceDetect = new FaceDetector(imageWidth, imageHeight, numberOfFace);
 numberOfFaceDetected = myFaceDetect.findFaces(mFaceBitmap, myFace);
 Toast.makeText(AndroidFaceDetection.this, "No of Face Detected: "+numberOfFaceDetected, Toast.LENGTH_LONG).show();
 Paint ditherPaint = new Paint();
 ditherPaint.setDither(true);

 myPaint.setColor(Color.GREEN);
 myPaint.setStyle(Paint.Style.STROKE);
 myPaint.setStrokeWidth(3);

 canvas.setBitmap(mFaceBitmap);
 canvas.drawBitmap(mFaceBitmap, 0, 0, ditherPaint);

 if (numberOfFaceDetected > 0) {
 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 * 2),
 (int) (myMidPoint.y - myEyesDistance * 2),
 (int) (myMidPoint.x + myEyesDistance * 2),
 (int) (myMidPoint.y + myEyesDistance * 2), myPaint);

 }

 }

}
 
}

2. Now open your main.xml layout and copy this code:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:id="@+id/ll1"
 android:orientation="vertical" >

 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content" >

 <Button
 android:id="@+id/selectPicture"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Select picture" />

 <Button
 android:id="@+id/takePicture"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Take Picture" />

 </LinearLayout>

 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:orientation="vertical" >

 <ImageView
 android:id="@+id/imageView1"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:contentDescription="TODO"
 android:src="@drawable/ic_launcher" />

 </LinearLayout>
 
</LinearLayout>

3. Now add these permissions in your AndroidManifest.xml file:

<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Tips to Remember always:
1) In this example i’m detecting only 5 faces. If you need to detect more faces, then change this line according to your needs.(On line no: 33)

public int numberOfFace = 5;

2) While accessing camera via Intent, you need to remember that these two line of code snippet is far enough to call a camera, but it returns always the thumbnail of the picture rather than original image.

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, TAKE_PICTURE_CODE);

3) FaceDetector.Face is the Android API. A Face contains all the information identifying the location of a face in a bitmap. (On line no: 140)

4) findfaces() is a method – Finds all the faces found in a given bitmap. (On line no: 142)

5) face.getMidPoint() – Sets the position of the mid-point between the eyes.(On line no: 158)

6) eyedistance() – Returns the distance between the eyes.(On line no: 159)

7) To draw a rectangle around the face, i used


canvas.drawRect((int) (myMidPoint.x - myEyesDistance * 2),
(int) (myMidPoint.y - myEyesDistance * 2),
(int) (myMidPoint.x + myEyesDistance * 2),
(int) (myMidPoint.y + myEyesDistance * 2), myPaint);

I just multiplied into two to grab the whole face rather than marking on a face. But to draw a rectangle on the face, then remove all (*2) from the above code.


canvas.drawRect((int) (myMidPoint.x - myEyesDistance ),
(int) (myMidPoint.y - myEyesDistance ),
(int) (myMidPoint.x + myEyesDistance ),
(int) (myMidPoint.y + myEyesDistance ), myPaint);

Screenshot_2014-05-09-12-21-03
Hope this helpful. Your valuable comments are always welcomed. It will help to improve my post and understanding.

durga chiranjeevi

durga chiranjeevi

I'm currently working as Android developer at Energy Alternatives India. Interested in Application and Game development.
durga chiranjeevi

Leave a Reply

Your email address will not be published. Required fields are marked *