Cachorros con lentes y bigotes utilizando Dlib

Hipsterizando fotos de perros con Deep Learning y Dlib

--

Quienes trabajamos en el campo de la Inteligencia Artificial a menudo nos vemos abrumados por la enorme cantidad de conceptos y disciplinas que este campo envuelve. Distribuciones de probabilidades, cálculo diferencial, cálculo de matrices, estructuras de datos y algoritmos… Realmente se puede volver un verdadero dolor de cabeza 🤯

Sin embargo lo que nunca perdemos es el humor y la habilidad para llevar estos conceptos complejos, a problemas simples, cotidianos y divertidos 🤣

Este tutorial se trata justamente de esto, cómo tomar algunos conceptos medianamente complejos de Machine Learning y Computer Vision, y aplicarlos en particular para “hipsterizar” fotos de perritos de forma automática🐶 + 💻 = 🎩.

Antes de arrancar, me parece pertinente aclarar que este ejemplo lo tomé prestado de un conjunto de ejemplos de problemas resueltos, que tiene implementados la biblioteca Dlib.

Ahora si empecemos viendo primero un poco de qué se trata esta biblioteca.

Dlib es una biblioteca de herramientas y algoritmos de Machine Learning y procesamiento de imágenes, desarrollada en C++. Contiene implementaciones de algoritmos SVM para problemas de regresión lineal y clasificación, métodos de clusterización como K-Means y un módulo de modelos de deep learning, entre otros.

Es utilizada tanto en la industria como en la academia por su versatilidad para resolver problemas en diferentes dominios. Además se puede descargar sin costo y extender en función de las necesidades que tengamos, gracias a su licencia open source.

Por último y no menos importante, una parte de su API se encuentra disponible en Python!!!

Estrategia

El objetivo es reconocer rostros de perros en una imagen y luego dibujarles automáticamente en un par de lentes y un bigote a cada uno. Esto se puede resumir sencillamente en 3 pasos:

  1. Detección de todos los perros en una foto y en particular de las coordenadas de sus bounding boxes. Una bounding box es sencillamente un cuadrado o rectángulo que encierra el rostro del perro. Queda definida por las coordenadas en la imagen en la que se encuentra el rostro: por ejemplo la posición <x, y> del vértice superior izquierdo de la bounding box y los valores de ancho y largo de la misma.
  2. Reconocimiento de los landmarks del rostro. Esto es ciertos puntos característicos del rostro como los ojos y el hocico, que luego nos servirán para posicionar en el lugar correcto los lentes y el bigote.
  3. Dibujar una máscara compuesta por los lentes y un bigote sobre el rostro del perro en la posición correcta y con el tamaño y alineación adecuado.
Foto procedimiento para reconocer y hipzterizar perro en una foto
Detección perro + Reconocimiento Landmarks + Colocación máscara

Para hacer todo esto que parece ultra complejo, vamos a utilizar algunos métodos del módulo de deep learning de Dlib junto con un ejemplo que viene con la propia biblioteca. Lamentablemente no se encuentra disponible en Python, por lo que voy a tener que recurrir a mis olvidados y rudimentarios conocimientos de C++.

Instalación Dlib

Comenzamos instalando Dlib. En mi caso, lo voy a hacer descargando directamente el código fuente de su repositorio en Github y compilarlo siguiendo las instrucciones que se indican en el repositorio. Vale la pena aclarar que en mi caso, hice todas las pruebas en Ubuntu pero seguramente todo es replicable en Mac OS o Windows.

  1. Clonar repositorio
    $ git clone https://github.com/davisking/dlib.git
  2. Build de ejemplos y sus dependencias con la bibloteca — Dentro de la carpeta “examples” ejecutar
    $ mkdir build; cd build; cmake .. ; cmake --build

Una vez que terminó el proceso de compilación, se crea una carpeta de nombre build dentro de la cual se encuentran todos los ejemplos compilados prontos para usar. En particular vamos a utilizar el archivo de nombre dnn_mmod_dog_hipsterizer.cpp con algunas modificaciones mínimas para facilitar su uso.

Analizando el código del ejemplo

Veamos que hay dentro del archivo dnn_mmod_dog_hipsterizer.cpp a ver si podemos entender como funciona.

La primera parte no tiene nada interesante, simplemente se incluyen las dependencias y se definen algunos templates.

Luego tenemos el cuerpo principal del script y algunas definiciones importantes. Primero se definen los modelos que utilizaremos para detectar los perros y predecir el contorno de su rostro, incluyendo las posiciones de sus ojos y hocico. Este modelo en particular, es un modelo basado en una CNN (Red Neuronal Convolucional), entrenada sobre un conjunto de datos de 9000 fotos de perros, de diferentes razas, nacionalidades, etc. El modelo pre-entrenado se encuentra disponible aquí.

Después viene la parte donde comienza la verdadera magia… Para cada imagen con la que se invoca el script:

  • Línea 5-6: Se carga la imagen en la variable img utilizando el método load_image
  • Línea 12: Utiliza la CNN definida como net para detectar cada perro en la foto. Guarda el resultado en variable dets.
  • Línea 13–17: Define algunos objetos que vamos a usar para mostrar la imagen resultado
  • Línea 18–29: Procesa cada detección y obtiene las coordenadas de ojos y hocico del perro. En particular en la línea 21 se obtienen las landmarks del perro utilizando el modelo shape_predictor.
  • Línea 35–46: Dibuja los lentes sobre el rostro, utilizando una imagen de lentes previamente cargada como una matriz RGB en la variable glasses.
  • Línea 48–61: Dibuja el bigote sobre el rostro, utilizando una imagen de un bigote también previamente cargada como una matriz RGB en la variable musstache.
  • Línea 64–74: Aprovecha cada uno de los landmarks encontrados y calcula las rectas entre ellos, para finalmente dibujarlos sobre una ventana a partir de la imagen original. Esto puede resultar útil para debugear el script y entender que tan bien o mal está el modelo detectando perros.
  • Línea 75: Muestra el resultado en una ventana diferente.

Por último se agregan algunas líneas adicionales para procesar el resto de las fotos.

Personalmente me pareció super divertido el ejemplo que trae Dlib, sin embargo sería mucho más práctico además de visualizar los resultados, guardar la imagen resultado para poder compartirla con mis amigos. Para hacer esto, sencillamente agregue la siguiente línea casi al final del código, en la que utilizo el método save_png de la propia biblioteca y guardo el objeto img que a esta altura contiene la foto original con todas las máscara. Además, como nombre utilizo el nombre de la imagen, que se encuentra disponible como argumento, seguido del sufijo “_hipster”.

Eso es todo, esa es la magia detrás del script dnn_mmod_dog_hipsterizer.cpp. Veamos ahora cómo invocarlo y que resultados obtenemos.

El proceso de instalación de Dlib debería habernos generado un archivo binario en la carpeta dlib/examples/build. Desde dicha carpeta invocamos al script dnn_mmod_dog_hipsterizer de la siguiente forma:

./dnn_mmod_dog_hipsterizer mmod_dog_hipsterizer.dat dog.jpg

Notar que es necesario pasarle el modelo pre-entrenado para detectar los perros, además de la foto que queremos procesar. También podemos pasar más de una foto de una vez:

./dnn_mmod_dog_hipsterizer mmod_dog_hipsterizer.dat dog.jpg dog2.jpg dog3.jpg

Pero que ¡woof! más sofisticado

Ahora que sabes cómo utilizar Dlib para hipsterizar perros es momento de ponerte a jugar y ver los resultados con tus fotos favoritas!!

Ejemplo de un perro hispterizado
Ejemplo de un perro hispterizado
Ejemplo de un perro hispterizado

Como todo modelo de Inteligencia Artificial, tiene sus limitaciones y no funciona a la perfección en todos los escenarios. Por ejemplo, si un perro no se encuentra mirando directamente a la cámara, el modelo de detección de perros lo pasa por alto o incluso lo detecta de forma imprecisa. En resumen la foto no va a quedar todo lo genial que quisiéramos 😕

Ejemplo de un perro hispterizado que no queda tan bien

¿Por qué limitarse solamente a perros? Proba también con fotos de otros animales parecidos a perros, por ejemplo un oso pardo o un león.

Ejemplo hipsterizando una foto de un oso pardo
Ejemplo hipsterizando una foto de un golden retriever disfrazado de leon

PD: Dejo el código original de Dlib incluyendo el código del script dnn_mmod_dog_hipsterizer con las modificaciones realizadas y los ejemplos de fotos de perros utilizados en este tutorial, en el siguiente repositorio Github.

--

--

Emiliano Viotti
IDATHA // Enterprise Experience & Academic´s

Machine Learning Director at IDATHA.com — AI Builder — CV and NLP practitioner — Hungry reader and stories writer — Former professor at Fing UdelaR.