Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Android

Una introducción a la detección de rostros en Android

by
Difficulty:IntermediateLength:LongLanguages:

Spanish (Español) translation by CYC (you can also view the original English article)

Introducido con las bibliotecas de Vision en Play Services 8.1, Face Detection te facilita, como desarrollador, analizar un video o una imagen para localizar rostros humanos. Una vez que tienes una lista de caras detectadas en una imagen, puedes recopilar información sobre cada cara, como orientación, probabilidad de sonreír, si alguien tiene los ojos abiertos o cerrados y puntos de referencia específicos en su rostro.

Esta información puede ser útil para múltiples aplicaciones, como una aplicación de cámara que toma automáticamente una foto cuando todos en el cuadro sonríen con los ojos abiertos o para aumentar las imágenes con efectos tontos, como los cuernos de unicornio. Es importante tener en cuenta que la detección de rostros no es un reconocimiento facial. Si bien se puede recopilar información sobre un rostro, la biblioteca de Visión no utiliza esa información para determinar si dos caras provienen de la misma persona.

Este tutorial utilizará una imagen fija para ejecutar la API de detección de rostros y recopilar información sobre las personas en la foto, al tiempo que ilustra esa información con gráficos superpuestos. Todo el código para este tutorial se puede encontrar en GitHub.

Example of a silly effect adding a unicorn horn to a face

1. Configuración del proyecto

Para agregar la biblioteca de Vision a tu proyecto, debes importar Play Services 8.1 o superior. Este tutorial solo importa la biblioteca Play Services Vision. Abre el archivo build.gradle de tu proyecto y agrega la siguiente línea de compilación al nodo de dependencias.

Una vez que hayas incluido Play Services en tu proyecto, puedes cerrar el archivo build.gradle de tu proyecto y abrir AndroidManifest.xml. Debes agregar un elemento de meta-data que defina la dependencia de la cara en el nodo application de tu manifiesto. Esto le permite a la biblioteca de Vision saber que tienes previsto detectar rostros dentro de tu aplicación.

Una vez que hayas terminado de configurar AndroidManifest.xml, puedes continuar y cerrarlo. A continuación, debes crear una nueva clase llamada FaceOverlayView.java. Esta clase extiende View y contiene la lógica para detectar caras en el proyecto, mostrando el mapa de bits que se analizó y dibujando en la parte superior de la imagen para ilustrar los puntos.

Por ahora, comienza agregando las variables miembro en la parte superior de la clase y definiendo los constructores. El objeto Bitmap se utilizará para almacenar el mapa de bits que se analizará y los objetos SparseArray de Face almacenarán cada cara que se encuentre en el mapa de bits.

A continuación, agrega un nuevo método dentro de FaceOverlayView llamado setBitmap (Bitmap bitmap). Por ahora, esto simplemente guardará el mapa de bits que se le pasó, sin embargo, más adelante utilizarás este método para analizar la imagen.

Luego, necesitas un mapa de bits. He incluido uno en el proyecto de muestra en GitHub, pero puedes usar cualquier imagen que desees para jugar con Face Detection y ver qué funciona y qué no. Cuando hayas seleccionado una imagen, colócala en el directorio res/raw. Este tutorial supondrá que la imagen se llama face.jpg.

Después de haber colocado tu imagen en el directorio res/raw, abre res/layout/activity_main.xml. Este diseño contiene una referencia a FaceOverlayView para que se muestre en MainActivity.

Con el diseño definido, abre MainActivity y configura FaceOverlayView desde onCreate(). Para ello, obtén una referencia a la vista, lee el archivo de imagen face.jpg del directorio sin formato como flujo de entrada y conviértelo en un mapa de bits. Una vez que tengas el mapa de bits, puedes llamar a setBitmap en FaceOverlayView para pasar la imagen a tu vista personalizada.

2. Detectando Caras

Ahora que tu proyecto está configurado, es hora de comenzar a detectar caras. En setBitmap (Bitmap bitmap) necesitas crear un FaceDetector. Esto se puede hacer utilizando un FaceDetector.Builder, que te permite definir múltiples parámetros que afectan la rapidez con que se detectarán las caras y qué otros datos generará FaceDetector.

La configuración que elijas dependerá de lo que estés intentando hacer en tu aplicación. Si habilitas la búsqueda de puntos de referencia, las caras se detectarán más lentamente. Al igual que con la mayoría de las cosas en la programación, todo tiene sus ventajas y desventajas. Para obtener más información sobre las opciones disponibles para FaceDetector.Builder, puedes encontrar la documentación oficial en el sitio web para desarrolladores Android.

También necesitas un control para ver si FaceDetector está operativo. Cuando un usuario usa la detección de rostros por primera vez en su dispositivo, Play Services debe salir y obtener un conjunto de pequeñas bibliotecas nativas para procesar la solicitud de su aplicación. Aunque esto casi siempre se hará antes de que tu aplicación haya terminado de iniciarse, es importante manejar la contingencia de que esto ha fallado.

Si FaceDetector está operativo, puedes convertir su mapa de bits en un objeto Frame y pasarlo al detector para recopilar datos sobre las caras en la imagen. Cuando hayas terminado de detectar rostros, invoca invalidate() para activar el redibujado de la vista. Cuando hayas terminado de detectar rostros, invoca invalidate() para activar el redibujado de la vista.

Ahora que has detectado las caras en tu imagen, es hora de usarlas. Para este ejemplo, simplemente dibujarás un cuadro verde alrededor de cada cara. Como se llamó a invalidate() después de que se detectaron las caras, puedes agregar toda la lógica necesaria en onDraw (Canvas canvas). Este método asegura que el mapa de bits y las caras están configurados, luego dibuja el mapa de bits en el lienzo y luego dibuja un cuadro alrededor de cada cara.

Dado que los diferentes dispositivos tienen diferentes tamaños de pantalla, también se hará un seguimiento del tamaño de la escala de bits para que toda la imagen esté siempre visible en el dispositivo y todas las superposiciones se dibujen adecuadamente.

El método drawBitmap (Canvas canvas) dibuja su mapa de bits en el lienzo y lo dimensiona de forma adecuada al mismo tiempo que devuelve un multiplicador para escalar sus otras dimensiones correctamente.

El método drawFaceBox (Canvas canvas, double scale) se vuelve un poco más interesante. Cada cara que se detectó y guardó tiene un valor de posición arriba y a la izquierda de cada cara. Este método tomará esa posición y dibujará un rectángulo verde a partir de él para abarcar cada cara en función de su ancho y alto.

Debes definir tu objeto Paint y luego recorrer cada Face en tu SparseArray para encontrar su posición, ancho y alto, y dibujar el rectángulo en el lienzo usando esa información.

En este punto, deberías poder ejecutar tu aplicación y ver tu imagen con rectángulos alrededor de cada cara que se ha detectado. Es importante tener en cuenta que la API de detección de rostros todavía es bastante nueva en el momento de escribir este documento y es posible que no detecte todos los rostros. Puedes jugar con algunas de las configuraciones en el objeto FaceDetector.Builder para, afortunadamente, recopilar más datos, aunque no está garantizado.

Faces detected and bound by a drawn rectangle

3. Comprender los hitos

Los puntos de referencia son puntos de interés en una cara. La API de detección de rostros no usa puntos de referencia para detectar una cara, sino que más bien detecta una cara en su totalidad antes de buscar puntos de referencia. Es por eso que descubrir puntos de referencia es una configuración opcional que se puede habilitar a través del FaceDetector.Builder.

Puedes utilizar estos puntos de referencia como una fuente de información adicional, como por ejemplo dónde están los ojos del sujeto, para que pueda reaccionar adecuadamente dentro de tu aplicación. Hay doce puntos de referencia que se pueden encontrar:

  • ojo izquierdo y derecho
  • oreja izquierda y derecha
  • punta de oído izquierdo y derecho
  • base de la nariz 
  • mejilla izquierda y derecha
  • esquina izquierda y derecha de la boca
  • base de la boca

Los puntos de referencia disponibles dependen del ángulo de la cara detectada. Por ejemplo, alguien mirando hacia un lado solo tendrá un ojo visible, lo que significa que el otro ojo no será detectable. La siguiente tabla describe qué puntos de referencia deberían ser detectables según el ángulo Y de Euler (dirección izquierda o derecha) de la cara.

Euler Y Puntos de referencia visibles
<-36 ° ojo izquierdo, boca izquierda, oreja izquierda, base nasal, mejilla izquierda
-36° a -12° boca izquierda, base de la nariz, boca inferior, ojo derecho, ojo izquierdo, mejilla izquierda, punta de la oreja izquierda
-12° a 12° ojo derecho, ojo izquierdo, base de la nariz, mejilla izquierda, mejilla derecha, boca izquierda, boca derecha, boca inferior
12° a 36° ojo derecho, ojo izquierdo, base de la nariz, mejilla izquierda, mejilla derecha, boca izquierda, boca derecha, boca inferior
> 36° ojo derecho, boca derecha, oreja derecha, base de nariz, mejilla derecha

Los puntos de referencia también son increíblemente fáciles de usar en tu aplicación, ya que los has incluido durante la detección de rostros. Simplemente necesitas llamar a getLandmarks() en un objeto Face para obtener una lista de objetos Landmark con los que puedes trabajar.

En este tutorial, pintarás un pequeño círculo en cada punto de referencia detectado llamando a un nuevo método, drawFaceLandmarks (Canvas canvas, double scale), de onDraw (canvas canvas) en vez de drawFaceBox (Canvas canvas, double scale). Este método toma la posición de cada punto de referencia, lo ajusta a la escala del mapa de bits y luego muestra el círculo indicador de punto de referencia.

Después de llamar a este método, deberías ver pequeños círculos verdes que cubren las caras detectadas, como se muestra en el siguiente ejemplo.

Circles placed over detected facial landmarks

4. Datos faciales adicionales

Si bien la posición de una cara y sus puntos de referencia son útiles, también puedes encontrar más información sobre cada cara detectada en tu aplicación a través de algunos métodos integrados del objeto Face. Los métodos getIsSmilingProbability()getIsLeftEyeOpenProbability() y getIsLightEyeOpenProbability() intentan determinar si los ojos están abiertos o si la persona detectada sonríe al devolver un float que va de 0.0 1.0. Cuanto más cerca de 1.0, es más probable que la persona esté sonriendo o tenga abierto el ojo izquierdo o derecho.

También puedes encontrar el ángulo de la cara en los ejes Y y Z de una imagen al verificar sus valores de Euler. El valor de Z Euler siempre se informará, sin embargo, debes usar el modo preciso cuando detectes rostros para recibir el valor X. Puedes ver un ejemplo de cómo obtener estos valores en el siguiente fragmento de código.

Conclusión

En este tutorial, has aprendido acerca de uno de los componentes principales de la biblioteca de Play Services Vision, Face Detection. Ahora sabes cómo detectar rostros en una imagen fija, cómo reunir información y encontrar puntos de referencia importantes para cada rostro.

Usando lo que has aprendido, deberías poder agregar algunas características excelentes a tus propias aplicaciones para aumentar las imágenes fijas, las pistas de seguimiento en una transmisión de video o cualquier otra cosa que puedas imaginar.

Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.