? ALMACENANDO ROSTROS ?? usando imágenes y video | Python – OpenCV
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:
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.
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.
Una vez más excelente video. Muy bien explicado y fácil de comprender.
Gracias por tu gran aporte Gaby.
Muchas gracias Omar. ¡Espero que sea de ayuda, muchos saludos :)!
Buenas,
Lo primero,… gracias por los videos y el desarrollo de programas en python.
Tengo un problemilla y no se de donde viene.
En el terminal me da fallo en esta línea:
faceClassif = cv2.CascadeClassifier(cv2.data.haarcascades+’haarcascade_frontalface_default.xml’)
Esto es lo que me pone en el terminal.
Traceback (most recent call last):
File «capturandoRostrosUnaImagen.py», line 3, in
faceClassif= cv2.CascadeClassifier(cv2.data.haarcascades+’haarcascade_frontalface_default.xml’)
AttributeError: ‘module’ object has no attribute ‘data’
Gracias y sigue así!!!!!
Hola David, qué versión de OpenCV posees?
hola tengo el mismo error y tengo la version de opecv 3.3.1
Hola Mariela, puede que te está dando problemas debido a como se está leyendo el detector de rostros, puedes probar leerlo como en este tutorial: http://omes-va.com/deteccion-de-rostros-con-haar-cascades-python-opencv/
Buen video, gaby
tuve el mismo problema al no reconocer la ‘data’, buscando ayuda solucione actualizando el pip de python: «pip install opencv-contrib-python «
Consulta Gaby , este codigo cambia algo en Linux
Hola Randall. No cambia, ¡puedes probarlo!.
Me gusto tu tutorial. Buen trabajo. Me sirvio para mis proyectos. Gracias
Hola John, me alegra mucho que te haya gustado y ayudado el tutorial, muchas gracias John, saludos.
Sabes como podría hacer para identifique los rostros si se esta usando cubrebocas ?
Hola Incog, podrías probar usando los algoritmos que empleamos en reconocimiento facial: http://omes-va.com/reconocimiento-facial-python-opencv/
Hola Gaby, excelente contenido
Si pudieras ayudarme
tengo un error en la linea 16,
OpenCV(4.5.1) /tmp/pip-req-build-jr1ur_cf/opencv/modules/imgproc/src/color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function ‘cvtColor’
File «/home/christian/Documents/proyectosPython/ChecadorVisual/GuardarRostrosVideo.py», line 16, in
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
googleando me decia que ret estaba vacio pero no se como depurarlo
Hola Christian muchas gracias. Asegúrate de que se estén leyendo correctamente las imágenes o fotogramas, puede que el programa esté enviando frame como vacío. 🙂
Hola, tuve el mismo problema, y el problema estaba en la linea que hacemos el VideoCapture
#cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)#habilitamos la camara — ESTO NO FUNCIONA CAP_DSHOW
#lo reemplaze como en el tutorial anterior
cap = cv2.VideoCapture(0)#habilitamos la camara
no se si es un tema de versionado de opencv o que, pero ese cambio me soluciono y hasta ahora no me afecto en nada. Le pregunto a la admin: ¿Que version de opencv se usan en estos tutoriales?
Hola Gaby, muy buen video como todas tus publicaciones. ¿funciona similar si quiero reconocer objetos y guardarlos? ¿Tengo que hacer un mix entre tu video de reconocimiento de objetos y este? Agradezco tus comentarios y sugerencias
Hola Abel, muchas gracias. 🙂 Si podrías hacerlo, me imagino que necesitas una vez obtenido el clasificador, ir pasándolo por un conjunto de imágenes, entonces sí. Este tutorial sería similar a lo que necesitarías.