OpenCV Python: Face Detection Neural Network

Todos sabemos que la Inteligencia Artificial se está volviendo cada vez más real y está llenando las brechas entre las capacidades de los humanos y las máquinas día a día. Ya no es solo una palabra elegante. Ha tenido muchos avances a lo largo de los años en muchos campos y una de esas áreas es el dominio de la Visión por Computador.

Cuando se trata de la Visión por Computador, su objetivo es entrenar las máquinas para ver y reconocer el mundo como lo hacen los humanos. Y también reúne conocimientos lo suficientemente grandes como para realizar reconocimiento de imágenes y video, análisis y clasificación de imágenes, recreación de medios, procesamiento de lenguaje natural, etc.

Redes neuronales convolucionales

El avance en la Visión por Computador se ha implementado y perfeccionado gradualmente con el tiempo. Principalmente sobre un algoritmo en particular, una Red Neural Convolucional (CNN o ConvNets).

Que es un tipo especial de red de avance que se usa principalmente para analizar imágenes visuales. Las redes neuronales convolucionales son muy similares a las redes neuronales comunes. Pero están formadas por neuronas que tienen pesos y sesgos que se pueden aprender.

ConvNets funciona mejor que las otras arquitecturas de redes neuronales profundas debido a su proceso único. En lugar de mirar la imagen un píxel a la vez, ConvNets agrupa varios píxeles para que puedan entender un patrón temporal.

De otra manera, ConvNets puede “ver” el grupo de píxeles que forman una línea o curva. Debido a la naturaleza profunda de las redes neuronales profundas, en el siguiente nivel no verán el grupo de píxeles, sino los grupos de líneas y curvas que forman algunas formas. Y así sucesivamente hasta formar un cuadro completo.

Transferencia de aprendizaje

Sin embargo, las CNN requieren grandes conjuntos de datos y mucho tiempo de cómputo para entrenar. Algunos pueden tardar hasta 2-3 semanas en múltiples GPU.

Hay muchas cosas que necesita aprender si quiere entender las CNN, desde las cosas más básicas, como un núcleo, agrupar capas, etc. Pero hoy en día, solo puede bucear y usar muchos proyectos de código abierto para esta tecnología.

Esto es realmente cierto debido a la tecnología llamada Transfer Learning. Transfer Learning es una técnica muy práctica y poderosa que utiliza un modelo entrenado en lugar de entrenar la red desde cero. El aprendizaje por transferencia utiliza un modelo capacitado en un conjunto de datos diferente. Y lo adapta al problema que estamos tratando de resolver.

Para desarrollar nuestra aplicación, seguiremos la técnica de transferencia de aprendizaje y utilizaremos un modelo capacitado, que se entrenó utilizando el marco de Caffe.

Un marco de aprendizaje profundo hecho con la expresión, la velocidad y la modularidad en mente. Caffe viene con un repositorio que es usado por investigadores y practicantes de aprendizaje automático para compartir sus modelos entrenados. Esta biblioteca se llama Model Zoo.

Puedes leer todo sobre esto revisando su documentación .

Empezando

El código de python, el modelo de caffe entrenado y el archivo de prototxt. Que incluye la descripción de texto de la red y algunas imágenes de ejemplo para usar con nuestra aplicación. Están disponibles en el repositorio de github si desea echar un vistazo.

En nuestra aplicación, utilizaremos las siguientes bibliotecas:
  1. OpenCV Python, que admite una gran cantidad de algoritmos relacionados con la Visión por Computador y el Aprendizaje Automático. Sin mencionar que está construido en Deep Neural Network. Que usaremos en nuestra aplicación.
  2. Numpy, que es un paquete utilizado para la computación científica con python.
  3. Sistema operativo, que proporciona una forma portátil de utilizar la funcionalidad dependiente del sistema operativo

Por lo tanto, para instalarlos, puede ejecutar los siguientes comandos en una ventana del símbolo del sistema. pip install opencv-pythonpara instalar OpenCV Python, pip install numpypara instalar Numpy y no tiene que instalar específicamente la biblioteca del sistema operativo como viene con su instalación de Python, pero todavía debe importarla.

Construyendo la aplicación

Primero, creemos un archivo llamado faceDetection.py e importemos nuestras bibliotecas.

#import libraries
import os   
import cv2
import numpy

Ahora, obtendremos la ruta absoluta del directorio de trabajo, donde colocaremos todas nuestras imágenes:
#import libraries
import os   
import cv2
import numpy
#get the absolute path of the working directory
dir_path = os.path.dirname(os.path.realpath(__file__))
Ahora, crearemos una carpeta llamada “Salida” para colocar nuestras imágenes finales si aún no existe.
#import libraries
import os   
import cv2
import numpy
#get the absolute path of the working directory
dir_path = os.path.dirname(os.path.realpath(__file__))
#create the Output folder if it doesn't already exist
if not os.path.exists('Output'): 
  os.makedirs('Output')
Después de eso, cargaremos nuestro modelo pre-entrenado y el archivo de prototxt del directorio de trabajo actual.
#import libraries
import os   
import cv2
import numpy
#get the absolute path of the working directory
dir_path = os.path.dirname(os.path.realpath(__file__))
#create the Output folder if it doesn't already exist
if not os.path.exists('Output'): 
  os.makedirs('Output')
#Reads the network model stored in Caffe framework's format.
model = cv2.dnn.readNetFromCaffe('deploy.prototxt', 'weights.caffemodel')

 

Luego, recorreremos los archivos disponibles en la carpeta actual para verificar si hay archivos con las extensiones, .png, .jpg y .jpeg.

 

#import libraries
import os   
import cv2
import numpy
#get the absolute path of the working directory
dir_path = os.path.dirname(os.path.realpath(__file__))
#create the Output folder if it doesn't already exist
if not os.path.exists('Output'): 
  os.makedirs('Output')
#Reads the network model stored in Caffe framework's format.
model = cv2.dnn.readNetFromCaffe('deploy.prototxt', 'weights.caffemodel')
for file in os.listdir(dir_path):
  #split the file name and the extension into two variales
  filename, file_extension = os.path.splitext(file)
  #check if the file extension is .png,.jpeg or .jpg 
  if (file_extension in ['.png','.jpg','.jpeg']):

Si se encuentra una imagen con las extensiones anteriores, leeremos la imagen utilizando OpenCV Python y obtendremos su altura y anchura accediendo a la tupla de image.shape y tomando los primeros dos elementos para dibujar el rectángulo alrededor de la cara más adelante.

#import libraries
import os   
import cv2
import numpy
#get the absolute path of the working directory
dir_path = os.path.dirname(os.path.realpath(__file__))
#create the Output folder if it doesn't already exist
if not os.path.exists('Output'): 
  os.makedirs('Output')
#Reads the network model stored in Caffe framework's format.
model = cv2.dnn.readNetFromCaffe('deploy.prototxt', 'weights.caffemodel')
for file in os.listdir(dir_path):
  #split the file name and the extension into two variales
  filename, file_extension = os.path.splitext(file)
  #check if the file extension is .png,.jpeg or .jpg
  if (file_extension in ['.png','.jpg','.jpeg']):
    #read the image using cv2
    image = cv2.imread(file)
#accessing the image.shape tuple and taking the elements
    (h, w) = image.shape[:2]


Y luego, obtendremos nuestro blob usando la cv2.dnn.blobFromImagefunción dando la imagen como entrada. Con la cv2.dnn.blobFromImagefunción redimensionamos la imagen a una dimensión de 300×300, 1.0 es un factor de escala y aquí usamos el valor predeterminado, por lo que no hay escala, después de eso es el tamaño espacial que la red neuronal convolucional espera, los últimos valores son valores de resta promedio en la tupla y son medios RGB, y al final, la función devuelve un “blob” que es nuestra imagen de entrada después del cambio de tamaño, la resta de la media y la normalización.

Después de eso, ingresaremos el blob en el modelo y obtendremos las detecciones usando la model.forewardfunción.

 

#import libraries
import os   
import cv2
import numpy
#get the absolute path of the working directory
dir_path = os.path.dirname(os.path.realpath(__file__))
#create the Output folder if it doesn't already exist
if not os.path.exists('Output'): 
  os.makedirs('Output')
#Reads the network model stored in Caffe framework's format.
model = cv2.dnn.readNetFromCaffe('deploy.prototxt', 'weights.caffemodel')
for file in os.listdir(dir_path):
  #split the file name and the extension into two variales
  filename, file_extension = os.path.splitext(file)
  #check if the file extension is .png,.jpeg or .jpg 
  if (file_extension in ['.png','.jpg','.jpeg']):
    #read the image using cv2
    image = cv2.imread(file)
    #accessing the image.shape tuple and taking the elements
    (h, w) = image.shape[:2]
#get our blob which is our input image 
blob = cv2.dnn.blobFromImage(cv2.resize(image, (300, 300)), 1.0, (300, 300), (104.0, 177.0, 123.0))
#input the blob into the model and get back the detections 
    model.setInput(blob)
    detections = model.forward()
Luego, recorreremos todas las caras detectadas y extraeremos sus puntos de inicio y final.

Extraeremos la confianza y la compararemos con el umbral de confianza para poder filtrar las detecciones que son débiles. Si el algoritmo tiene más de 16.5% de confianza de que la detección es una cara, le mostraremos un rectángulo verde.

#import libraries
import os   
import cv2
import numpy
#get the absolute path of the working directory
dir_path = os.path.dirname(os.path.realpath(__file__))
#create the Output folder if it doesn't already exist
if not os.path.exists('Output'): 
  os.makedirs('Output')
#Reads the network model stored in Caffe framework's format.
model = cv2.dnn.readNetFromCaffe('deploy.prototxt', 'weights.caffemodel')
for file in os.listdir(dir_path):
  #split the file name and the extension into two variales
  filename, file_extension = os.path.splitext(file)
  #check if the file extension is .png,.jpeg or .jpg 
  if (file_extension in ['.png','.jpg','.jpeg']):
    #read the image using cv2
    image = cv2.imread(file)
    #accessing the image.shape tuple and taking the elements
    (h, w) = image.shape[:2]
    #get our blob which is our input image 
    blob = cv2.dnn.blobFromImage(cv2.resize(image, (300, 300)), 1.0, (300, 300), (104.0, 177.0, 123.0))
    #input the blob into the model and get back the detections 
    model.setInput(blob)
    detections = model.forward()
    #Iterate over all of the faces detected and extract their start and end points
    count = 0
    for i in range(0, detections.shape[2]):
      box = detections[0, 0, i, 3:7] * numpy.array([w, h, w, h])
      (startX, startY, endX, endY) = box.astype("int")
      
     confidence = detections[0, 0, i, 2]
     #if the algorithm is more than 16.5% confident that the      detection is a face, show a rectangle around it
     if (confidence > 0.165):
     cv2.rectangle(image, (startX, startY), (endX, endY), (0, 255, 0), 2)
     count = count + 1
Finalmente, guardaremos la imagen de salida en la carpeta de salida que creamos e imprimiremos un mensaje de éxito para que el usuario sepa que está listo.
#import libraries
import os   
import cv2
import numpy
#get the absolute path of the working directory
dir_path = os.path.dirname(os.path.realpath(__file__))
#create the Output folder if it doesn't already exist
if not os.path.exists('Output'): 
  os.makedirs('Output')
#Reads the network model stored in Caffe framework's format.
model = cv2.dnn.readNetFromCaffe('deploy.prototxt', 'weights.caffemodel')
for file in os.listdir(dir_path):
  #split the file name and the extension into two variales
  filename, file_extension = os.path.splitext(file)
#check if the file extension is .png,.jpeg or .jpg 
  if (file_extension in ['.png','.jpg','.jpeg']):
    #read the image using cv2
    image = cv2.imread(file)
#accessing the image.shape tuple and taking the elements
    (h, w) = image.shape[:2]
#get our blob which is our input image 
    blob = cv2.dnn.blobFromImage(cv2.resize(image, (300, 300)), 1.0, (300, 300), (104.0, 177.0, 123.0))
#input the blob into the model and get back the detections 
    model.setInput(blob)
    detections = model.forward()
    #Iterate over all of the faces detected and extract their start and end points
    count = 0
    for i in range(0, detections.shape[2]):
      box = detections[0, 0, i, 3:7] * numpy.array([w, h, w, h])
      (startX, startY, endX, endY) = box.astype("int")
confidence = detections[0, 0, i, 2]
      #if the algorithm is more than 16.5% confident that the      detection is a face, show a rectangle around it
      if (confidence > 0.165):
        cv2.rectangle(image, (startX, startY), (endX, endY), (0, 255, 0), 2)
        count = count + 1
    #save the modified image to the Output folder
    cv2.imwrite('Output/' + file, image)
    #print out a success message
    print("Face detection complete for image "+ file + " ("+ str(count) +") faces found!")

Espero que hayan disfrutado los resultados! Ahora, siempre puedes jugar un poco con el código para tener una idea de lo que hace cada función. OpenCV Python proporciona una excelente documentación y tutoriales si quieres leer y obtener más información también.

Conclusión

En este artículo, caminamos a través,

  1. El concepto de redes neuronales convolucionales y cómo podemos ahorrar mucho tiempo y esfuerzo con Transfer Learning y los modelos pre-entrenados.
  2. Los modelos de Caffe y cómo vamos a utilizar un modelo de Caffe pre-entrenado para implementar nuestra aplicación.
  3. instalando las bibliotecas requeridas y configurando el entorno.

Y finalmente, implementamos un programa de python que puede detectar usando una imagen.

Si tiene alguna pregunta, no dude en dejar un comentario a continuación. ¡Gracias!

 

Dejá un comentario