Este tutorial le mostrará cómo crear GIF animados usando OpenCV, Python e ImageMagick. ¡Luego combina estos métodos para crear un generador de memes con OpenCV!
Todos necesitamos reírnos de vez en cuando. Y quizás la mejor manera de encontrar a Lulza es con memes. Algunos de mis favoritos:
- Kermit the Frog: "Pero no es asunto mío"
- Gato gruñón
- Fracaso épico
- Buen chico greg
Pero para mí personalmente, ninguno de estos memes puede compararse con el meme "Lidia con él" ("Lidia con él" o "Comprendelo tú mismo"), un ejemplo del cual se da al comienzo del artículo.Por lo general, se usa en los siguientes casos:
- Como una respuesta u objeción a alguien que no aprueba algo que usted ha hecho / dicho ("Enfréntelo")
- Ponerse las gafas como si se fuera y dejar a la persona sola con el problema ("Comprenda usted mismo")
Hace unos años leí un artículo divertido en el blog del autor, que no recuerdo cómo generar esos memes usando la visión por computadora. La semana pasada no pude encontrar esta guía en ningún lado, así que como blogger, experto en visión artificial y conocedor de memes, ¡decidí escribir un tutorial yo mismo! (Por cierto, si accidentalmente conoce la fuente original, avíseme para agradecerle al autor.
UPD: Acabo de encontrar el artículo original del blog
MakeArtWithPython de Kirk Kaiser).
El desarrollo de un generador de memes en OpenCV nos enseñará varias habilidades prácticas valiosas, que incluyen:
- Detección de rostros utilizando técnicas de aprendizaje profundo
- Usando la biblioteca dlib para detectar puntos de referencia faciales y extraer áreas de los ojos
- Cómo calcular el ángulo de rotación entre los ojos en función de la información recibida
- Y finalmente, cómo generar GIF animados usando OpenCV (con un poco de ayuda de ImageMagick)
Esta guía debe ser divertida y entretenida y, al mismo tiempo, enseñarle valiosas habilidades de programación de visión por computadora que son útiles en el mundo real.
Crear GIF con OpenCV
En la primera parte de la guía, discutiremos las condiciones y dependencias necesarias para este proyecto, incluida la configuración adecuada del entorno de desarrollo.
Luego considere la estructura del proyecto / catálogo para nuestro generador de GIF OpenCV.
Tan pronto como comprendamos la estructura del proyecto, consideraremos: 1) nuestro archivo de configuración; 2) el script Python responsable de crear GIF con OpenCV.
Finalmente, evaluaremos los resultados del programa sobre el popular meme "Deal With It".
Prerrequisitos y dependencias
Fig. 1. Usaremos OpenCV, dlib e ImageMagick para crear GIFOpencv y dlib
Se necesita OpenCV para determinar las caras en el marco y el procesamiento básico de imágenes. Siga una de mis
guías de instalación de OpenCV si OpenCV no
está instalado en el sistema.
Usamos Dlib para detectar puntos de referencia faciales, lo que nos permite encontrar dos ojos en la cara y ponernos gafas de sol. Puede
instalar dlib usando estas instrucciones .
Imagemagick
Si no está familiarizado con
ImageMagick , entonces en vano. Es una herramienta de línea de comandos multiplataforma con muchas funciones de procesamiento de imágenes.
¿Quieres convertir PNG / JPG a PDF con un solo comando? No hay problema
¿Hay varias imágenes de las que necesita hacer un PDF de varias páginas? Fácilmente
¿Necesita dibujar polígonos, líneas y otras formas? Y es posible.
¿Qué tal la clasificación de color por lotes o el cambio de tamaño de todas las imágenes con un comando? Para hacer esto, no necesita escribir algunas líneas en Python para OpenCV.
ImageMagick también genera GIF a partir de cualquier imagen.
Para instalar ImageMagick en Ubuntu (o Raspbian) simplemente use apt:
Crear GIF con OpenCVShell
$ sudo apt-get install imagemagick
En macOS, puede usar HomeBrew:
$ brew install imagemagick
inútiles
En la mayoría de los artículos, cursos y libros, utilizo mi conveniente
paquete de procesamiento de imágenes
imutils . Se instala en un sistema o entorno virtual utilizando pip:
$ pip install imutils
Estructura del proyecto
Fig. 2. La estructura del proyecto incluye dos directorios, un archivo de configuración y un script PythonHay dos catálogos en nuestro proyecto:
images/
: ejemplos de imágenes de entrada para las que queremos hacer un GIF animado. Encontré algunas imágenes conmigo, pero siéntase libre de agregar las suyas.assets/
: esta carpeta contiene nuestro detector de rostro, detector de hito facial y todas las imágenes + máscaras relacionadas. Con estos recursos, colocaremos puntos y texto en las imágenes originales de la primera carpeta.
Debido a la gran cantidad de parámetros configurables, decidí crear un archivo de configuración JSON, que: 1) facilitará la edición de parámetros; 2) requerirá menos argumentos de línea de comando. Todos los parámetros de configuración necesarios para este proyecto están contenidos en
config.json
.
Considere los contenidos de
config.json
y
create_gif.py
.
Nota Per .: El código del proyecto y el manual de 17 páginas sobre visión por computadora, aprendizaje automático y OpenCV se emiten después del registro (espejo: código fuente , manual ).Generación GIF con OpenCV
¡Entonces, continuemos y comencemos a crear nuestro generador de GIF OpenCV!
Contenido del archivo de configuración JSON
Comencemos con el archivo de configuración JSON y luego pasemos al script Python.
Abra un nuevo archivo
config.json
e inserte los siguientes pares clave / valor:
Crear GIF con OpenCVPython
{ "face_detector_prototxt": "assets/deploy.prototxt", "face_detector_weights": "assets/res10_300x300_ssd_iter_140000.caffemodel", "landmark_predictor": "assets/shape_predictor_68_face_landmarks.dat",
Estos son archivos de modelo de
detector de rostro OpenCV en aprendizaje profundo .
La última línea es la ruta al predictor de cara dlib.
Y ahora tenemos algunas rutas a los archivos de imagen:
"sunglasses": "assets/sunglasses.png", "sunglasses_mask": "assets/sunglasses_mask.png", "deal_with_it": "assets/deal_with_it.png", "deal_with_it_mask": "assets/deal_with_it_mask.png",
Estos son los caminos a nuestras gafas de sol, texto y máscaras a juego para ellos, que se muestran a continuación.
En primer lugar, gafas de sol elegantes y una máscara:
Fig. 3. ¿No te gustan las gafas con píxeles? Solo aguantaloFig. 4. ¿No entiendes por qué necesitas una máscara para gafas de sol? Solo aguantalo, o lee el resto del artículo para obtener la respuesta.Y ahora nuestro texto es "TRATE CON ÉL" y la máscara:
Fig. 5. ¿Odias Helvetica Neue Condensed? Lidiar con esoFig. 6: Esta máscara te permite dibujar un borde alrededor del texto. Oh, tal vez no quieras, ¿quieres un borde? Bueno, aguantaloSe necesitan máscaras para superponer la imagen correspondiente en la foto: trataremos esto más adelante.
Ahora configure algunos parámetros para el generador de memes:
"min_confidence": 0.5, "steps": 20, "delay": 5, "final_delay": 250, "loop": 0, "temp_dir": "temp" }
Aquí están las definiciones para cada uno de los parámetros:
min_confidence
: min_confidence
mínima requerida de detección de rostros.steps
: número de cuadros en la animación final. Cada "paso" mueve las gafas de sol desde el borde superior hacia el objetivo (es decir, hacia los ojos).delay
: retraso entre cuadros en centésimas de segundo.final_delay
: retraso del último fotograma en centésimas de segundo (útil en este contexto, ya que queremos que el texto se muestre más tiempo que el resto de los fotogramas).loop
: un valor cero indica que el GIF se repite para siempre; de lo contrario, especifique un número entero positivo para el número de repeticiones de la animación.temp_dir
: el directorio temporal en el que se almacenarán cada uno de los marcos antes de crear el GIF final.
Memes, GIF y OpenCV
Creamos el archivo de configuración JSON, ahora pasemos al código real.
Abra un nuevo archivo,
create_gif.py
nombre
create_gif.py
y pegue el siguiente código:
Aquí importamos los paquetes necesarios. En particular, usaremos imutils, dlib y OpenCV. Para instalar estas dependencias, consulte la sección Requisitos previos y dependencias más arriba.
Ahora el script tiene los paquetes necesarios, así
overlay_image
definamos la función
overlay_image
:
def overlay_image(bg, fg, fgMask, coords):
La función
overlay_image
impone un primer plano (
fg
) en la parte superior de la imagen de fondo (
bg
) en las coordenadas de las coordenadas
( coordenadas
(x, y) ), realizando la transparencia alfa sobre la máscara de primer plano
fgMask
.
Para familiarizarse con los conceptos básicos de OpenCV, como trabajar con máscaras, asegúrese de leer
esta guía .
Para completar el proceso de mezcla, realice una mezcla alfa:
def alpha_blend(fg, bg, alpha):
Esta implementación de mezcla alfa también está disponible
en el blog LearnOpenCV .
En esencia, convertiremos el primer plano, el fondo y el canal alfa a números de coma flotante en el rango
[0, 1] . Luego realizamos una mezcla alfa, agregamos el primer plano y el fondo para obtener el resultado de que volvemos a la función de llamada.
También crearemos una función auxiliar que permita generar GIF a partir de un conjunto de rutas de imagen utilizando ImageMagick y el comando de
convert
:
def create_gif(inputPath, outputPath, delay, finalDelay, loop):
La función
create_gif
toma un conjunto de imágenes y las recopila en animaciones GIF con un retraso especificado entre cuadros y bucles. ImageMagick procesa todo esto: simplemente envolvemos el comando de
convert
en una función que procesa dinámicamente varios parámetros.
Para ver los argumentos de
convert
disponibles,
consulte la documentación . ¡Allí verá cuántas funciones tiene este equipo!
Específicamente en esta función, nosotros:
- Tome
imagePaths
. - Elija la ruta de la última imagen, que tendrá un retraso por separado.
- Reasigne
imagePaths
para excluir la última ruta. - Ensamblamos un comando con argumentos de línea de comando y luego le indicamos al sistema operativo que
convert
para crear animaciones GIF.
Asigne al script sus propios argumentos de línea de comando:
Tenemos tres argumentos de línea de comandos que se procesan en tiempo de ejecución:
--config
: ruta al archivo de configuración JSON. Revisamos el archivo de configuración en la sección anterior.--image
: ruta a la imagen de entrada contra la cual se crea la animación (es decir, detectar una cara, agregar gafas de sol y luego texto).--output
: ruta al GIF resultante.
Cada uno de estos argumentos es obligatorio al ejecutar el script en la línea de comando / terminal.
Descargue el archivo de configuración, así como las gafas y la máscara correspondiente:
Aquí cargamos el archivo de configuración (que puede estar disponible en el futuro como un diccionario Python). Luego cargue las gafas de sol y la máscara.
Si queda algo del script anterior, elimine el directorio temporal y vuelva a crear el directorio temporal vacío. La carpeta temporal contendrá cada cuadro individual de la animación GIF.
Ahora cargue el
detector facial de aprendizaje profundo OpenCV en la memoria:
Para hacer esto, llame a
cv2.dnn.readNetFromCaffe
. El módulo
dnn
solo está disponible en OpenCV 3.3 o posterior. Un detector de rostros detectará la presencia de rostros en la imagen:
Fig. 7. Operación del detector de rostros usando OpenCV DNNA continuación, cargue el
predictor de hito de cara dlib . Le permitirá localizar estructuras individuales: ojos, cejas, nariz, boca y mentón:
Fig. 8. Los puntos de referencia descubiertos por dlib se superponen en mi caraMás adelante en este guión extraemos solo el área de los ojos.
Continuando, busquemos la cara:
En este bloque hacemos lo siguiente:
- Descargue la
image
original. - Construimos una
blob
para enviar al detector facial de una red neuronal. Este artículo describe cómo funciona blobFromImage
de OpenCV. - Realice el procedimiento de detección de rostros.
- Encontramos a la persona con el valor de probabilidad más alto y lo comparamos con el umbral de probabilidad mínimo aceptable. Si no se cumplen los criterios, simplemente salga del script. De lo contrario, continúe.
Ahora extraeremos la cara y calcularemos los puntos de referencia:
Para extraer la cara y encontrar puntos de referencia faciales, hacemos lo siguiente:
- Extraemos las coordenadas del cuadro delimitador alrededor de la cara.
- Cree un objeto
rectangle
en dlib y aplique la localización de caras. - Recuperamos las coordenadas (x, y) de
leftEyePts
y rightEyePts
, respectivamente.
Dadas las coordenadas de los ojos, puede calcular dónde y cómo colocar las gafas de sol:
Primero, calculamos el centro de cada ojo, luego el ángulo entre los centroides. La misma operación se realiza con la
alineación horizontal
de la cara en el marco .
Ahora puede rotar y cambiar el tamaño de las gafas. Tenga en cuenta que utilizamos
la función rotate_bound , no solo
rotate , de modo que OpenCV no recorta partes que no son visibles después de la conversión afín.
Las mismas operaciones que se aplicaron a las gafas, se aplican a la máscara. Pero primero debe convertirlo a tonos de gris y binarizar, porque las máscaras siempre son binarias. Luego giramos y redimensionamos la máscara de la misma manera que lo hicimos con los anteojos.
Nota: tenga en cuenta que al cambiar el tamaño de la máscara, usamos interpolación para los puntos vecinos más cercanos, porque la máscara debe tener solo dos valores (0 y 255). Otros métodos de interpolación son más estéticos, pero no adecuados para máscaras. Aquí puede obtener información adicional sobre la interpolación en los puntos vecinos más cercanos.Los tres bloques de código restantes crean marcos para la animación GIF:
Las gafas caen desde la parte superior de la imagen. En cada cuadro, se muestran más cerca de la cara hasta que cubren sus ojos. Usando la variable
"steps"
en el archivo de configuración JSON, generamos coordenadas y para cada cuadro. Para hacer esto, sin mucho esfuerzo, usamos la función
linspace
de NumPy.
Las líneas con un ligero desplazamiento hacia la izquierda y hacia arriba pueden parecer un poco extrañas, pero son necesarias para garantizar que las gafas cubran los ojos en su conjunto y no solo se muevan hasta el punto donde se encuentra el centro del ojo. Determiné empíricamente porcentajes para calcular el desplazamiento a lo largo de cada eje. La siguiente línea asegura que no haya valores negativos.
Usando la función
overlay_image
, generamos el marco de
output
final.
Ahora aplique el texto "TRATE CON EL" usando otra máscara:
En el último paso, imponemos el texto, que en realidad es otra imagen.
Decidí usar una imagen porque las capacidades de representación de las fuentes OpenCV son bastante limitadas. Además, quería agregar una sombra y un borde alrededor del texto, que de nuevo OpenCV no sabe cómo.
En el resto de este código, cargamos tanto la imagen como la máscara, y luego realizamos una mezcla alfa para generar el resultado final.
Solo queda guardar cada fotograma en el disco con la creación posterior de animación GIF:
Escribimos el resultado en el disco. Después de generar todos los cuadros, llamamos a la función
create_gif
para crear el archivo de animación GIF. Recuerde que este es un shell que pasa parámetros a la herramienta de línea de comandos de
convert
ImageMagick.
Finalmente, elimine el directorio de salida temporal y los archivos de imagen individuales.
Resultados
Ahora la parte divertida: ¡veamos qué creó nuestro generador de memes!
Asegúrese de
descargar el código fuente, las imágenes de muestra y los modelos de aprendizaje profundo. Luego abra una terminal y ejecute el siguiente comando:
$ python create_gif.py --config config.json --image images/adrian.jpg \ --output adrian_out.gif [INFO] loading models... [INFO] computing object detections... [INFO] creating GIF... [INFO] cleaning up...
Figura 9. Animación GIF generada con OpenCV e ImageMagick con este script de PythonAquí puede ver el GIF creado con OpenCV e ImageMagick. Se realizan las siguientes acciones en él:
- Detección correcta de mi cara.
- Localización de los ojos y cálculo de sus centros.
- Las gafas caen correctamente sobre la cara.
Los lectores de mi blog saben que soy un gran nerd en Jurassic Park y a menudo lo mencionan en mis libros, cursos y guías de estudio.
¿No te gusta
Jurassic Park ?
Ok, aquí está mi respuesta:
$ python create_gif.py --config config.json --image images/adrian_jp.jpg \ --output adrian_jp_out.gif [INFO] loading models... [INFO] computing object detections... [INFO] creating GIF... [INFO] cleaning up...
Fig. 10. Animación GIF de OpenCV basada en una fotografía de la proyección reciente de Jurassic World 2Aquí estoy en el espectáculo "Jurassic World: 2" en una camiseta temática, con un vaso de luz y un libro de colección.
Historia divertida:
Hace cinco o seis años, mi esposa y yo visitamos el parque temático Epcot Center en Disney World, Florida.
Decidimos hacer un viaje para alejarnos de los duros inviernos en Connecticut, y necesitábamos desesperadamente la luz del sol.
Desafortunadamente, en Florida llovió todo el tiempo y la temperatura apenas superó los 10 ° C.
Cerca de los jardines canadienses, Trisha me tomó una foto: dice que me veo como un vampiro con piel pálida, ropa oscura y una capucha, en el contexto de los exuberantes jardines detrás:
$ python create_gif.py --config config.json --image images/vampire.jpg \ --output vampire_out.gif [INFO] loading models... [INFO] computing object detections... [INFO] creating GIF... [INFO] cleaning up...
Fig. 11. Usando OpenCV y Python, puedes crear este meme u otro GIF animadoEsa misma tarde, Trisha publicó una foto en las redes sociales, tuve que aguantarla.
Aquellos de ustedes que asistieron a PyImageConf 2018 (
lea la reseña ) saben que siempre estoy abierto a bromas. Aquí hay un ejemplo:
Pregunta: ¿Por qué el gallo cruza la calle? $ python create_gif.py --config config.json --image images/rooster.jpg \ --output rooster_out.gif [INFO] loading models... [INFO] computing object detections... [INFO] creating GIF... [INFO] cleaning up...
Fig. 12. La cara se reconoce incluso con poco contraste, y OpenCV procesa correctamente la foto y baja las gafas de sol.Respuesta: No diré la respuesta, aguanta esto.Finalmente, concluimos la guía de hoy con un buen meme.Hace unos seis años, mi padre y yo adoptamos un pequeño beagle, Gemma.Aquí puedes ver a Gemma en mi hombro: $ python create_gif.py --config config.json --image images/pupper.jpg \ --output pupper_out.gif [INFO] loading models... [INFO] computing object detections... [INFO] creating GIF... [INFO] cleaning up...
Fig. 13. Gemma es deliciosa. ¿No te parece? Entonces "¡acéptalo!"¿No estás de acuerdo con que ella es linda? Tratar con eso.¿Tiene un error AttributeError?
No te preocupes!Si viste este error: $ python create_gif.py --config config.json --image images/adrian.jpg \ --output adrian_out.gif ... Traceback (most recent call last): File "create_gif.py", line 142, in <module> (lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"] AttributeError: module 'imutils.face_utils' has no attribute 'FACIAL_LANDMARKS_IDXS'
... entonces solo necesita actualizar el paquete imutils: $ pip install --upgrade imutils Collecting imutils ... Successfully installed imutils-0.5.1
Por quéPor defecto, imutils.face_utils
utiliza un detector de puntos de referencia de 68 puntos integrado en dlib (como en este artículo). Hay un detector de 5 puntos más rápido , que ahora también funciona con imutils. Recientemente actualicé imutils para admitir ambos detectores (por lo que puede ver un error).Resumen
En el tutorial de hoy, aprendiste a crear GIF usando OpenCV.Para que la lección sea divertida, utilizamos OpenCV para generar la animación GIF "Deal With It", un meme popular (y mi favorito) que se encuentra de una forma u otra en casi todos los sitios de redes sociales.En el proceso, utilizamos la visión por computadora y el aprendizaje profundo para resolver varios problemas prácticos:- Identificación de personas
- Pronosticar puntos de referencia en la cara
- Identificación de áreas de la cara (en este caso, el ojo)
- Calcular el ángulo entre los ojos para alinear la cara
- Crea mezclas transparentes con mezcla alfa
Finalmente, tomamos un conjunto de imágenes generadas y creamos un GIF animado usando OpenCV e ImageMagick.¡Espero que hayas disfrutado el tutorial de hoy!Si te gustó, deja un comentario y avísame.Bueno, si no te gustó, no importa, solo aguanta. ;)