11

CNN para deteccion de rostros y ojos en tiempo real con OpenCV

Para hacer esto debemos entender que es una convolucion y que es el algoritmo Haar Cascade.

En este blog hay informacion al respecto:
https://datasmarts.net/es/deteccion-de-rostros-a-la-vieja-usanza-con-haar-cascades/

Ahi tambien pueden encontrar el codigo para implementarlo en una imagen pero en este caso lo haremos para detectar nuestros rostros en tiempo real, ademas proporciono el codigo para descargar los clasificadores

Importaremos dos archivos desde github, uno con el clasificador de ojos y otro con el clasificador de rostros, ademas usaremos la libreria OpenCV para realizar la convolucion en nuestro modelo y para la manipulacion de imagenes, en este caso de la captura(ejm: el dibujo de los cuadrantes).

Lamentablemente a pesar de que google colab tiene integrada la libreria OpenCV no me permite ejecutar en tiempo real el algoritmo, por eso les dejare el codigo aca:

0-Antes que nada instalamos OpenCV:

pip install opencv-python

1-Ahora en nuestro IDE importamos las librerias numpy para manejo de matrices, cv2 de opencv, requests para obtener los archivos de github y os para manejo de archivos, luego cargamos nuestros clasificadores, le decimos que si no encuentra esos archivos que los descargue de github.

import numpy as np
import cv2
import requests
import os

#Descargar la data

face = "haarcascade.xml"ifnot os.path.isfile(face):
	url = "https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_default.xml"
	content = requests.get(url).content
	f = open(face, "wb")
	f.write(content)

eye = "eyecascade.xml"ifnot os.path.isfile(eye):
	url_ = "https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_eye.xml"
	content_ = requests.get(url_).content
	f = open(eye, "wb")
	f.write(content_)

2- Creamos nuestros clasificadores a partir de la data importada, luego creamos nuestra captura de video y con cv2.namedWindow haremos que sea posible cambiar el tamaño de nuestra ventana.

#Clasificadores
face_cascade = cv2.CascadeClassifier(face)
eye_cascade = cv2.CascadeClassifier(eye)

#Captura de video
cap = cv2.VideoCapture(0)

cv2.namedWindow("frame", cv2.WINDOW_NORMAL)

3-Ahora creamos un infinite loop para mantener nuestra captura, gray es la captura en escala de grises, faces son las regiones o bounding boxes donde clasificó el/los rostros los cuales tienen como variables:
-x,y: coordenadas de los centros de cada bounding box
-w,h: ancho y altura de la imagen

Dibujaremos el bounding box de cada rostro segun esos datos y agregamos la palabra:“Person”.

Una vez que tenemos las regiones de nuestros rostros(x,y,w,h), para detectar los ojos pasaremos a usar el clasificador de ojos para cada region de cada rostro y asi optimizar la busqueda de manera que no recorra toda la imagen.
Dejare anotaciones en el codigo para un mejor entendimiento.

while 1:
	ret, frame = cap.read()
	#Imagen en escala de grises
	gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
	
	#Deteccion de rostros con nuestro clasificador
	faces = face_cascade.detectMultiScale(gray, 1.3, 5)
	
	#(coordenadas en xy, ancho y alto)
	for (x,y,w,h) in faces:
		#Dibujar rectangulo(imagen, coordenadas, ancho y alto, color en RGB, grosor)
		img = cv2.rectangle(frame, (x,y), (x+w, y+h), (0,0,255), 2)
		cv2.putText(img = img,
                text = "Person",
                org = (x-10, y-10),
                fontFace = cv2.FONT_HERSHEY_SIMPLEX,
                fontScale = 0.6,
                color = (0,0,255),
                thickness= 1
                )
		#Regiondel rostro en la imagen en escala de grises
		roi_gray = gray[y:y+h, x:x+w]
		
		#Regiondel rostro en la imagen a colores
		roi_color = img[y:y+h, x:x+w]
		
		#Deteccion de ojos por cada rostro
		#Recuerda que el kernel o filtro solo funciona con imagenes en escala de grises
		eyes = eye_cascade.detectMultiScale(roi_gray)
		
		#(coordenadas en xy, ancho y alto)
		for (ex,ey,ew,eh) in eyes:
			#Dibuja el rectangulo en la region del rostro
			img = cv2.rectangle(roi_color, (ex,ey), (ex+ew, ey+eh), (0,255,0), 2)
			

Ahora todo el codigo se veria asi:

import numpy as np
import cv2
import requests
import os

#Descargamos los clasificadoresface = "haarcascade.xml"if not os.path.isfile(face):
	url = "https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_default.xml"content = requests.get(url).content
	f = open(face, "wb")
	f.write(content)

eye = "eyecascade.xml"if not os.path.isfile(eye):
	url_ = "https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_eye.xml"content_ = requests.get(url_).content
	f = open(eye, "wb")
	f.write(content_)

#Clasificadoresface_cascade = cv2.CascadeClassifier(face)
eye_cascade = cv2.CascadeClassifier(eye)

#Captura de videocap = cv2.VideoCapture(0)

cv2.namedWindow("frame", cv2.WINDOW_NORMAL)

while 1:
	ret, frame = cap.read()
	#Imagen en escala de grisesgray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
	
	#Deteccion de rostros con nuestro clasificadorfaces = face_cascade.detectMultiScale(gray, 1.3, 5)
	
	#(coordenadas en xy, ancho y alto)
	for (x,y,w,h) in faces:
		#Dibujar rectangulo(imagen, coordenadas, ancho y alto, color en RGB, grosor)img = cv2.rectangle(frame, (x,y), (x+w, y+h), (0,0,255), 2)
		cv2.putText(img = img,
                text = "Person",
                org = (x-10, y-10),
                fontFace = cv2.FONT_HERSHEY_SIMPLEX,
                fontScale = 0.6,
                color = (0,0,255),
                thickness=1
                )
		#Region del rostro en la imagen en escala de grisesroi_gray = gray[y:y+h, x:x+w]
		
		#Region del rostro en la imagen a coloresroi_color = img[y:y+h, x:x+w]
		
		#Deteccion de ojos por cada rostro#Recuerda que el kernel o filtro solo funciona con imagenes en escala de griseseyes = eye_cascade.detectMultiScale(roi_gray)
		
		#(coordenadas en xy, ancho y alto)
		for (ex,ey,ew,eh) in eyes:
			#Dibuja el rectangulo en la region del rostroimg = cv2.rectangle(roi_color, (ex,ey), (ex+ew, ey+eh), (0,255,0), 2)
			
	
	cv2.imshow("frame", frame)
	cv2.waitKey(1)

cap.release()
cv2.destroyAllWindows()

Y listo, mantente cerca de la camara de tu computadora para que veas como funciona.

Podremos probar este algoritmo para algo mas simple, en este caso para detectar los rostros de Messi y CR7:

import numpy as np
import cv2
import requests
import os
import matplotlib.pyplot as plt

#Download dataface = "haarcascade.xml"if not os.path.isfile(face):
	url = "https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_default.xml"content = requests.get(url).content
	f = open(face, "wb")
	f.write(content)

eye = "eyecascade.xml"if not os.path.isfile(eye):
	url_ = "https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_eye.xml"content_ = requests.get(url_).content
	f = open(eye, "wb")
	f.write(content_)

image = "messi_cr7.jpg"if not os.path.isfile(image):
	url_ = "https://publimetro.pe/resizer/n7FU8sz4fE1ml7RPdvi_6XEFp1w=/980x528/smart/arc-anglerfish-arc2-prod-elcomercio.s3.amazonaws.com/public/HBSLR2R2ZVGOFBJXSFIJZ3HOTQ.jpg"content_ = requests.get(url_).content
	f = open(image, "wb")
	f.write(content_)


#Classifiersface_cascade = cv2.CascadeClassifier(face)
eye_cascade = cv2.CascadeClassifier(eye)

#Image we will predictimg = cv2.imread(image)
plt.imshow(img)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

#Detect facefaces = face_cascade.detectMultiScale(gray, 1.3, 5)


for (x,y,w,h) in faces:
	#params = (image, position, width and height, color in RGB scale, and thickness)img = cv2.rectangle(img, (x,y), (x+w, y+h), (255,0,0), 2)
	roi_gray = gray[y:y+h, x:x+w]
	roi_color = img[y:y+h, x:x+w]
	#Detect eyes per faceeyes = eye_cascade.detectMultiScale(roi_gray)
	for (ex,ey,ew,eh) in eyes:
		cv2.rectangle(roi_color, (ex,ey), (ex+ew, ey+eh), (0,255,0), 2)


#Show image
cv2.namedWindow("image", cv2.WINDOW_NORMAL)

while 1:
	cv2.imshow("image", img)
	cv2.waitKey(1)

cv2.destroyAllWindows()

Output:

cr7.JPG
Escribe tu comentario
+ 2
2
20943Puntos

Excelente tutorial, te felicito mi amigo!

2
12229Puntos

Gracias Christian! que bueno que te haya gustado.