Tutorial: Simple implementation of the Android SDK's FaceDetector and FaceDetector.Face classes.
First a few things about the FaceDetector class.
- According to the documentation, Bitmaps need to use the RGB565 format. However it seems to work with bitmaps using the default constructors for that class but I used mode RGB565 just in case.
- Seems that the class uses eyes as the "facial detection" this means there is no other detail (face dimensions, mouth location, etc.) and faces that are taken from the side will not be detected. Sunglasses/glasses seem to interfere with detection.
- The bigger the image the easier it can detect images. However there is a limit to how big of an image you can load into Android's memory. The images I used were all under 1000x1000 but at least 400x300.
- Regardless of how many faces you specify in the FaceDetector constructor, it seems that it takes the same amount of time, i.e. if there are only 5 faces in the image you won't be penalized for asking for 10.
- The FaceDetector.Face class cannot be extended, all its constructors are privatized, which means you cannot change the Face class's CONFIDENCE_THRESHOLD.
- Maximum number of faces you can ask for is 64 after that it won't bother loading the face detection.
- pose() in class FaceDetector.Face does not seem to do anything.
/src/package_name/FaceTest.java
Using java Syntax Highlighting
- package com.jrr.facetest;
- import android.app.Activity;
- import android.os.Bundle;
- public class FaceTest extends Activity {
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- FaceView faceView = new FaceView(this);
- setContentView(faceView);
- }
- }
Parsed in 0.033 seconds, using GeSHi 1.0.8.4
/src/package_name/FaceView.java
Note you must change R.drawable.bao102 with the actual resource image you use.
Using java Syntax Highlighting
- package com.jrr.facetest;
- import android.content.Context;
- 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.graphics.Rect;
- import android.media.FaceDetector;
- import android.util.Log;
- import android.view.View;
- public class FaceView extends View {
- private static final int NUM_FACES = 10; // max is 64
- private static final boolean DEBUG = true;
- private FaceDetector arrayFaces;
- private FaceDetector.Face getAllFaces[] = new FaceDetector.Face[NUM_FACES];
- private FaceDetector.Face getFace = null;
- private PointF eyesMidPts[] = new PointF[NUM_FACES];
- private float eyesDistance[] = new float[NUM_FACES];
- private Bitmap sourceImage;
- private Paint tmpPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- private Paint pOuterBullsEye = new Paint(Paint.ANTI_ALIAS_FLAG);
- private Paint pInnerBullsEye = new Paint(Paint.ANTI_ALIAS_FLAG);
- private int picWidth, picHeight;
- private float xRatio, yRatio;
- public FaceView(Context context) {
- super(context);
- pInnerBullsEye.setStyle(Paint.Style.FILL);
- pInnerBullsEye.setColor(Color.RED);
- pOuterBullsEye.setStyle(Paint.Style.STROKE);
- pOuterBullsEye.setColor(Color.RED);
- tmpPaint.setStyle(Paint.Style.STROKE);
- tmpPaint.setTextAlign(Paint.Align.CENTER);
- BitmapFactory.Options bfo = new BitmapFactory.Options();
- bfo.inPreferredConfig = Bitmap.Config.RGB_565;
- sourceImage = BitmapFactory.decodeResource( getResources() ,R.drawable.bao102, bfo);
- picWidth = sourceImage.getWidth();
- picHeight = sourceImage.getHeight();
- arrayFaces = new FaceDetector( picWidth, picHeight, NUM_FACES );
- arrayFaces.findFaces(sourceImage, getAllFaces);
- for (int i = 0; i < getAllFaces.length; i++)
- {
- getFace = getAllFaces[i];
- try {
- PointF eyesMP = new PointF();
- getFace.getMidPoint(eyesMP);
- eyesDistance[i] = getFace.eyesDistance();
- eyesMidPts[i] = eyesMP;
- if (DEBUG)
- {
- Log.i("Face",
- i + " " + getFace.confidence() + " " + getFace.eyesDistance() + " "
- + "Pose: ("+ getFace.pose(FaceDetector.Face.EULER_X) + ","
- + getFace.pose(FaceDetector.Face.EULER_Y) + ","
- + getFace.pose(FaceDetector.Face.EULER_Z) + ")"
- + "Eyes Midpoint: ("+eyesMidPts[i].x + "," + eyesMidPts[i].y +")"
- );
- }
- }
- catch (Exception e)
- {
- if (DEBUG) Log.e("Face", i + " is null");
- }
- }
- }
- @Override
- protected void onDraw(Canvas canvas)
- {
- xRatio = getWidth()*1.0f / picWidth;
- yRatio = getHeight()*1.0f / picHeight;
- canvas.drawBitmap( sourceImage, null , new Rect(0,0,getWidth(),getHeight()),tmpPaint);
- for (int i = 0; i < eyesMidPts.length; i++)
- {
- if (eyesMidPts[i] != null)
- {
- pOuterBullsEye.setStrokeWidth(eyesDistance[i] /6);
- canvas.drawCircle(eyesMidPts[i].x*xRatio, eyesMidPts[i].y*yRatio, eyesDistance[i] / 2 , pOuterBullsEye);
- canvas.drawCircle(eyesMidPts[i].x*xRatio, eyesMidPts[i].y*yRatio, eyesDistance[i] / 6 , pInnerBullsEye);
- }
- }
- }
- }
Parsed in 0.046 seconds, using GeSHi 1.0.8.4




