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);
Hope this helpful. Your valuable comments are always welcomed. It will help to improve my post and understanding.
Related Posts
durga chiranjeevi
Latest posts by durga chiranjeevi (see all)
- Sharing Application Data Between Two Android Apps – Part III - April 8, 2015
- Sharing Application Data Between Two Android Apps – Part II - April 8, 2015
- Sharing Application Data Between Two Android Apps – Part I - April 8, 2015