Saturday, December 28, 2013

Android Face Detection (Android-Tutorial)


In this tutorial ,I will show you how to detect faces from a bitmap using FaceDetector.Face class.

First create a new application in Eclipse & name it Face Detect.

In this app, I am creating activity with two buttons ,while one serves for selecting image from gallery and other to detect faces in the given gallery.
I am creating a CustomView to add image without any bitmap size issues.

The code should be self explanatory.
If you get any errors or issues, Please feel free to mention it in the comment section.

Note:
- Drop a Imagefile in your projects resources folder named face.jpg.
- The image should contain some faces to detect(duh).


activity_face_detect.xml



     


 
      
    
    
    


FaceDetectMainActivity.java



package com.forloexample.facedetect;

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

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class FaceDetectMainActivity extends Activity {

 public static int screenHeight,screenWidth;
 public MyView faceview;
 
 public Bitmap defaultBitmap;
 
 public Button gallery,detect;
 
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_face_detect);
  
  
  // we use Display metrics to get the screen width and height.
  //we need the screen size for later use to set the image from gallery on the screen.
  
   DisplayMetrics displaymetrics = new DisplayMetrics();
   getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
   screenHeight = displaymetrics.heightPixels;  
   screenWidth = displaymetrics.widthPixels; 
  
  // Declaring our custom view ( I named it faceview).
   
   faceview = (MyView)findViewById(R.id.faceview);
   
  //Declaring our two buttons.
   
   gallery=(Button)findViewById(R.id.gallery);
   detect=(Button)findViewById(R.id.detect);
   
  
   
    BitmapFactory.Options bitmapFatoryOptions=new BitmapFactory.Options();
    bitmapFatoryOptions.inPreferredConfig=Bitmap.Config.RGB_565;
  
   defaultBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.face,bitmapFatoryOptions);
   // we are gicing a default bitmap to show up when the app starts.
   // this is important. To detect the faces in the bitmap, the bitmap should be in the format RGB_565.
   // so we convert the bitmap to RGB format using BitmapFactory.Options.
   
   
   //setting the default bitmap to our customview.(A method setImage in view class)
   faceview.setImage(defaultBitmap);
   
   
   gallery.setOnClickListener(new OnClickListener() {
    
    @Override
    public void onClick(View v) {
     // TODO Auto-generated method stub
    
     // onclick we are having onactivity for result. To select an image from our gallery and return an image.
     
     Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("image/*");
     startActivityForResult(intent, 0 );
     
    }
   });
  
   
    detect.setOnClickListener(new OnClickListener() {
    
    @Override
    public void onClick(View v) {
     // TODO Auto-generated method stub
    
     
     // a method to detect faces ( in view class).
     faceview.facedetect();
     
    }
   });
  
 }
 
 
 // onActivityresult for getting an image from gallery.
 @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        super.onActivityResult(requestCode, resultCode, data);

        if (resultCode == Activity.RESULT_OK) {
         
         if(requestCode==0){
         
        // We get the image selected in gallery in the form of image Uri. 
          
           Uri imageURI = data.getData(); 
            
            try {
             
             //converting the image uri to the bitmap of RGB format.( for our needs)
             
              BitmapFactory.Options bitmapFatoryOptions=new BitmapFactory.Options();
           bitmapFatoryOptions.inPreferredConfig=Bitmap.Config.RGB_565;
             
             Bitmap b =  
                  BitmapFactory.decodeStream(getContentResolver().openInputStream(imageURI), null,  
                    bitmapFatoryOptions);

             // we need to display the selected image in our view. So we are setting the bitmap as follows
             faceview.myBitmap=b;

             
   } catch (FileNotFoundException e) {
//     TODO Auto-generated catch block
    e.printStackTrace();
   } catch (IOException e) {
//     TODO Auto-generated catch block  
    e.printStackTrace();
   }
            
            faceview.invalidate(); 
 
         }
         //invalidate the view for changes to take effect.
         faceview.invalidate(); 
        } else {
            System.exit(0);
            Log.e("result", "BAD");
        }
    }
 
 
 
 
}





MyView.java


package com.forloexample.facedetect;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.media.FaceDetector;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Toast;



 public class MyView extends View {
  
  
  private FaceDetector.Face[] detectedFaces;
  private int NUMBER_OF_FACES=10;
  private FaceDetector faceDetector;
  int NUMBER_OF_FACE_DETECTED;
  private float eyeDistance;
  
  public Paint myPaint;
  
  public Bitmap myBitmap,resultBmp;
  
  
  public MyView(Context context, AttributeSet attrs) {
   super(context,attrs);
   // TODO Auto-generated constructor stub
  
  }

  
  // this method is used to set the defaultbitmap to our view.
  public void setImage(Bitmap bitmap) {
    myBitmap = bitmap;
         invalidate();
     }
  
  
  // method to detect faces in a bitmap.
  public void facedetect(){
   
    myPaint = new Paint();
          myPaint.setColor(Color.GREEN);
          myPaint.setStyle(Paint.Style.STROKE); 
          myPaint.setStrokeWidth(3);

          // Using FaceDetector.Face we detect faces in a givem bitmap.
          // We give resultBmp which is the scaledbitmap of the original bitmap.
          
   detectedFaces=new FaceDetector.Face[NUMBER_OF_FACES];
   faceDetector=new FaceDetector(resultBmp.getWidth(),resultBmp.getHeight(),NUMBER_OF_FACES);
   NUMBER_OF_FACE_DETECTED=faceDetector.findFaces(resultBmp, detectedFaces);
  
   
  
   invalidate();
   
   // we are creating a toast to know how many faces are detected.
   
   if(NUMBER_OF_FACE_DETECTED==0){
   
   Toast.makeText(getContext(), "no faces detected", Toast.LENGTH_LONG).show(); 
   
   }else if(NUMBER_OF_FACE_DETECTED!=0){
    
    Toast.makeText(getContext(), "faces detected "+NUMBER_OF_FACE_DETECTED, Toast.LENGTH_LONG).show(); 
    
   }
  }
  
  protected void onDraw(Canvas canvas)
  {
   // here we are drawing the bitmap on the canvas.
   // scaled bitmap so that our our image can fit in the view no matter what size it is.
   
   if(myBitmap!=null)
   {
   
    int w = myBitmap.getWidth();
           int h = myBitmap.getHeight();
         resultBmp = null;
           
           int widthofBitMap  = FaceDetectMainActivity.screenWidth ;
           int heightofBitMap = widthofBitMap*h/w;

           // we are setting the bitmap according to the width of the bitmap.
           // the width of bitmap is equal to width of the screen.
           
          resultBmp = Bitmap.createScaledBitmap(myBitmap, widthofBitMap, heightofBitMap, true);  
          canvas.drawBitmap(resultBmp, (FaceDetectMainActivity.screenWidth-widthofBitMap)/2,(FaceDetectMainActivity.screenHeight-heightofBitMap)/2, null);
  
         }
   
  } 
  
  
  
 }




Now Run your app and see for yourself.



Download the Whole Project



Please give your suggestions in the commentsection.
You may also give suggestions on what tutorial you want me to do next.
Please feel free to comment.
As this is my first post , I need some motivation to provide as many tutorials as possible.