andbook!.pdf - Learning Android Get an anddev.org - Android-Shirt Back to index
anddev.org Header Logo
FAQ Search Top rated articles Browse Feeds anddev.org - Authors Contact Details Register Log in

Quick and easy FaceDetector demo


 
       anddev.org - Android Development Community | Android Tutorials | Index -> Novice Tutorials
Author Message
strongsauce
Freshman
Freshman


Joined: 03 Dec 2008
Posts: 5

PostPosted: Fri Dec 05, 2008 7:43 am    Post subject: Quick and easy FaceDetector demo Reply with quote

Using Android's FaceDetector

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.

To make it as simple as possible, I only created 2 classes for this tutorial. You will also need to add an image into your res/drawable folder to use as a test image.

/src/package_name/FaceTest.java
Java:

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);
    }
}


/src/package_name/FaceView.java
Note you must change R.drawable.bao102 with the actual resource image you use.
Java:

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);
               }
          }
     }
}



facedetector1.jpg
 Description:
 Filesize:  35.58 KB
 Viewed:  9074 Time(s)

facedetector1.jpg


Back to top
View user's profile Send private message
Houseonfire
Freshman
Freshman


Joined: 05 Dec 2008
Posts: 3

PostPosted: Fri Dec 05, 2008 8:49 am    Post subject: Reply with quote

This is very interesting.
I was wondering if you could comment in your code the part that actually identifies the face.

Thank you for this script.
Back to top
View user's profile Send private message
liaowg
Junior Developer
Junior Developer


Joined: 03 Jun 2008
Posts: 12

PostPosted: Thu Feb 05, 2009 10:02 am    Post subject: Reply with quote

It seems the neven vision detection is very poor, I try 4 pictures, only one succeed
Back to top
View user's profile Send private message MSN Messenger
Craigo
Junior Developer
Junior Developer


Joined: 17 Mar 2009
Posts: 10
Location: Sydney, Australia

PostPosted: Tue Mar 17, 2009 3:53 am    Post subject: Reply with quote

Houseonfire wrote:
This is very interesting.
I was wondering if you could comment in your code the part that actually identifies the face.
Thank you for this script.


The line of code is: arrayFaces.findFaces(sourceImage, getAllFaces);

The calls to pose(FaceDetector.Face.EULER_X,Y,Z) always return 0 for me. Anyone ever get values for these?
Back to top
View user's profile Send private message
shyjumon.n
Freshman
Freshman


Joined: 18 Mar 2009
Posts: 9

PostPosted: Wed Mar 18, 2009 8:19 am    Post subject: unable to get the red mark Reply with quote

Hi,
I tried but some problem please help.
I am able to get the picture displayed but detection is not happening. I am using the same code posted in the article and my xml file is as follows:

main.xml
XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello"
    />

    <ImageView android:id="@+id/image"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true"
        android:layout_width="200.0sp"
        android:layout_height="300.0sp"
        android:src="@drawable/image"
        android:layout_x="70.0sp"
        android:layout_y="130.0sp">


</ImageView>
</LinearLayout>


And also the adb logcat out put is as follows:

Code:
I/jdwp    (  455): received file descriptor 24 from ADB
I/ActivityManager(   46): Starting activity: Intent { flags=0x10000000 comp={com.android.facegetapp/com.android.facegetapp.facegetapp} }
D/AndroidRuntime(  455): Shutting down VM
D/dalvikvm(  455): DestroyJavaVM waiting for non-daemon threads to exit
I/dalvikvm(  455): DestroyJavaVM shutting VM down
D/dalvikvm(  455): HeapWorker thread shutting down
D/dalvikvm(  455): HeapWorker thread has shut down
D/jdwp    (  455): JDWP shutting down net...
D/jdwp    (  455): +++ peer disconnected
I/dalvikvm(  455): Debugger has detached; object registry had 1 entries
D/dalvikvm(  455): VM cleaning up
E/dalvikvm(  455): pthread_setspecific failed, err=22
I/ActivityManager(   46): Start proc com.android.facegetapp for activity com.android.facegetapp/.facegetapp: pid=464 uid=10029 gids={}
D/dalvikvm(  455): LinearAlloc 0x0 used 541284 of 4194304 (12%)
I/jdwp    (  464): received file descriptor 10 from ADB
D/dalvikvm(  464): GC freed 512 objects / 34504 bytes in 85ms
D/dalvikvm(  464): Trying to load lib /system/lib/libFFTEm.so 0x0
D/dalvikvm(  464): Added shared lib /system/lib/libFFTEm.so 0x0
E/Face    (  464): 0 is null
E/Face    (  464): 1 is null
I/ActivityManager(   46): Displayed activity com.android.facegetapp/.facegetapp: 1214 ms
D/dalvikvm(   90): GC freed 1719 objects / 92536 bytes in 82ms
D/GpsLocationProvider(   46): NetworkThread out of wake loop
D/GpsLocationProvider(   46): Requesting time from NTP server pool.ntp.org
D/SntpClient(   46): request time failed: java.net.SocketTimeoutException: The operation timed out
D/GpsLocationProvider(   46): requestTime failed
D/GpsLocationProvider(   46): NetworkThread wait for 300000ms




Please advice me where i am wrong or anything missing in xml file ?
Back to top
View user's profile Send private message
Craigo
Junior Developer
Junior Developer


Joined: 17 Mar 2009
Posts: 10
Location: Sydney, Australia

PostPosted: Wed Mar 18, 2009 9:18 am    Post subject: Re: unable to get the red mark Reply with quote

shyjumon.n wrote:
...or anything missing in xml file ?

I didn't bother with changing the xml file. I just stuck the view straight onto the Activity ContentView:
setContentView(new FaceView(this)).

Worked great, got about 90% of the faces. However, the pose(FaceDetector.Face.EULER_...) always returns 0 for me?
Back to top
View user's profile Send private message
shyjumon.n
Freshman
Freshman


Joined: 18 Mar 2009
Posts: 9

PostPosted: Wed Mar 18, 2009 10:32 am    Post subject: Reply with quote

Thank you.
xml is not important.

For me call to getFace = getAllFaces[i]; are success in all cases. but "getFace.getMidPoint(eyesMP);" fails ( java.lang.NullPointerException). and the following is my debug prints.

E/Face: ( 231): exception thrown
E/Face ( 231): 0 is null
E/Face: ( 231): exception thrown
E/Face ( 231): 1 is null
E/Face: ( 231): exception thrown
E/Face ( 231): 2 is null


Are you guys able to succeed ? I tried 10-15 different resolution images.
Back to top
View user's profile Send private message
Craigo
Junior Developer
Junior Developer


Joined: 17 Mar 2009
Posts: 10
Location: Sydney, Australia

PostPosted: Wed Mar 18, 2009 10:39 am    Post subject: Reply with quote

shyjumon.n wrote:
Thank you.
For me call to getFace = getAllFaces[i]; are success in all cases. but "getFace.getMidPoint(eyesMP);" fails ( java.lang.NullPointerException). and the following is my debug prints.


Sorry, the (somewhat obvious) thing I can suggest is debugging into the Face object to see if you can see all it's values. It works great for me. I'm using android-sdk-windows-1.1_r1.
Back to top
View user's profile Send private message
shyjumon.n
Freshman
Freshman


Joined: 18 Mar 2009
Posts: 9

PostPosted: Wed Mar 18, 2009 10:55 am    Post subject: Reply with quote

>> Sorry, the (somewhat obvious) thing I can suggest is debugging into the Face object to see if you can see all it's values. It works great for me. I'm using android-sdk-windows-1.1_r1.

Thank you for the reply.
Could you please be able to share the diff of the code (if any) or the image which succeeded for you ?
I am using the same SDK's Linux version.

Thank you.
Back to top
View user's profile Send private message
Craigo
Junior Developer
Junior Developer


Joined: 17 Mar 2009
Posts: 10
Location: Sydney, Australia

PostPosted: Wed Mar 18, 2009 10:59 am    Post subject: Reply with quote

shyjumon.n wrote:

Could you please be able to share the diff of the code (if any) or the image which succeeded for you ?
I am using the same SDK's Linux version.

Thank you.

Sorry, my code is now very different as I have been playing around with it. You should be able to inspect the values in the Face object to verify the face detection worked correctly.
Back to top
View user's profile Send private message
shyjumon.n
Freshman
Freshman


Joined: 18 Mar 2009
Posts: 9

PostPosted: Wed Mar 18, 2009 11:03 am    Post subject: Reply with quote

Thank you. Let me do some debug and will be back with some good news. Once again thanks for the support.
Back to top
View user's profile Send private message
shyjumon.n
Freshman
Freshman


Joined: 18 Mar 2009
Posts: 9

PostPosted: Wed Mar 25, 2009 8:13 am    Post subject: Reply with quote

Thanks a lot for the support. I could able to succeed in the example. The problem was with my test images. Converted formats are not accepting but the raw jpg files are accepted.

special thanks to Craigo Very Happy
Back to top
View user's profile Send private message
chandrasekhar.m
Once Poster
Once Poster


Joined: 07 Apr 2009
Posts: 1

PostPosted: Tue Apr 07, 2009 10:51 am    Post subject: Re: Quick and easy FaceDetector demo Reply with quote

Kudos....It works !!....cool application

Smile

_________________
^^
C.
Back to top
View user's profile Send private message Visit poster's website
shyjumon.n
Freshman
Freshman


Joined: 18 Mar 2009
Posts: 9

PostPosted: Sat Apr 25, 2009 8:07 pm    Post subject: Reply with quote

How can i add a button to the FaceView and upon clicking the button, i would like to load a layout which is there in layout1.xml ????
any idea....
Also how can i put this FaceView to an Imageview which is there in my main.xml...
Please help if you have clues ....

Thank you.
Back to top
View user's profile Send private message
nbadal
Junior Developer
Junior Developer


Joined: 26 May 2009
Posts: 23

PostPosted: Tue May 26, 2009 4:07 pm    Post subject: Reply with quote

Very cool! It worked on an old family photo of mine perfectly
Back to top
View user's profile Send private message
Display posts from previous:   
       anddev.org - Android Development Community | Android Tutorials | Index -> Novice Tutorials All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


© 2007, Android Development Community
All rights reserved.
Powered by phpBB.