Cet article a pour but d’introduire la détection de visage, cette nouveauté arrivée avec la nouvelle version d’Android (Ice Cream Sandwich).

Ce tutoriel sera découpé en deux parties, dont cette première partie qui abordera la détection de visage sur une image.

Android Ice Cream Sandwich Logo

Qu’est ce que FaceDetector ?

La version ICS d’Android fournie une nouvelle classe FaceDetector afin de pouvoir détecter des visages depuis un Bitmap.
Cette classe, vous permet d’obtenir un tableau d’objet Face. Chaque Objet représente un visage trouvé dans l’image.

Cette classe vous permets de récupérer des données sur chaque visage, positions des yeux, distance entre les yeux, le point se trouvant au milieu des deux yeux ….

Un petit exemple pour bien comprendre

Petit pré-requis, il faut que vous ayez installé la version 4.0 du SDK Android sur votre Eclipse.

Donc pour commencer, il faut créer un projet Android en version 4.0.

Une fois ce projet créé, nous allons pouvoir modifier notre Activité. Il nous faut créer une classe qui étends la classe View.

Nous allons créer un constructeur qui prends en argument un variable de type context : public FaceView(Context context).

Dans le constructeur, nous allons charger notre Bitmap qui se trouve dans notre dossier Drawable.

private Bitmap facesImg;
.....
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;

facesImg = BitmapFactory.decodeResource(
		getResources(), R.drawable.faces, bitmapOptions);
  • On commence par définir le type de notre Bitmap en RGB_565. Car ceci est une condition du bon fonctionnement de la classe FaceDetector
  • On Charge notre Bitmap qui se trouve dans notre dossier Drawable à l’aide de la classe BitmapFactory et plus précisément à l’aide de la méthode decodeResource

Une fois notre image chargée, il faut récupérer le longueur et la largueur de cette derniére

private int mBitmapWidth;
private int mBitmapHeight;
....
mBitmapWidth = facesImg.getWidth();
mBitmapHeight = facesImg.getHeight();

Maintenant, il suffit juste de créer une instance de la classe FaceDetector et appeler la méthode findFaces pour récupérer la liste des visages trouvées dans le Bitmap.

private static final int NUM_FACES = 64;
private FaceDetector mFaceDetector;
private FaceDetector.Face mFacesArray[] = new FaceDetector.Face[NUM_FACES];
......
mFaceDetector = new FaceDetector(mBitmapWidth, mBitmapHeight, NUM_FACES);
mFaceDetector.findFaces(facesImg, mFacesArray);
  • On définie le nombre de visage maximum à détecter dans l’image, la valeur maximum supportée est 64
  • On créé une instance de la classe FaceDetector, en lui passant la hauteur, largeur de l’image et le nombre maximum de visage à détecter.
  • On créer un tableau qui nous servira à stocker la liste des visages
  • On appelle la méthode findFaces en lui passant l’image et le tableau à remplir

Puis on parcours la liste des visages, on récupère le visage en question. Dans chaque instance de visage on récupère les différentes valeurs dont on a besoin dans le reste du projet.

  • Le point se trouvant au milieu des yeux grâce à la méthode getMidPoint
  • La distance entre les yeux à l’aide de la méthode eyesDistance
for (int i = 0; i < mFacesArray.length; i++)
{
	mFace = mFacesArray[i];
	try
	{
		PointF eyesMiddlePoint = new PointF();
		mFace.getMidPoint(eyesMiddlePoint);
		mEyesDistance[i] = mFace.eyesDistance();
		mEyesCenterPoints[i] = eyesMiddlePoint;
	}
	catch (Exception e)
	{
		e.printStackTrace();
	}
}

Voici le résultat finale

public FaceView(Context context)
{
	super(context);
	BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
	bitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;

	 facesImg = BitmapFactory.decodeResource(
			getResources(), R.drawable.faces, bitmapOptions);

	mBitmapWidth = facesImg.getWidth();
	mBitmapHeight = facesImg.getHeight();

	mFaceDetector = new FaceDetector(mBitmapWidth, mBitmapHeight, NUM_FACES);
	mFaceDetector.findFaces(facesImg, mFacesArray);

	for (int i = 0; i < mFacesArray.length; i++)
	{
		mFace = mFacesArray[i];
		try
		{
			PointF eyesMiddlePoint = new PointF();
			mFace.getMidPoint(eyesMiddlePoint);
			mEyesDistance[i] = mFace.eyesDistance();
			mEyesCenterPoints[i] = eyesMiddlePoint;
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}
}

Puis, on surcharge la méthode OnDraw pour redessiner notre vue et indiquer les visages détectés.

  • On définit une couleur pour le dessin des cercles et une autre pour redessiner l’image.
  • On redessine l’image
  • Pour on parcours les différents visages et on dessine un cercle au milieu des yeux de chaques visages

Voici ce que cela donnera :

@Override
protected void onDraw(Canvas canvas)
{
	mXRatio = getWidth() * 1.0f / mBitmapWidth;
	mYRatio = getHeight() * 1.0f / mBitmapHeight;

	mCirclePaint.setStyle(Paint.Style.FILL);
	mCirclePaint.setColor(Color.GREEN);

	mColor.setStyle(Paint.Style.STROKE);
	mColor.setTextAlign(Paint.Align.CENTER);

	canvas.drawBitmap(
		facesImg, null, new Rect(0, 0, getWidth(), getHeight()), mColor);

	for (int i = 0; i < mEyesCenterPoints.length; i++)
		if (mEyesCenterPoints[i] != null)
			canvas.drawCircle(
			mEyesCenterPoints[i].x * mXRatio, mEyesCenterPoints[i].y * mYRatio, mEyesDistance[i] / 3,mCirclePaint);
	}
}

Voici le code complet de la classe :

public class FaceDetectionExampleActivity extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(new FaceView(this));
	}

	public class FaceView extends View
	{
		private static final int NUM_FACES = 64;

		private FaceDetector mFaceDetector;
		private FaceDetector.Face mFacesArray[] = new FaceDetector.Face[NUM_FACES];
		private FaceDetector.Face mFace = null;

		private PointF mEyesCenterPoints[] = new PointF[NUM_FACES];
		private float mEyesDistance[] = new float[NUM_FACES];

		private Bitmap facesImg;

		private Paint mColor = new Paint(Paint.ANTI_ALIAS_FLAG);
		private Paint mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);

		private int mBitmapWidth;
		private int mBitmapHeight;

		private float mXRatio, mYRatio;

		public FaceView(Context context)
		{
			super(context);

			BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
			bitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;

			 facesImg = BitmapFactory.decodeResource(
				getResources(), R.drawable.faces, bitmapOptions);

			mBitmapWidth = facesImg.getWidth();
			mBitmapHeight = facesImg.getHeight();

			mFaceDetector = new FaceDetector(mBitmapWidth, mBitmapHeight, NUM_FACES);
			mFaceDetector.findFaces(
				facesImg, mFacesArray);

			for (int i = 0; i < mFacesArray.length; i++)
			{
				mFace = mFacesArray[i];
				try
				{
					PointF eyesMiddlePoint = new PointF();
					mFace.getMidPoint(eyesMiddlePoint);
					mEyesDistance[i] = mFace.eyesDistance();
					mEyesCenterPoints[i] = eyesMiddlePoint;
				}
				catch (Exception e)
				{
					e.printStackTrace();
				}
			}
		}

		@Override
		protected void onDraw(Canvas canvas)
		{
			mXRatio = getWidth() * 1.0f / mBitmapWidth;
			mYRatio = getHeight() * 1.0f / mBitmapHeight;

			mCirclePaint.setStyle(Paint.Style.FILL);
			mCirclePaint.setColor(Color.GREEN);

			mColor.setStyle(Paint.Style.STROKE);
			mColor.setTextAlign(Paint.Align.CENTER);

			canvas.drawBitmap(
				facesImg, null, new Rect(0, 0, getWidth(), getHeight()), mColor);

			for (int i = 0; i < mEyesCenterPoints.length; i++)
				if (mEyesCenterPoints[i] != null)
					canvas.drawCircle(
						mEyesCenterPoints[i].x * mXRatio, mEyesCenterPoints[i].y * mYRatio, mEyesDistance[i] / 3,
						mCirclePaint);
		}
	}

}

Voici l’image originale :

Voici le resultat obtenu :

Conclusion

Voilà ce tutoriel s’arrête ici. Si vous souhaitez obtenir le code du projet, vous pouvez le trouver ici.

Categories: Tutoriels

5 Responses so far.


  1. fred dit :

    Svp,je veux un code source pour detecter tous les données d´un compteur d´élèctricité dans une image

  2. Abdou dit :

    Bonjour Mr Nazim,
    Est ce qu’on peut faire une capture vidéo pour l’écran Android.
    Merci d’avance

  3. [...] Cet article a pour but d’introduire la détection de visage, cette nouveauté arrivée avec la nouvelle version d’Android (Ice Cream Sandwich).Via http://www.tutos-android.com [...]

  4. [...] Tutos-android: Détection de visages dans une image sous Android ICS [...]

  5. julien dit :

    Bonjour, pourrais-t-on avoir quelques conseil pour pouvoir comparer deux visages entre eux.
    merci d’avance et merci pour ce super tuto !!

Leave a Reply


Notifiez-moi des commentaires à venir via email. Vous pouvez aussi vous abonner sans commenter.