👩 Reconocimiento Facial 👨 | Python – OpenCV

Por Administrador

En este post veremos como realizar reconocimiento facial en Python usando OpenCV, para ello emplearemos: Eigenfaces, Fisherfaces y Local Binary Patterns Histograms.

Para poder llevar a cabo el reconocimiento facial, en primer lugar necesitaremos recolectar los datos, es decir los rostros de las personas que se desee reconocer, posteriormente entrenaremos el clasificador, para finalmente probarlo. Para todo este proceso será necesario usar la  detección de rostros con haarcascades que habíamos visto en posts anteriores.

El objetivo de este post será proveer los pasos y código necesario para poder probar tú mismo esta aplicación, por lo que te dejaré los 3 programas que trataremos hoy y de igual manera podrás encontrarlos en mi repositorio en github.

CONTENIDO

  • ¿Cuál es la diferencia entre detección y reconocimiento facial?
  • Creando la base de datos de los rostros
  • Preparando los datos para entrenar
  • Entrenamiento del reconocedor
    • EigenFaces
      • EigenFaces en OpenCV, cv2.face.EigenFaceRecognizer_create()
    • FisherFaces
      • FisherFaces en OpenCV, cv2.face.FisherFaceRecognizer_create()
    • Local Binary Patterns Histograms
      • LBPH en OpenCV, cv2.face.LBPHFaceRecognizer_create()
    • Entrenamiento (Código)
    • Guardando el modelo obtenido
  • Probando EigenFaces, FisherFaces y LBPH para el reconocimiento facial
    • Probando EigenFaces
    • Probando FisherFaces
    • Probando LBPH
    • Prueba extra en video directo (video streaming)

¿Cuál es la diferencia entre detección y reconocimiento facial?

Figura 1: Detección y reconocimiento facial.

Antes de pasar con el desarrollo de este post, es necesario entender la diferencia entre la detección y reconocimiento de rostros, ya que son términos que muchas veces se usan como si se refiriera a una misma acción.

La diferencia es simple, la detección de rostros busca caras dentro de una imagen o dentro fotogramas en caso de emplear un video. El reconocimiento facial  en cambio emplea la detección de rostros y buscará identificar a la persona que le pertenece aquel rostro detectado.

Por lo tanto primero debemos emplear detección facial, y luego sobre el rostro detectado pasaremos al  reconocimiento facial. Para esta último procedimiento se necesita que previamente se haya entrenado un clasificador de rostros de las personas que se deseen reconocer.

Creando la base de datos de los rostros

Para realizar el reconocimiento facial necesitaremos de los rostros de las personas que deseemos reconocer. Estos rostros deberán denotar variedad de expresiones como: felicidad, tristeza, aburrimiento, sorpresa, entre otros. Otro aspecto que deben tener estas imágenes es la variación de condiciones de luz, que las personas lleven lentes o que no los lleven, incluso que cierren los ojos o guiñen uno.

Es recomendable que se realice la recolección de estas imágenes en el escenario o ambiente en donde se vaya a aplicar el reconocimiento facial. Toda esta variedad de imágenes que se obtenga de los rostros contribuirá al desempeño de los algoritmos que usemos el día de hoy (y claro, según vayas experimentado podrás añadir o quitar algunas de estas condiciones que he nombrado).

Una pregunta que te debes estar haciendo es, ¿cuántos rostros por persona debo obtener para poder realizar el reconocimiento?. Pues bien, según mi percepción no hay una receta para saber cuantas imágenes, lo que si entre más y más variadas mejor.

Ahora vamos a pasar con el código, para ello estaré usando el programa del post anterior: 📁 ALMACENANDO ROSTROS 👩👨 usando imágenes y video | Python – OpenCV, en especial el apartado de almacenar rostros desde un video. En este programa llamado capturandoRostros.py se almacenarán automáticamente 300 rostros dado un video, por ello he modificado un par de líneas de código la cuales explicaré, el resto del programa podrás revisarlo a profundidad en el post anteriormente citado.

import cv2
import os
import imutils

personName = 'Gaby'
dataPath = 'C:/Users/Gaby/Desktop/Reconocimiento Facial/Data'#Cambia a la ruta donde hayas almacenado Data
personPath = dataPath + '/' + personName

if not os.path.exists(personPath):
    print('Carpeta creada: ',personPath)
    os.makedirs(personPath)

cap = cv2.VideoCapture(0,cv2.CAP_DSHOW)
#cap = cv2.VideoCapture('Video.mp4')

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

while True:
    
    ret, frame = cap.read()
    if ret == False: break
    frame =  imutils.resize(frame, width=640)
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    auxFrame = frame.copy()

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

    for (x,y,w,h) in faces:
        cv2.rectangle(frame, (x,y),(x+w,y+h),(0,255,0),2)
        rostro = auxFrame[y:y+h,x:x+w]
        rostro = cv2.resize(rostro,(150,150),interpolation=cv2.INTER_CUBIC)
        cv2.imwrite(personPath + '/rotro_{}.jpg'.format(count),rostro)
        count = count + 1
    cv2.imshow('frame',frame)

    k =  cv2.waitKey(1)
    if k == 27 or count >= 300:
        break

cap.release()
cv2.destroyAllWindows()

Línea 1 a 3: Importamos OpenCV, os e imutils.

Línea 5 a 7: En estas líneas crearemos una carpeta con el nombre de la persona que se desee reconocer, esta se creará dentro de la carpeta Data que ya había creado previamente de forma manual. Entonces en la línea 5 en personName se asigana el nombre de la persona, en la línea 6 se asigna a dataPath la ubicación del directorio donde se creará cada carpeta con el nombre de cada persona a reconocer. Finalmente personPath será la ruta completa.

Línea 9 a 11: Con la información de las líneas pasadas, se creará el directorio con el nombre de la persona a reconocer dentro de la carpeta Data. En el la línea 5 por ejemplo puedes ver que se creará una carpeta llamada ‘Gaby’, que tendrías que modificar de acuerdo a las personas que quieras identificar.

Línea 13 y 14: En la línea 13 indicamos que vamos a realizar un video en directo, mientras que en la línea 14 leeremos un video. Puedes usar cualquiera de estas dos líneas para poder capturar los rostros.

Línea 23: Estoy redimensionando con imutils.resize (para más información sobre esta función ve a este link), esto lo hago para redimensionar el tamaño de los fotogramas del video de entrada.

Línea 32: Se está redimensionando las imágenes correspondientes a los rostros para que todos posean el mismo tamaño. Yo he elegido 150 pixeles, pero podrías hacerlo con otro valor.

Línea 48: En esta línea he añadido la condición de count >= 300 para que el proceso de almacenamiento termine a los 300 rostros almacenados.

Para este procedimiento voy a leer un video de una amiga muy especial para mí llamada Brenda, y un video mío. Puedes ver el procedimiento de almacenamiento de los rostros en este enlace.

Preparando los datos para entrenar

Antes de proceder con el entrenamiento es necesario tener cada una de las imágenes con una etiqueta asociada a la persona a la que pertenecen los rostros. Por ello, por ejemplo cuando leamos la carpeta ‘Persona 1’ todas esas imágenes se les asignará etiqueta 0, luego a todas imágenes de los rostros de ‘Persona 2’ se asignará 1,  de ‘Persona 3’ se asignará 2, y así sucesivamente. Con cada una de estas etiquetas le haremos saber al computador que las imágenes le corresponden a personas diferentes.

Figura 2: Ejemplo de rostros y etiquetas.

Entonces en otro script llamado entrenandoRF.py prepararemos este proceso, es decir las imágenes y etiquetas para poder entrenarlos empleando: Eigenfaces, fisherfaces y Local Binary Patterns Histograms.

import cv2
import os
import numpy as np

dataPath = 'C:/Users/Gaby/Desktop/Reconocimiento Facial/Data'#Cambia a la ruta donde hayas almacenado Data
peopleList = os.listdir(dataPath)
print('Lista de personas: ', peopleList)

labels = []
facesData = []
label = 0

for nameDir in peopleList:
    personPath = dataPath + '/' + nameDir
    print('Leyendo las imágenes')

    for fileName in os.listdir(personPath):
        print('Rostros: ', nameDir + '/' + fileName)
        labels.append(label)
        facesData.append(cv2.imread(personPath+'/'+fileName,0))
        #image = cv2.imread(personPath+'/'+fileName,0)
        #cv2.imshow('image',image)
        #cv2.waitKey(10)
    label = label + 1

#print('labels= ',labels)
#print('Número de etiquetas 0: ',np.count_nonzero(np.array(labels)==0))
#print('Número de etiquetas 1: ',np.count_nonzero(np.array(labels)==1))

Línea 1 a 3: Importamos OpenCV, os y numpy con un alias np.

Línea 5 a 7: En primer lugar especificamos la ruta de la carpeta ‘Data’ que habíamos creado manualmente antes y dentro de ella estará cada carpeta con el nombre de las personas que se desee identificar (lo habíamos realizado en el apartado anterior). En la línea 6 listamos todas los nombres de las carpetas almacenadas en ‘Data’. En la línea 7 imprimimos la lista obtenida.

Línea 9: Declaramos labels en este se almacenarán las etiquetas correspondientes a cada imagen según la persona.

Línea 10: Declaramos facesData en donde se almacenará cada una de las imágenes de los rostros.

Lo que necesitamos construir en la línea 9 y 10 es lo que podemos ver en la figura 2.

Línea 11: Estableceremos un contador label en 0, para conforme se termine de leer las imágenes de una persona, cambie a otro valor. Esto ayudará al clasificador a entender que se tarda de diferentes personas.

Línea 13 a 15: Vamos a leer cada una las carpetas dentro de ‘Data’. En personPath establecemos la ruta a la carpeta de cada persona. Mientras que en la línea 15 imprimimos el mensaje 'Leyendo las imágenes...' para que cuando se ejecute podamos saber en que parte del proceso estamos.

Línea 17 y 18: Aquí leeremos todas las imágenes correspondientes a cada rostro. En la línea 18 estamos imprimiendo el nombre de la carpeta y la imagen.

Línea 19: En labels vamos añadiendo la etiqueta de cada imagen.

Línea 20: En el array facesData añadiremos cada imagen (rostro).

Línea 21 a 23: Si deseamos leer cada imagen (rostro) para verificar que se está realizando bien el proceso, podemos descomentar estas líneas.

Línea 24: Cada vez que se termine de almacenar los rostros y etiquetas de una carpeta, se incrementará label en 1.

Línea 27 y 28: Podemos comprobar en número de etiquetas almacenadas, por ejemplo, cuantas están en 0, 1, etc. El número que obtengamos debe corresponder con el número de imágenes almacenadas en cada carpeta dentro de ‘Data’.

Ahora que tenemos listos nuestros datos (imágenes y etiquetas) en dos arrays es hora de realizar el entrenamiento, podrás escoger de cada uno de las tres técnicas de las cuales te había comentado, vamos a analizar cada una de ellas.

Entrenamiento del reconocerdor

Vamos a hablar brevemente de Eigenfaces, fisherfaces y Local Binary Patterns Histograms antes de pasar con el entrenamiento.

Te recomiendo que visites la documentación de OpenCV sobre estos métodos: https://docs.opencv.org/4.2.0/da/d60/tutorial_face_main.html#tutorial_face_eigenfaces

Eigenfaces

Este emplea el método PCA (Principal Component Analysis), lo que nos dice la documentación de OpenCV es: ‘La idea es que un conjunto de datos de alta dimensión a menudo se describe mediante variables correlacionadas y, por lo tanto, solo unas pocas dimensiones significativas explican la mayor parte de la información.’

Eigenfaces en OpenCV, cv2.face.EigenFaceRecognizer_create()

Para este método usaremos cv2.face.EigenFaceRecognizer_create(). Podríamos darle parámetros, sin embargo en este tutorial lo dejaremos vacío, pero si te interesa saber más sobre estos puedes visitar este link con su documentación.

Existen algunas consideraciones cuando vayamos a usar este método:

  • Las imágenes de entrenamiento como de predicción deben estar en escala de grises.
  • El método eigenfaces asume que todas las imágenes, ya sean de entrendamiento o test deben tener el mismo tamaño.

Fisherfaces

Este método es una mejora de anterior.

Fisherfaces en OpenCV, cv2.face.FisherFaceRecognizer_create()

Al igual que el método anterior, de dejaré el link a esta función para que profundices sobre ella en caso de ser necesario.

Consideraciones:

  • Las imágenes de entrenamiento como de predicción deben estar en escala de grises.
  • El método eigenfaces asume que todas las imágenes, ya sean de entrendamiento o test deben tener el mismo tamaño.

Local Binary Patterns Histograms

LBPH (Histogramas de Patrones Binarios Locales) presenta mejoras respecto a los métodos anteriores, ya que es más robusto ante cambios de iluminación. Además, citando a la documentación de OpenCV: ‘ La idea es no mirar la imagen completa como un vector de alta dimensión, sino describir solo las características locales de un objeto‘.

LBPH en OpenCV, cv2.face.LBPHFaceRecognizer_create()

Para esta función puedes usar distintos parámetros como radius, neighbors, grid_x, grid_y y threshold, para más información sobre estos puedes dirigirte a este link.

Consideraciones:

  • Las imágenes de entrenamiento como de predicción deben estar en escala de grises.
  • No se tiene especificaciones sobre el tamaño de las imágenes correspondientes a los rostros. Por lo tanto asumimos que pueden tener distinto tamaño.

Entrenado (Código)

Ahora que tenemos una idea de estos métodos para reconocimiento facial usando OpenCV, pasaremos al código. Podremos elegir entonces de los siguientes métodos (recuerda comentar los 2 que no vayas a usar):

# Métodos para entrenar el reconocedor
face_recognizer = cv2.face.EigenFaceRecognizer_create()
face_recognizer = cv2.face.FisherFaceRecognizer_create()
face_recognizer = cv2.face.LBPHFaceRecognizer_create()

Una vez que hayas elegido uno de estos métodos es hora de entrenar, y descuida que solo necesitarás una línea de código.

# Entrenando el reconocedor de rostros
print("Entrenando...")
face_recognizer.train(facesData, np.array(labels))

Línea 37: Para entrenar el reconocedor de rostros necesitamos de face_recognizer.train, en donde face_recognizer será la variable donde se asignó el método (cualquierda de las líneas  31, 32 o 33). Dentro de los paréntesis tendremos que especificar el array en donde estén contenidos los rostros o imágenes de entrenamiento, mientras que el segundo parámetro corresponde a las etiquetas. Es necesario que este sea un numpy array por ello he puesto np.array(labels).

Guardando el modelo obtenido

Una vez entrenado el modelo que nos servirá para reconocer rostros es posible almacenarlo. ¿Para qué nos serviría esto?, pues el entrenamiento toma tiempo, y más si son varias personas que se busca reconocer, es por eso que es mejor guardar el modelo obtenido para luego leerlo en otro script, así nos ahorramos el volverlo a entrenar.

Para almacenar el modelo usaremos write, dentro de los paréntesis deberemos especificar el nombre que deseamos asignarle, junto con la extensión XML o YAML.

# Almacenando el modelo obtenido
#face_recognizer.write('modeloEigenFace.xml')
#face_recognizer.write('modeloFisherFace.xml')
face_recognizer.write('modeloLBPHFace.xml')
print("Modelo almacenado...")

Línea 40 a 43: Usaremos write para guardar el modelo. Yo había elegido guardar un modelo por cada método (por separado), por ello usé distintos nombres en las líneas 40 a la 42. En la línea 43 imprimiremos un mensaje de 'Modelo almacenado...'.

Obtendrás el o los modelos almacenados algo parecido a lo siguiente:

Figura 3: Ejemplo del almacenamiento de distintos modelos.

Probando EigenFaces, Fisherfaces y LBPH para el reconocimiento facial

Ahora que hemos llegado hasta este punto, es hora de probar el reconocimiento. Crearemos un script llamado ReconocimientoFacial.py. El proceso que vamos a realizar, al igual que en el entrenamiento nos servirá para los tres métodos (por separado). Veamos:

import cv2
import os

dataPath = 'C:/Users/Gaby/Desktop/Reconocimiento Facial/Data' #Cambia a la ruta donde hayas almacenado Data
imagePaths = os.listdir(dataPath)
print('imagePaths=',imagePaths)

#face_recognizer = cv2.face.EigenFaceRecognizer_create()
#face_recognizer = cv2.face.FisherFaceRecognizer_create()
#face_recognizer = cv2.face.LBPHFaceRecognizer_create()

# Leyendo el modelo
#face_recognizer.read('modeloEigenFace.xml')
#face_recognizer.read('modeloFisherFace.xml')
#face_recognizer.read('modeloLBPHFace.xml')

#cap = cv2.VideoCapture(0,cv2.CAP_DSHOW)
#cap = cv2.VideoCapture('Video.mp4')

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

while True:
    ret,frame = cap.read()
    if ret == False: break
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    auxFrame = gray.copy()

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

    for (x,y,w,h) in faces:
        rostro = auxFrame[y:y+h,x:x+w]
        rostro = cv2.resize(rostro,(150,150),interpolation= cv2.INTER_CUBIC)
        result = face_recognizer.predict(rostro)

        cv2.putText(frame,'{}'.format(result),(x,y-5),1,1.3,(255,255,0),1,cv2.LINE_AA)
        '''
        # EigenFaces
        if result[1] < 5700:
            cv2.putText(frame,'{}'.format(imagePaths[result[0]]),(x,y-25),2,1.1,(0,255,0),1,cv2.LINE_AA)
            cv2.rectangle(frame, (x,y),(x+w,y+h),(0,255,0),2)
        else:
            cv2.putText(frame,'Desconocido',(x,y-20),2,0.8,(0,0,255),1,cv2.LINE_AA)
            cv2.rectangle(frame, (x,y),(x+w,y+h),(0,0,255),2)
        
        # FisherFace
        if result[1] < 500:
            cv2.putText(frame,'{}'.format(imagePaths[result[0]]),(x,y-25),2,1.1,(0,255,0),1,cv2.LINE_AA)
            cv2.rectangle(frame, (x,y),(x+w,y+h),(0,255,0),2)
        else:
            cv2.putText(frame,'Desconocido',(x,y-20),2,0.8,(0,0,255),1,cv2.LINE_AA)
            cv2.rectangle(frame, (x,y),(x+w,y+h),(0,0,255),2)
        
        # LBPHFace
        if result[1] < 70:
            cv2.putText(frame,'{}'.format(imagePaths[result[0]]),(x,y-25),2,1.1,(0,255,0),1,cv2.LINE_AA)
            cv2.rectangle(frame, (x,y),(x+w,y+h),(0,255,0),2)
        else:
            cv2.putText(frame,'Desconocido',(x,y-20),2,0.8,(0,0,255),1,cv2.LINE_AA)
            cv2.rectangle(frame, (x,y),(x+w,y+h),(0,0,255),2)
        '''
    cv2.imshow('frame',frame)
    k = cv2.waitKey(1)
    if k == 27:
        break

cap.release()
cv2.destroyAllWindows()

Antes de pasar con la explicación del programa, debo decir este agrupa como probar el funcionamiento del reconocimiento facial con cada uno de los tres métodos vistos en este post. Cuando llegue la hora desglozaremos cada uno de ellos.

Línea 1 y 2: Importamos OpenCV y os.

Línea 4 a 6: Voy a especificar la ruta en donde están las carpetas de las personas que vamos a reconocer, y las listaremos para obtener únicamente sus nombres. Esto lo hago ya que al momento de realizar el reconocimiento facial tomaré de aquí los nombres para que se visualicen. 

Línea 8 a 11: Establezco el método que voy a usar para realizar el reconocimiento facial, puedes descomentar la línea que corresponda a aquel con el que entrenaste el reconocedor.

Línea 13 a 15: Para poder leer el modelo almacenado usaremos read, el nombre del modelo corresponderá al que se almacenó en la sección anterior.

Línea 17 y 18: Tienes dos opciones para poder probar el funcionamiento del reconocedor de caras, en la línea 17 por ejemplo puedes hacerlo a través de un videostreaming, mientras que en la línea 18 a través de la lectura de un video.

Línea 20 a 32: Aquí haremos el mismo procedimiento que en el primer programa capturandoRostros.py, vamos a leer el clasificador de rostros, luego pasamos con la lectura de los fotogramas, transformamos a escala de grises, detectamos los rostros, luego vamos con el análisis de cada uno de los rostros detectados, los recortamos y redimensionamos. Realizamos esto ya que las imágenes con las que entrenamos, como en los nuevos rostros se debe aplicar el mismo proceso.

Línea 33: En esta línea vamos a emplear predict para una nueva imagen llamada rostro que nos permitirá predecir los resultados. Esto lo hemos asignado a result, por lo que en la posición 0 tendremos una etiqueta (0, 1, …) y el valor de confianza, este último será diferente para cada método.

predict()

Predice una etiqueta y la confianza asociada (por ejemplo, la distancia) para una imagen de entrada determinada.

NOTA 1: Algo que hay que tener en cuenta es que al aplicar predict,  obtendremos una etiqueta y su valor de confianza asociado. Vamos a tener muy en cuenta este segundo valor ya que dependiendo este podremos aceptar o descartar el reconocimiento.

NOTA 2: Los valores (valor de confianza) más bajos o cercanos a cero querrá decir que el rostro a identificar tiene mucha similitud al de los entrenados, mientras que al tener valores muchos más altos el grado de similitud será más pobre por lo que podremos descartarlos. Cabe destacar que dependiendo de cada método obtendremos distintos valores de confianza que podremos comparar.

Línea 35: Visualizamos los resultados obtenidos en result.

De las líneas 37 a 59, las explicaré luego ya que dependerán de cada método empleado.

Línea 61 a 67: Procedemos a visualizar frame, el proceso se dentendrá cuando se presione ‘Esc’, se terminará con el video y se cerrarán todas las ventanas de visualización

Probando EigenFaces

Si descomentamos las líneas 8 y 13 correspondientes al método EigenFaces, vamos a obtener una etiqueta con el rostro más parecido a los entrenados junto con su valor de confianza. Tendremos que realizar algunas pruebas para determinar un umbral para que aparezca el nombre de la persona identificada y para valores mayores a este umbral será considerado como rostro desconocido.

Una vez que hemos probado el código y hemos experimentado, procederemos a descomentar las líneas 37 a 43.

# EigenFaces
if result[1] < 5700:
    cv2.putText(frame,'{}'.format(imagePaths[result[0]]),(x,y-25),2,1.1,(0,255,0),1,cv2.LINE_AA)
    cv2.rectangle(frame, (x,y),(x+w,y+h),(0,255,0),2)
else:
    cv2.putText(frame,'Desconocido',(x,y-20),2,0.8,(0,0,255),1,cv2.LINE_AA)
    cv2.rectangle(frame, (x,y),(x+w,y+h),(0,0,255),2)

Línea 38: Comparo el valor de confianza que está en result[1] con 5700, de tal modo que valores menores a este se etiquete con el nombre de la persona y valores mayores a este se estiquete como desconocido. El umbral 5700 que he escogido ha sido a través de prueba y error, por lo que tu debes cambiar este con la experimentación que realices con respecto a tus resultados.

Línea 39 y 40: En la línea 39 vamos a visualizar el nombre de la persona correspondiente al valor de la etiqueta almacenada en result[0], para ello usaremos imagePaths para obtener los nombres. En la línea 40 dibujaremos un rectángulo de color verde alrededor del rostro detectado.

Línea 42 y 43: En caso de que el valor de confianza supere 5700 (en mi caso), se visualizará 'Desconocido' y un rectángo rojo que rodee el rostro.

Veamos los resultados al aplicar este método y este umbral (puedes ver las pruebas aquí):

Probando FisherFaces

Ahora probaremos el reconocimiento facial empleando Fisher Faces. Tendrías que descomentar las líneas 9, 14 y de la 45 a 51.

# FisherFace
if result[1] < 500:
    cv2.putText(frame,'{}'.format(imagePaths[result[0]]),(x,y-25),2,1.1,(0,255,0),1,cv2.LINE_AA)
    cv2.rectangle(frame, (x,y),(x+w,y+h),(0,255,0),2)
else:
    cv2.putText(frame,'Desconocido',(x,y-20),2,0.8,(0,0,255),1,cv2.LINE_AA)
    cv2.rectangle(frame, (x,y),(x+w,y+h),(0,0,255),2)

Línea 46: En mi caso después de realizar algunas pruebas establecí un umbral de 500 de tal modo que valores menores a este se visualizará el nombre de la persona, mientras que valores mayores a este se visualizará como rostro desconocido.

Línea 47 y 48: Se visualizará el nombre de la persona y un rectángulo que rodee el rostro de color verde.

Línea 50 y 51: En caso de que el valor sea mayor a 500 se visualizará ‘Desconocido’ y un rectángulo que rodee el rostro de color rojo.

Veamos algunas pruebas realizadas (puedes ver las pruebas aquí):

Probando LBPH

Para probar este método descomentaremos las líneas 10, 15, 53 a 59. Analicemos estas últimas:

# LBPHFace
if result[1] < 70:
    cv2.putText(frame,'{}'.format(imagePaths[result[0]]),(x,y-25),2,1.1,(0,255,0),1,cv2.LINE_AA)
    cv2.rectangle(frame, (x,y),(x+w,y+h),(0,255,0),2)
else:
    cv2.putText(frame,'Desconocido',(x,y-20),2,0.8,(0,0,255),1,cv2.LINE_AA)
    cv2.rectangle(frame, (x,y),(x+w,y+h),(0,0,255),2)

Línea 54: Con esté método después de pruebas he establecido un umbral de 70 de tal modo que valores mayores son tratados como desconocidos y menores se etiqueta a cada uno de los rostros.

Línea 55 y 56: Se visualiza de color verde el nombre de la persona identificada y un rectángulo que rodee el rostro.

Línea 58 y 59: Se visualiza de color rojo ‘Desconocido’ y un rectángulo que rodee el rostro.

(puedes ver las pruebas aquí)

Prueba extra en directo (video streaming)

Ahora, con este último método voy a probar el reconocimiento facial con un videostreaming. Lo voy a hacer en un lugar diferente al que usé para realizar la captura de rostros (al alimentar el clasificiador), además de usar otra cámara y otra iluminación, veamos:

NOTA: Este procedimeinto lo puedes ver en video aquí.

Quería mostrarte este análisis extra, ya que te podría pasar algo similar, y es que al aplicar reconocimiento facial en este videostreaming ha fallado. Esto se debe a la falta de diversidad en las condiciones de las imágenes con las que entrené el reconocedor.

Para mejorar el reconocimiento voy a incrementar 100 rostros con este ambiente, a más de los 300 que tenía inicialmente, así que en total tendré 400 imágenes con mi rostros y entrenaré nuevamente.

Una vez obtenido el modelo, probemos el reconocimiento a ver que tal nos va:

Entonces recuerda que para mayor robustes o para que mejor reconozca  debes tener mayor diversidad en las imágenes (rostros) con las que vayas a entrenar. 

Referencias:

  • https://docs.opencv.org/4.2.0/da/d60/tutorial_face_main.html
  • https://docs.opencv.org/4.2.0/dd/d7c/classcv_1_1face_1_1EigenFaceRecognizer.html
  • https://www.superdatascience.com/blogs/opencv-face-recognition
  • https://docs.opencv.org/4.2.0/dd/d7c/classcv_1_1face_1_1EigenFaceRecognizer.html
  • https://docs.opencv.org/3.4/d2/de9/classcv_1_1face_1_1FisherFaceRecognizer.html
  • https://docs.opencv.org/3.4/df/d25/classcv_1_1face_1_1LBPHFaceRecognizer.html
  • https://docs.opencv.org/master/dd/d65/classcv_1_1face_1_1FaceRecognizer.html#ac8680c2aa9649ad3f55e27761165c0d6
  • https://docs.opencv.org/master/dd/d65/classcv_1_1face_1_1FaceRecognizer.html#a2adf2d555550194244b05c91fefcb4d6