? ALMACENANDO ROSTROS ?? usando imágenes y video | Python – OpenCV

Por Administrador

Bienvenido a un nuevo tutorial, en este veremos como almacenar rostros detectados de imágenes o videos. Para ello primero almacenaremos el rostro de una sola imagen, luego haremos que este procedimiento se automatice para un banco de imágenes almacenando los rostros en un nuevo directorio, y finalmente veremos como extraer rostros presentes en videos, en este caso también los almacenaremos en un nuevo directorio. Para detectar los rostros en las imágenes estaremos usando haar cascades, si quieres más información sobre como hacerlo, puedes visitar este post.

Si bien este procedimiento lo vamos a realizar con caras, puedes realzarlo para cualquier objeto, siempre y cuando tengas las coordenadas que lo rodean para poder recortarlo de la imagen, por ejemplo en el caso de la detección de placas automóviles, este proceso también podría usarse.

ATENCIÓN: Para usar las imágenes y/o programas que se van a emplear en este post no olvides visitar mi repositorio en gitHub.

Este tutorial tiene como objetivo que puedas almacenar regiones de interés, ya sea para monitorear o para que construyas un data set si deseas entrenarlo.

CONTENIDO

  • Guardando los rostros presentes en una imagen
  • Mejoremos el código… Almacenando rostros de un banco de imágenes
  • Almacenando rostros presentes en un video

Guardando los rostros presentes en una imagen

Ya teníamos el código necesario para poder detectar rostros en una image con el uso de haar cascades, pues emplearemos el mismo procedimiento y añadiremos unas cuantas líneas de código para guardar los rostros.

En este tutorial no se especificará como detectar rostros en imágenes ya que ese tema esta presente en el post: ? DETECCIÓN DE ROSTROS ? con Haar Cascades Python – OpenCV. Pondremos nuestra atención en almacenar todos esos rostros detectados.

Supongamos que tenemos la siguiente imagen de entrada:

Figura 1: Imagen de entrada para almacenar rostros de una imagen.

El programa para detectar y almacenar los rostros de la imagen de la figura 1 sería el siguiente:

import cv2

faceClassif = cv2.CascadeClassifier(cv2.data.haarcascades+'haarcascade_frontalface_default.xml')

image = cv2.imread('imagen_000.jpg')
imageAux = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

faces = faceClassif.detectMultiScale(gray, 1.1, 5)

count = 0

for (x,y,w,h) in faces:

    cv2.rectangle(image, (x,y),(x+w,y+h),(128,0,255),2)
    rostro = imageAux[y:y+h,x:x+w]
    rostro = cv2.resize(rostro,(150,150), interpolation=cv2.INTER_CUBIC)
    cv2.imwrite('rostro_{}.jpg'.format(count),rostro)
    count = count + 1

    cv2.imshow('rostro',rostro)
    cv2.imshow('image',image)
    cv2.waitKey(0)

cv2.destroyAllWindows()

Línea 1: Importamos OpenCV.

Línea 3: Vamos a cargar el clasificador de rostros.

Línea 5: Leemos la imagen de entrada que sería la correspondiente a la imagen de la figura 1.

Línea 6: Creamos una copia de la imagen de entrada, esta se mantendrá intacta, por lo que nos servirá para rectorar los rostros encontrados.

Línea 7: Transformamos la imagen de entrada de BGR a escala de grises.

Línea 9: Con esta línea se realiza la detección de rostros presentes en la imagen, según los parámetros de entrada de la función detectMultiScale. Para más información por favor dirigente a este post.

Línea 11: Vamos a iniciar un contador count = 0, que nos ayudará al conteo de cada uno de los rostros detectados.

Línea 13: Extraemos las coordenadas, ancho y alto de cada una de las caras detectadas.

Línea 15: Vamos a visualizar los rostros detectados en un rectángulo rosa.

Línea 16 y 17: En la línea 16 recortamos los rostros de la imagen imageAux con ayuda de las coordenadas x, y ancho y alto que obtuvimos de la línea 13. En la línea 17 vamos a redimensionar los rostros a 150 pixeles de ancho y alto (esta línea puede ser omitida o el ancho y alto podrían cambiar de acuerdo a tus requerimientos).

Línea 18:  Almacenamos los rostros. Cada una de las imágenes tendrá un número diferente gracias al contador count.

Línea 21 a 25: Estas líneas son para la visualización del rostro y de las detecciones.

Si ejecutamos tendríamos lo siguiente:

Conforme se presiona cualquier tecla se rodea un rostro,y se va almacenando en la carpeta donde se encuentra el script. Cabe destacar que todos los rostros tienen el mismo ancho y alto ya que los redimensionamos, tú podrías omitir este paso dejando el tamaño original de cada rostro, o podrías cambiar el tamaño del redimensionamiento.

Hasta aquí ya tenemos solución al problema de almacenar los rostros de una imagen, pero al guardarlos en la misma carpeta del script donde además está la imagen de entrada puede que no sea muy recomendable. Otro aspecto a considerar es cuando se tiene varias imágenes de entrada, entoonces podría ser un tanto desordenado si guardamos y leemos todo en el mismo lugar. Por ello a continuación vamos a mejorar este proceso para que se puedan guardar los rostros de varias imágenes.

Mejoremos el código… Almacenando rostros de un banco imágenes

Esta vez nos plantearemos almacenar rostros presentes en imágenes que se encuentran en un directorio. Además crearemos una carpeta en donde se almacenarán todos los rostros recortados.

Las imágenes que usaremos para este proceso serán las siguientes (estas se encuentran almacenadas en una carpeta llamada ‘Imagenes’):

TIP: El nombre de la carpeta ‘Imagenes’ lo he puesto sin tilde, ya que tuve problemas con OpenCV al momento de leer las imágenes de ese directorio. Si llegas a tener problemas tú también, puedes probar con nombres de los archivos y directorios sin tildes.

El almacenamiento se realizará cuando se presione la letra ‘s’, mientras que si queremos finalizar el programa y no seguir recortando rostros usaremos ‘Esc’. ¡Vamos con el código!

import cv2
import os

imagesPath = "C:/Users/Gaby/Desktop/Extrayendo rostros/Imagenes"
imagesPathList = os.listdir(imagesPath)

if not os.path.exists('Rostros encontrados'):
    print('Carpeta creada: Rostros encontrados')
    os.makedirs('Rostros encontrados')

faceClassif = cv2.CascadeClassifier(cv2.data.haarcascades+'haarcascade_frontalface_default.xml')

count = 0
for imageName in imagesPathList:
    image = cv2.imread(imagesPath+'/'+imageName)
    imageAux = image.copy()
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    
    faces = faceClassif.detectMultiScale(gray, 1.1, 5)

    for (x,y,w,h) in faces:
        cv2.rectangle(image, (x,y),(x+w,y+h),(128,0,255),2)
    cv2.rectangle(image,(10,5),(450,25),(255,255,255),-1)
    cv2.putText(image,'Presione s, para alamacenar los rostros encontrados',(10,20), 2, 0.5,(128,0,255),1,cv2.LINE_AA)
    cv2.imshow('image',image)
    k = cv2.waitKey(0)
    if  k == ord('s'):
        for (x,y,w,h) in faces:
            rostro = imageAux[y:y+h,x:x+w]
            rostro = cv2.resize(rostro,(150,150), interpolation=cv2.INTER_CUBIC)
            #cv2.imshow('rostro',rostro)
            #cv2.waitKey(0)
            cv2.imwrite('Rostros encontrados/rostro_{}.jpg'.format(count),rostro)
            count = count +1
    elif k == 27:
        break

cv2.destroyAllWindows()

Línea 1 y 2: Importamos OpenCV y os, este último nos ayudará a crear directorios, listarlos entre otros.

Línea 4: Asignamos a imagesPath la ruta en donde estan presentes las imágenes con las que vamos a trabajar.

Línea 5: Aquí estamos listando los archivos y directorios presentes en el directorio imagesPath además los estamos almacenando en la variable imagesPathList. Si imprimimos tendríamos lo siguiente:

['imagen_000.jpg', 'imagen_001.jpg', 'imagen_002.jpg', 'imagen_003.jpg', 'imagen_004.jpg', 'imagen_005.jpg']

Línea 7 a 9: Verificamos si existe algún directorio llamado ‘Rostros encontrados’, si no es así lo creamos.

En la línea 11 cargamos el clasificador de rostros, mientras que en la línea 13 inicializamos el contador count que nos ayudará con los nombres para cada rostro.

Línea 14 y 15: Vamos a leer el nombre de cada imagen de la carpeta ‘Imagenes’, mientras que en la línea 15 añadimos la ruta principal y dicho nombre de la imagen para leerla con cv2.imread.

Línea 16 a 25: Este procedimiento es similar al del apartado anterior, creamos una imagen auxiliar copia de la imagen de entrada, transformamos la imagen de entrada en escala de grises, detectamos los rostros, dibujamos un rectángulo que rodee las caras y además pondremos el mensaje: Presione s, para almacenar los rostros encontrados.

Figura 2: Detección de rostro y visualización de un mensaje.

Línea 26 y 27: Ahora vamos a asignar la tecla ‘s’ para que se guarden los rostros detectados en el nuevo directorio.

Línea 28 a 34: Similar al apartado anterior, con ayuda de las coordenadas x e y, ancho y alto de los rostros detectados recortamos y guardamos los rostros en la carpeta que habíamos creado en un principio. Recuerda que en la línea 30 estamos redimensionando los rostros, pueedes omitir o modificar esta línea. Si deseas puedes descomentar las líneas 31 y 32 para que visualices cada rostro. Finalmente sumamos 1 a la variable count.

Línea 35 a 38: Cuando presionemos ‘Esc’, el ciclo se va a romper y se cerrarán las ventanas de visualización.

Podemos ver que se realiza el proceso de almacenamiento de cada rostro en la carpeta que creamos: Rostros encontrados.

Almacenando rostros presentes en un video

Finalmente vamos con la extracción y almacenamiento de rotros mediante el uso de videos (recuerda que puedes realizar video streaming o leer un video). Veamos:

import cv2
import os

if not os.path.exists('Rostros encontrados'):
    print('Carpeta creada: Rostros encontrados')
    os.makedirs('Rostros encontrados')

cap = cv2.VideoCapture(0,cv2.CAP_DSHOW)

faceClassif = cv2.CascadeClassifier(cv2.data.haarcascades+'haarcascade_frontalface_default.xml')

count = 0
while True:
    ret,frame = cap.read()
    frame = cv2.flip(frame,1)
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    auxFrame = frame.copy()

    faces = faceClassif.detectMultiScale(gray, 1.3, 5)

    k = cv2.waitKey(1)
    if k == 27:
        break

    for (x,y,w,h) in faces:
        cv2.rectangle(frame, (x,y),(x+w,y+h),(128,0,255),2)
        rostro = auxFrame[y:y+h,x:x+w]
        rostro = cv2.resize(rostro,(150,150), interpolation=cv2.INTER_CUBIC)
        if k == ord('s'):
            cv2.imwrite('Rostros encontrados/rostro_{}.jpg'.format(count),rostro)
            cv2.imshow('rostro',rostro)
            count = count +1
    cv2.rectangle(frame,(10,5),(450,25),(255,255,255),-1)
    cv2.putText(frame,'Presione s, para almacenar los rostros encontrados',(10,20), 2, 0.5,(128,0,255),1,cv2.LINE_AA)
    cv2.imshow('frame',frame)

cap.release()
cv2.destroyAllWindows()

Ya que se sigue el mismo procedimiento me voy a centrar en las líneas que no han aparecido en los dos programas anteriores.

En la línea 8 especificamos que vamos a realizar un video streaming, sin embargo bien podrías leer un video.

NOTA: Uso cv2.CAP_DSHOW en este programa, para que al momento de  realizar la visualización ocupe totalmente la ventana.

En la línea 15 usé la función cv2.flip para que la visualización sea como un espejo. Y en sí el resto de líneas siguen el mismo procedimiento. Veamos como sería el resultado:

Este procedimiento lo usaremos más adelante para reconocimiento facial, ya que neccesitaremos muchísimas imágenes de personas que vayan a ser reconocidas por el algoritmo. Y hemos llegado al final del tutorial, espero que te haya sido de ayuda :). Nos vemos en el siguiente.