Detección de rostros con la api FaceDetector en Ice Cream Sandwich

Este articulo tiene por objetivo hacer descubrir una de las novedades que trae la API del Ice Cream Sandwich

Este tutorial esta cortado en dos partes, cuya primera parte aborde la detección de rostros desde una imagen.

Que es el FaceDetector ?

La version del ICS de Android trae una nueva clase FaceDetector con el objetivo de poder detectar los rostros desde cualquier Bitmap.

Esta clase nos permite obtener un areglo del objeto Face. Cada Objeto representa un rostro encontrado en la imagen.

Por ejemplo esta clase nos permite recuperar datos en cada rostros de la imagen, las posiciones de ojos, la distancia entre los ojos, o bien el punto entre los dos ojos.

Un pequeño ejemplo para bien entender:

Primero, requisito obligatorio: instalar la version 4.0 desde  el AVD manager, cuando se ejecuta el update seleccionamos la API 15.
Cuando este hecho, ya se puede crear un proyecto con el sdk de android 4.0.

Una vez el proyecto creado, vamos a poder modificar nuestra Activity. Tenemos que crear una simple clase que extienda el Objeto View.

 
 
 
 
 

Vamos a crear una función constructor, ahi donde cargaremos nuestro Bitmap quien se encuentra en nuestra carpeta Drawable

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

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

– Empezamos por definir el tipo de nuestro Bitmap en RGB_265. Cuando es una condicion del buen funcionamiento de la clase FaceDetector.
– Cargamos nuestro Bitmap que se encuentra en nuestra carpeta Drawable con la ayuda de la Clase BitmapFactory y mas precisamente con la ayuda del metodo decodeResource.

Una vez nuestra imagen cargada, hay que recuperar el ancho, y el largo de la imagen.

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

Ahora, hay que crear una instancia de la clase FaceDetector y llamar el metodo finFaces para recuperar toda la lista de los rostros encontrados en el 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);

– Definemos el maximo de rostros a detectar en la imagen. el valor maximo soportada es 64.
– Creamos una instancia de la clase FaceDetector, pasandole el alto y el ancho de la imagen, y el numero de rostros a detectar.
– Creamos un areglo, que nos permite donde guardar en stock la lista de los rostros encontrados.
– Luego llamamos al metodo findFaces pasandole una imagen y un areglo a llenar
Entonces recorremos la lista de rostros, y recuperamos el rostro en cuestión. En cada instancia del rostro, recuperamos las diferentes valores que que necesitamos en el resto de nuestro proyecto.

– el punto se encuentra en el medio, entre los dos ojos, con el metodo getMidPoint
– La distancia entre los dos ojos, con la ayuda del metodo 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();
    }
}

Aqui el resultado final:

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

Luego, sobre escribimos el metodo onDraw para redibujar nuestra View y indicar los rostros detectados.

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

– Definimos un color para el dibujo de los circulos y otro para deibujar la imagen.
– Redibujamos nuestra imagen.
– Recorremos los diferentes rostros y dibujamos un circulo como centro, el punto entre los dos ojos del rostro.

Y aqui pueden ver el codigo completo de la clase en el código fuente del proyecto.

Les dejo aqui el enlace para descargarlo.

Este articulo fue escrito por Benbourahla Nazim. fuente: tutos-android.com

Nazim Benbourahla
Igeniero en desarrollo especializado en Android en la empresa ATOS.
Nazim Benbourahla

Latest posts by Nazim Benbourahla (see all)

About Nazim Benbourahla

Igeniero en desarrollo especializado en Android en la empresa ATOS.
This entry was posted in Android. Bookmark the permalink.

Deja un comentario

  • Facebook AndroidCol