Quick and easy FaceDetector demo

Basic Tutorials concerning: GUI, Views, Activites, XML, Layouts, Intents, ...

Quick and easy FaceDetector demo

Postby strongsauce » Fri Dec 05, 2008 7:43 am

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
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package com.jrr.facetest;
  2.  
  3. import android.app.Activity;
  4. import android.os.Bundle;
  5.  
  6. public class FaceTest extends Activity {
  7.     /** Called when the activity is first created. */
  8.     @Override
  9.     public void onCreate(Bundle savedInstanceState) {
  10.         super.onCreate(savedInstanceState);
  11.         FaceView faceView = new FaceView(this);
  12.         setContentView(faceView);
  13.     }
  14. }
  15.  
Parsed in 0.036 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.
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package com.jrr.facetest;
  2.  
  3. import android.content.Context;
  4. import android.graphics.Bitmap;
  5. import android.graphics.BitmapFactory;
  6. import android.graphics.Canvas;
  7. import android.graphics.Color;
  8. import android.graphics.Paint;
  9. import android.graphics.PointF;
  10. import android.graphics.Rect;
  11. import android.media.FaceDetector;
  12. import android.util.Log;
  13. import android.view.View;
  14.  
  15. public class FaceView extends View {
  16.         private static final int NUM_FACES = 10; // max is 64
  17.         private static final boolean DEBUG = true;
  18.  
  19.         private FaceDetector arrayFaces;
  20.         private FaceDetector.Face getAllFaces[] = new FaceDetector.Face[NUM_FACES];
  21.         private FaceDetector.Face getFace = null;
  22.        
  23.         private PointF eyesMidPts[] = new PointF[NUM_FACES];
  24.         private float  eyesDistance[] = new float[NUM_FACES];
  25.        
  26.         private Bitmap sourceImage;
  27.        
  28.         private Paint tmpPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  29.         private Paint pOuterBullsEye = new Paint(Paint.ANTI_ALIAS_FLAG);
  30.         private Paint pInnerBullsEye = new Paint(Paint.ANTI_ALIAS_FLAG);
  31.        
  32.         private int picWidth, picHeight;
  33.         private float xRatio, yRatio;
  34.        
  35.         public FaceView(Context context) {
  36.                 super(context);
  37.                
  38.                 pInnerBullsEye.setStyle(Paint.Style.FILL);
  39.                 pInnerBullsEye.setColor(Color.RED);
  40.                
  41.                 pOuterBullsEye.setStyle(Paint.Style.STROKE);
  42.                 pOuterBullsEye.setColor(Color.RED);
  43.                
  44.                 tmpPaint.setStyle(Paint.Style.STROKE);
  45.                 tmpPaint.setTextAlign(Paint.Align.CENTER);
  46.                
  47.                 BitmapFactory.Options bfo = new BitmapFactory.Options();
  48.                 bfo.inPreferredConfig = Bitmap.Config.RGB_565;
  49.                
  50.                 sourceImage = BitmapFactory.decodeResource( getResources() ,R.drawable.bao102, bfo);
  51.  
  52.                 picWidth = sourceImage.getWidth();
  53.                 picHeight = sourceImage.getHeight();
  54.                
  55.                 arrayFaces = new FaceDetector( picWidth, picHeight, NUM_FACES );
  56.                 arrayFaces.findFaces(sourceImage, getAllFaces);
  57.                
  58.                 for (int i = 0; i < getAllFaces.length; i++)
  59.                 {
  60.                         getFace = getAllFaces[i];
  61.                         try {
  62.                                 PointF eyesMP = new PointF();
  63.                                 getFace.getMidPoint(eyesMP);
  64.                                 eyesDistance[i] = getFace.eyesDistance();
  65.                                 eyesMidPts[i] = eyesMP;
  66.                                
  67.                                 if (DEBUG)
  68.                                 {
  69.                                         Log.i("Face",
  70.                                                 i +  " " + getFace.confidence() + " " + getFace.eyesDistance() + " "
  71.                                                 + "Pose: ("+ getFace.pose(FaceDetector.Face.EULER_X) + ","
  72.                                                 + getFace.pose(FaceDetector.Face.EULER_Y) + ","
  73.                                                 + getFace.pose(FaceDetector.Face.EULER_Z) + ")"
  74.                                                 + "Eyes Midpoint: ("+eyesMidPts[i].x + "," + eyesMidPts[i].y +")"
  75.                                         );
  76.                                 }
  77.                         }
  78.                         catch (Exception e)
  79.                         {
  80.                                 if (DEBUG) Log.e("Face", i + " is null");
  81.                         }
  82.                
  83.                 }
  84.         }
  85.        
  86.         @Override
  87.         protected void onDraw(Canvas canvas)
  88.         {
  89.                 xRatio = getWidth()*1.0f / picWidth;
  90.                 yRatio = getHeight()*1.0f / picHeight;
  91.                 canvas.drawBitmap( sourceImage, null , new Rect(0,0,getWidth(),getHeight()),tmpPaint);
  92.                 for (int i = 0; i < eyesMidPts.length; i++)
  93.                 {
  94.                         if (eyesMidPts[i] != null)
  95.                         {
  96.                                 pOuterBullsEye.setStrokeWidth(eyesDistance[i] /6);
  97.                                 canvas.drawCircle(eyesMidPts[i].x*xRatio, eyesMidPts[i].y*yRatio, eyesDistance[i] / 2 , pOuterBullsEye);
  98.                                 canvas.drawCircle(eyesMidPts[i].x*xRatio, eyesMidPts[i].y*yRatio, eyesDistance[i] / 6 , pInnerBullsEye);
  99.                         }
  100.                 }
  101.         }
  102. }
  103.  
Parsed in 0.065 seconds, using GeSHi 1.0.8.4
Attachments
facedetector1.jpg
facedetector1.jpg (35.58 KiB) Viewed 35793 times
strongsauce
Freshman
Freshman
 
Posts: 5
Joined: Wed Dec 03, 2008 8:30 pm

Top

Postby Houseonfire » Fri Dec 05, 2008 8:49 am

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.
Houseonfire
Freshman
Freshman
 
Posts: 3
Joined: Fri Dec 05, 2008 8:33 am

Postby liaowg » Thu Feb 05, 2009 10:02 am

It seems the neven vision detection is very poor, I try 4 pictures, only one succeed
liaowg
Junior Developer
Junior Developer
 
Posts: 12
Joined: Tue Jun 03, 2008 7:26 am

Postby Craigo » Tue Mar 17, 2009 3:53 am

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?
Craigo
Junior Developer
Junior Developer
 
Posts: 10
Joined: Tue Mar 17, 2009 3:30 am
Location: Sydney, Australia

unable to get the red mark

Postby shyjumon.n » Wed Mar 18, 2009 8:19 am

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
Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.    android:orientation="vertical"
  4.    android:layout_width="fill_parent"
  5.    android:layout_height="fill_parent"
  6.    >
  7. <TextView
  8.    android:layout_width="fill_parent"
  9.    android:layout_height="wrap_content"
  10.    android:text="@string/hello"
  11.    />
  12.     <ImageView android:id="@+id/image"
  13.    android:layout_centerVertical="true"
  14.    android:layout_centerHorizontal="true"
  15.        android:layout_width="200.0sp"
  16.        android:layout_height="300.0sp"
  17.        android:src="@drawable/image"
  18.        android:layout_x="70.0sp"
  19.        android:layout_y="130.0sp">
  20.  
  21. </ImageView>
  22. </LinearLayout>
Parsed in 0.005 seconds, using GeSHi 1.0.8.4


And also the adb logcat out put is as follows:

Code: Select all
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 ?
shyjumon.n
Freshman
Freshman
 
Posts: 9
Joined: Wed Mar 18, 2009 8:13 am

Re: unable to get the red mark

Postby Craigo » Wed Mar 18, 2009 9:18 am

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?
Craigo
Junior Developer
Junior Developer
 
Posts: 10
Joined: Tue Mar 17, 2009 3:30 am
Location: Sydney, Australia

Top

Postby shyjumon.n » Wed Mar 18, 2009 10:32 am

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.
shyjumon.n
Freshman
Freshman
 
Posts: 9
Joined: Wed Mar 18, 2009 8:13 am

Postby Craigo » Wed Mar 18, 2009 10:39 am

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.
Craigo
Junior Developer
Junior Developer
 
Posts: 10
Joined: Tue Mar 17, 2009 3:30 am
Location: Sydney, Australia

Postby shyjumon.n » Wed Mar 18, 2009 10:55 am

>> 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.
shyjumon.n
Freshman
Freshman
 
Posts: 9
Joined: Wed Mar 18, 2009 8:13 am

Postby Craigo » Wed Mar 18, 2009 10:59 am

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.
Craigo
Junior Developer
Junior Developer
 
Posts: 10
Joined: Tue Mar 17, 2009 3:30 am
Location: Sydney, Australia

Postby shyjumon.n » Wed Mar 18, 2009 11:03 am

Thank you. Let me do some debug and will be back with some good news. Once again thanks for the support.
shyjumon.n
Freshman
Freshman
 
Posts: 9
Joined: Wed Mar 18, 2009 8:13 am

Postby shyjumon.n » Wed Mar 25, 2009 8:13 am

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 :D
shyjumon.n
Freshman
Freshman
 
Posts: 9
Joined: Wed Mar 18, 2009 8:13 am

Re: Quick and easy FaceDetector demo

Postby chandrasekhar.m » Tue Apr 07, 2009 10:51 am

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

:-)
^^
C.
chandrasekhar.m
Once Poster
Once Poster
 
Posts: 1
Joined: Tue Apr 07, 2009 10:47 am

Postby shyjumon.n » Sat Apr 25, 2009 8:07 pm

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.
shyjumon.n
Freshman
Freshman
 
Posts: 9
Joined: Wed Mar 18, 2009 8:13 am

Postby nbadal » Tue May 26, 2009 4:07 pm

Very cool! It worked on an old family photo of mine perfectly
nbadal
Developer
Developer
 
Posts: 30
Joined: Tue May 26, 2009 3:55 pm

Top
Next

Return to Novice Tutorials

Who is online

Users browsing this forum: No registered users and 6 guests