Tabla de contenido:

Reconocimiento facial en tiempo real: un proyecto de principio a fin: 8 pasos (con imágenes)
Reconocimiento facial en tiempo real: un proyecto de principio a fin: 8 pasos (con imágenes)

Video: Reconocimiento facial en tiempo real: un proyecto de principio a fin: 8 pasos (con imágenes)

Video: Reconocimiento facial en tiempo real: un proyecto de principio a fin: 8 pasos (con imágenes)
Video: Todo lo que el reconocimiento facial permite saber sobre nosotros 2024, Mes de julio
Anonim
Reconocimiento facial en tiempo real: un proyecto de principio a fin
Reconocimiento facial en tiempo real: un proyecto de principio a fin

En mi último tutorial explorando OpenCV, aprendimos SEGUIMIENTO AUTOMÁTICO DE OBJETOS DE VISIÓN. Ahora usaremos nuestra PiCam para reconocer rostros en tiempo real, como puedes ver a continuación:

Imagen
Imagen

Este proyecto se realizó con esta fantástica "Biblioteca de visión por computadora de código abierto", la OpenCV. En este tutorial, nos centraremos en Raspberry Pi (es decir, Raspbian como sistema operativo) y Python, pero también probé el código en Mi Mac y también funciona bien. OpenCV fue diseñado para la eficiencia computacional y con un fuerte enfoque en aplicaciones en tiempo real. Por lo tanto, es perfecto para el reconocimiento facial en tiempo real con una cámara.

Para crear un proyecto completo sobre Reconocimiento facial, debemos trabajar en 3 fases muy diferenciadas:

  1. Detección de rostros y recopilación de datos
  2. Entrena al reconocedor
  3. Reconocimiento facial

El siguiente diagrama de bloques reanuda esas fases:

Imagen
Imagen

Paso 1: BoM - Lista de materiales

Partes principales:

  1. Raspberry Pi V3 - US $ 32,00
  2. 5 megapíxeles 1080p Sensor OV5647 Mini módulo de video de cámara - US $ 13.00

Paso 2: Instalación del paquete OpenCV 3

Instalación del paquete OpenCV 3
Instalación del paquete OpenCV 3

Estoy usando una Raspberry Pi V3 actualizada a la última versión de Raspbian (Stretch), por lo que la mejor manera de tener OpenCV instalado, es seguir el excelente tutorial desarrollado por Adrian Rosebrock: Raspbian Stretch: Instale OpenCV 3 + Python en su Raspberry Pi.

Probé varias guías diferentes para instalar OpenCV en mi Pi. El tutorial de Adrian es el mejor. Te aconsejo que hagas lo mismo, siguiendo su pauta paso a paso.

Una vez que haya terminado el tutorial de Adrian, debe tener un entorno virtual OpenCV listo para ejecutar nuestros experimentos en su Pi.

Vayamos a nuestro entorno virtual y confirmemos que OpenCV 3 está instalado correctamente.

Adrian recomienda ejecutar el comando "fuente" cada vez que abra una nueva terminal para asegurarse de que las variables de su sistema se hayan configurado correctamente.

fuente ~ /.profile

A continuación, entremos en nuestro entorno virtual:

trabajar en cv

Si ve el texto (cv) que precede a su mensaje, entonces se encuentra en el entorno virtual cv:

(cv) pi @ frambuesa: ~ $Adrian llama la atención sobre el hecho de que el entorno virtual cv Python es completamente independiente y está aislado de la versión predeterminada de Python incluida en la descarga de Raspbian Stretch. Por lo tanto, cualquier paquete de Python en el directorio global site-packages no estará disponible para el entorno virtual cv. De manera similar, cualquier paquete de Python instalado en paquetes de sitio de cv no estará disponible para la instalación global de Python

Ahora, ingrese su intérprete de Python:

pitón

y confirme que está ejecutando la versión 3.5 (o superior)

Dentro del intérprete (aparecerá el ">>>"), importe la biblioteca OpenCV:

importar cv2

Si no aparecen mensajes de error, el OpenCV está instalado correctamente EN SU ENTORNO VIRTUAL PYTHON.

También puede comprobar la versión de OpenCV instalada:

cv2._ versión_

Debería aparecer la 3.3.0 (o una versión superior que se puede lanzar en el futuro). La pantalla de impresión del terminal anterior muestra los pasos anteriores.

Paso 3: prueba tu cámara

Probando su cámara
Probando su cámara

Una vez que tenga OpenCV instalado en su RPi, hagamos una prueba para confirmar que su cámara está funcionando correctamente.

Supongo que ya tiene una PiCam instalada en su Raspberry Pi.

Ingrese el siguiente código de Python en su IDE:

importar numpy como np

import cv2 cap = cv2. VideoCapture (0) cap.set (3, 640) # set Width cap.set (4, 480) # set Height while (True): ret, frame = cap.read () frame = cv2. flip (marco, -1) # Voltear la cámara verticalmente gris = cv2.cvtColor (marco, cv2. COLOR_BGR2GRAY) cv2.imshow ('marco', marco) cv2.imshow ('gris', gris) k = cv2.waitKey (30) & 0xff si k == 27: # presione 'ESC' para salir de romper cap.release () cv2.destroyAllWindows ()

El código anterior capturará la transmisión de video que generará su PiCam, mostrando ambos, en color BGR y en modo gris.

Tenga en cuenta que giré mi cámara verticalmente debido a la forma en que está ensamblada. Si no es su caso, comente o elimine la línea de comando "flip".

Alternativamente, puede descargar el código de mi GitHub: simpleCamTest.py

Para ejecutar, ingrese el comando:

python simpleCamTest.py

Para finalizar el programa, debe presionar la tecla [ESC] en su teclado.

Haga clic con el mouse en la ventana de video, antes de presionar [ESC]

La imagen de arriba muestra el resultado.

Algunos fabricantes encontraron problemas al intentar abrir la cámara (mensajes de error "Aserción fallida"). Eso podría suceder si la cámara no se habilitó durante la instalación de OpenCv y, por lo tanto, los controladores de la cámara no se instalaron correctamente. Para corregir, use el comando:

sudo modprobe bcm2835-v4l2

También puede agregar bcm2835-v4l2 a la última línea del archivo / etc / modules para que el controlador se cargue al arrancar.

Para saber más sobre OpenCV, puede seguir el tutorial: loading -video-python-opencv-tutorial

Paso 4: Detección de rostro

Detección de rostro
Detección de rostro
Detección de rostro
Detección de rostro

La tarea más básica del reconocimiento facial es, por supuesto, la "detección de rostros". Antes que nada, debes "capturar" un rostro (Fase 1) para poder reconocerlo, en comparación con un nuevo rostro capturado en el futuro (Fase 3).

La forma más común de detectar una cara (o cualquier objeto) es utilizando el "clasificador Haar Cascade"

La detección de objetos mediante clasificadores en cascada basados en características de Haar es un método eficaz de detección de objetos propuesto por Paul Viola y Michael Jones en su artículo, "Detección rápida de objetos mediante una cascada mejorada de características simples" en 2001. Es un enfoque basado en el aprendizaje automático en el que un La función de cascada se entrena a partir de una gran cantidad de imágenes positivas y negativas. Luego se usa para detectar objetos en otras imágenes.

Aquí trabajaremos con detección de rostros. Inicialmente, el algoritmo necesita muchas imágenes positivas (imágenes de rostros) e imágenes negativas (imágenes sin rostros) para entrenar al clasificador. Entonces necesitamos extraer características de él. La buena noticia es que OpenCV viene con un entrenador y un detector. Si desea entrenar su propio clasificador para cualquier objeto como automóvil, aviones, etc., puede usar OpenCV para crear uno. Sus detalles completos se dan aquí: Entrenamiento de clasificador en cascada.

Si no desea crear su propio clasificador, OpenCV ya contiene muchos clasificadores previamente entrenados para rostro, ojos, sonrisa, etc. Esos archivos XML se pueden descargar desde el directorio haarcascades.

Basta de teoría, ¡creemos un detector de rostros con OpenCV!

Descarga el archivo: faceDetection.py desde mi GitHub.

importar numpy como np

import cv2 faceCascade = cv2. CascadeClassifier ('Cascades / haarcascade_frontalface_default.xml') cap = cv2. VideoCapture (0) cap.set (3, 640) # set Width cap.set (4, 480) # set Height while True: ret, img = cap.read () img = cv2.flip (img, -1) gris = cv2.cvtColor (img, cv2. COLOR_BGR2GRAY) caras = faceCascade.detectMultiScale (gris, scaleFactor = 1.2, minNeighbors = 5, minSize = (20, 20)) para (x, y, w, h) en caras: cv2.rectangle (img, (x, y), (x + w, y + h), (255, 0, 0), 2) roi_gray = gris [y: y + h, x: x + w] roi_color = img [y: y + h, x: x + w] cv2.imshow ('video', img) k = cv2.waitKey (30) & 0xff si k == 27: # presione 'ESC' para salir de romper cap.release () cv2.destroyAllWindows ()

Lo crea o no, las pocas líneas de código anteriores son todo lo que necesita para detectar una cara, usando Python y OpenCV.

Cuando lo compare con el último código utilizado para probar la cámara, se dará cuenta de que se le agregaron pocas partes. Tenga en cuenta la línea siguiente:

faceCascade = cv2. CascadeClassifier ('Cascades / haarcascade_frontalface_default.xml')

Esta es la línea que carga el "clasificador" (que debe estar en un directorio llamado "Cascades /", bajo el directorio de su proyecto).

Luego, configuraremos nuestra cámara y dentro del bucle, cargaremos nuestro video de entrada en modo escala de grises (lo mismo que vimos antes).

Ahora debemos llamar a nuestra función clasificadora, pasándole algunos parámetros muy importantes, como factor de escala, número de vecinos y tamaño mínimo del rostro detectado.

caras = faceCascade.detectMultiScale (gray, scaleFactor = 1.2, minNeighbors = 5, minSize = (20, 20))

Dónde,

  • el gris es la imagen de entrada en escala de grises.
  • scaleFactor es el parámetro que especifica cuánto se reduce el tamaño de la imagen en cada escala de imagen. Se utiliza para crear la pirámide de escala.
  • minNeighbors es un parámetro que especifica cuántos vecinos debe tener cada rectángulo candidato para retenerlo. Un número más alto da menos falsos positivos.
  • minSize es el tamaño mínimo de rectángulo para ser considerado una cara.

La función detectará rostros en la imagen. A continuación, debemos "marcar" las caras en la imagen, utilizando, por ejemplo, un rectángulo azul. Esto se hace con esta parte del código:

para (x, y, w, h) en caras:

cv2.rectangle (img, (x, y), (x + w, y + h), (255, 0, 0), 2) roi_gray = gris [y: y + h, x: x + w] roi_color = img [y: y + h, x: x + w]

Si se encuentran caras, devuelve las posiciones de las caras detectadas como un rectángulo con la esquina superior izquierda (x, y) y teniendo "w" como su Ancho y "h" como su Alto ==> (x, y, w, h). Por favor, vea la imagen de arriba.

Una vez que obtenemos estas ubicaciones, podemos crear un "ROI" (rectángulo dibujado) para la cara y presentar el resultado con la función imshow ().

Ejecute el script de Python anterior en su entorno de Python, usando la Terminal Rpi:

python faceDetection.py

El resultado:

Imagen
Imagen

También puede incluir clasificadores para "detección de ojos" o incluso "detección de sonrisas". En esos casos, incluirá la función de clasificador y el dibujo del rectángulo dentro del bucle de la cara, porque no tendría sentido detectar un ojo o una sonrisa fuera de una cara.

Tenga en cuenta que en una Pi, tener varios clasificadores en el mismo código ralentizará el procesamiento, una vez que este método de detección (HaarCascades) utiliza una gran cantidad de poder computacional. En un escritorio, es más fácil ejecutarlo.

En mi GitHub encontrarás otros ejemplos:

faceEyeDetection.py

faceSmileDetection.py

faceSmileEyeDetection.py

Y en la imagen de arriba puedes ver el resultado.

También puede seguir el siguiente tutorial para comprender mejor la detección de rostros:

Haar Cascade Object Detection Face & Eye OpenCV Python Tutorial

Paso 5: recopilación de datos

Recopilación de datos
Recopilación de datos
Recopilación de datos
Recopilación de datos

En primer lugar, debo agradecer a Ramiz Raja por su gran trabajo en el reconocimiento facial en fotos:

RECONOCIMIENTO FACIAL CON OPENCV Y PYTHON: UNA GUÍA PARA PRINCIPIANTES

y también Anirban Kar, que desarrolló un tutorial muy completo usando video:

RECONOCIMIENTO FACIAL - 3 partes

Realmente te recomiendo que eches un vistazo a ambos tutoriales.

Dicho esto, comencemos la primera fase de nuestro proyecto. Lo que haremos aquí, es comenzar desde el último paso (Detección de rostros), simplemente crearemos un conjunto de datos, donde almacenaremos para cada identificación, un grupo de fotos en gris con la parte que se utilizó para la detección de rostros.

Primero, cree un directorio donde desarrolle su proyecto, por ejemplo, FacialRecognitionProject:

mkdir FacialRecognitionProject

En este directorio, además de los 3 scripts en python que crearemos para nuestro proyecto, debemos tener guardado en él el Clasificador Facial. Puedes descargarlo de mi GitHub: haarcascade_frontalface_default.xml

A continuación, cree un subdirectorio donde almacenaremos nuestras muestras faciales y lo nombraremos "conjunto de datos":

conjunto de datos mkdir

Y descargue el código de mi GitHub: 01_face_dataset.py

importar cv2

import os cam = cv2. VideoCapture (0) cam.set (3, 640) # set video width cam.set (4, 480) # set video height face_detector = cv2. CascadeClassifier ('haarcascade_frontalface_default.xml') # Para cada persona, ingrese un ID de rostro numérico face_id = input ('\ n ingrese el ID de usuario y presione ==>') print ("\ n [INFO] Inicializando la captura de rostros. Mire la cámara y espere…") # Inicialice el recuento del conteo de rostros de muestreo individual = 0 while (True): ret, img = cam.read () img = cv2.flip (img, -1) # voltear imagen de video verticalmente gris = cv2.cvtColor (img, cv2. COLOR_BGR2GRAY) caras = face_detector.detectMultiScale (gris, 1.3, 5) para (x, y, w, h) en caras: cv2.rectangle (img, (x, y), (x + w, y + h), (255, 0, 0), 2) count + = 1 # Guarde la imagen capturada en la carpeta de conjuntos de datos cv2.imwrite ("dataset / User." + str (face_id) + '.' + str (count) + ".jpg", gris [y: y + h, x: x + w]) cv2.imshow ('image', img) k = cv2.waitKey (100) & 0xff # Presione 'ESC' para salir del video si k == 27: break elif count> = 30: # Tomar 30 muestras de caras y detener la pausa de video # Hacer ab it of cleanup print ("\ n [INFO] Saliendo del programa y cosas de limpieza") cam.release () cv2.destroyAllWindows ()

El código es muy similar al código que vimos para la detección de rostros. Lo que agregamos fue un "comando de entrada" para capturar una identificación de usuario, que debería ser un número entero (1, 2, 3, etc.)

face_id = input ('\ n ingrese la identificación del usuario y presione ==>')

Y para cada uno de los fotogramas capturados, debemos guardarlo como un archivo en un directorio de "conjunto de datos":

cv2.imwrite ("conjunto de datos / Usuario." + str (face_id) + '.' + str (cuenta) + ".jpg", gris [y: y + h, x: x + w])

Tenga en cuenta que para guardar el archivo anterior, debe haber importado la biblioteca "os". El nombre de cada archivo seguirá la estructura:

User.face_id.count.jpg

Por ejemplo, para un usuario con face_id = 1, el cuarto archivo de muestra en el directorio / conjunto de datos será algo como:

Usuario.1.4.jpg

como se muestra en la foto de arriba de mi Pi. En mi código, estoy capturando 30 muestras de cada id. Puede cambiarlo en el último "elif". El número de muestras se utiliza para romper el bucle donde se capturan las muestras faciales.

Ejecute la secuencia de comandos de Python y capture algunos ID. Debe ejecutar el script cada vez que desee agregar un nuevo usuario (o cambiar las fotos por uno que ya existe).

Paso 6: Entrenador

Entrenador
Entrenador

En esta segunda fase, debemos tomar todos los datos del usuario de nuestro conjunto de datos y "entrenar" el OpenCV Recognizer. Esto se realiza directamente mediante una función específica de OpenCV. El resultado será un archivo.yml que se guardará en un directorio "trainer /".

Entonces, comencemos a crear un subdirectorio donde almacenaremos los datos entrenados:

entrenador mkdir

Descargue de mi GitHub el segundo script de Python: 02_face_training.py

importar cv2

import numpy as np from PIL import Image import os # Path for face image database path = 'dataset' Recognizer = cv2.face. LBPHFaceRecognizer_create () detector = cv2. CascadeClassifier ("haarcascade_frontalface_default.xml"); # función para obtener las imágenes y los datos de la etiqueta def getImagesAndLabels (ruta): imagePaths = [os.path.join (ruta, f) para f en os.listdir (ruta)] faceSamples = ids = para imagePath en imagePaths: PIL_img = Image.open (imagePath).convert ('L') # convertirlo a escala de grises img_numpy = np.array (PIL_img, 'uint8') id = int (os.path.split (imagePath) [- 1]. split (".") [1]) faces = detector.detectMultiScale (img_numpy) para (x, y, w, h) en caras: faceSamples.append (img_numpy [y: y + h, x: x + w]) ids.append (id) return faceSamples, ids print ("\ n [INFO] Entrenar caras. Tardará unos segundos. Espera…") caras, ids = getImagesAndLabels (ruta) Recognizer.train (caras, np.array (ids)) # Guarde el modelo en trainer / trainer.yml Recognizer.write ('trainer / trainer.yml') # Recognizer.save () funcionó en Mac, pero no en Pi # Imprima el número de caras entrenadas y finalice la impresión del programa ("\ n [INFO] {0} rostros entrenados. Saliendo del programa".format (len (np.unique (ids))))

Confirme si tiene la biblioteca PIL instalada en su Rpi. De lo contrario, ejecute el siguiente comando en la Terminal:

pip instalar almohada

Usaremos como reconocedor, el Reconocimiento facial LBPH (LOCAL BINARY PATTERNS HISTOGRAMS), incluido en el paquete OpenCV. Hacemos esto en la siguiente línea:

reconocedor = cv2.face. LBPHFaceRecognizer_create ()

La función "getImagesAndLabels (ruta)", tomará todas las fotos en el directorio: "conjunto de datos /", devolviendo 2 matrices: "ID" y "caras". Con esas matrices como entrada, "entrenaremos nuestro reconocedor":

Recognizer.train (caras, identificadores)

Como resultado, se guardará un archivo llamado "trainer.yml" en el directorio del entrenador que fue creado previamente por nosotros.

¡Eso es todo! Incluí la última declaración impresa donde mostré para confirmación, el número de caras de usuario que hemos entrenado.

Cada vez que realiza la Fase 1, la Fase 2 también debe ejecutarse

Paso 7: reconocedor

Reconocedor
Reconocedor
Reconocedor
Reconocedor

Ahora, llegamos a la fase final de nuestro proyecto. Aquí, capturaremos una cara nueva en nuestra cámara y si esta persona tuvo su cara capturada y entrenada antes, nuestro reconocedor hará una "predicción" devolviendo su identificación y un índice, mostrando qué tan seguro está el reconocedor con esta coincidencia.

Descarguemos el script de Python de la tercera fase de mi GitHub: 03_face_recognition.py.

importar cv2

import numpy as np import os Recognizer = cv2.face. LBPHFaceRecognizer_create () Recognizer.read ('trainer / trainer.yml') cascadePath = "haarcascade_frontalface_default.xml" faceCascade = cv2. CascadeClassifier (cascadePath); font = cv2. FONT_HERSHEY_SIMPLEX #iniciate id counter id = 0 # nombres relacionados con ids: ejemplo ==> Marcelo: id = 1, etc names = ['None', 'Marcelo', 'Paula', 'Ilza', 'Z ',' W '] # Inicializa e inicia la captura de video en tiempo real cam = cv2. VideoCapture (0) cam.set (3, 640) # set video widht cam.set (4, 480) # set video height # Define el tamaño mínimo de la ventana para ser reconocido como una cara minW = 0.1 * cam.get (3) minH = 0.1 * cam.get (4) while True: ret, img = cam.read () img = cv2.flip (img, -1) # Voltear verticalmente gris = cv2.cvtColor (img, cv2. COLOR_BGR2GRAY) caras = faceCascade.detectMultiScale (gray, scaleFactor = 1.2, minNeighbors = 5, minSize = (int (minW), int (minH)),) para (x, y, w, h) en caras: cv2.rectangle (img, (x, y), (x + w, y + h), (0, 255, 0), 2) id, confianza = reconocedor.predicto (gris [y: y + h, x: x + w]) # Compruebe si la confianza es menor que ellos 100 ==> "0" es una coincidencia perfecta si (confianza <100): id = nombres [id] confianza = "{0}% ".format (round (100 - confianza)) else: id =" desconocido "confianza =" {0}% ". formato (round (100 - conf idence)) cv2.putText (img, str (id), (x + 5, y-5), font, 1, (255, 255, 255), 2) cv2.putText (img, str (confianza), (x + 5, y + h-5), fuente, 1, (255, 255, 0), 1) cv2.imshow ('cámara', img) k = cv2.waitKey (10) & 0xff # Presione 'ESC' para salir del video si k == 27: break # Hacer un poco de limpieza print ("\ n [INFO] Saliendo del programa y cosas de limpieza") cam.release () cv2.destroyAllWindows ()

Incluimos aquí una nueva matriz, por lo que mostraremos "nombres", en lugar de identificadores numerados:

nombres = ['Ninguno', 'Marcelo', 'Paula', 'Ilza', 'Z', 'W']

Entonces, por ejemplo: Marcelo será el usuario con id = 1; Paula: id = 2, etc.

A continuación, detectaremos una cara, igual que hicimos antes con el clasificador haasCascade. Teniendo una cara detectada podemos llamar a la función más importante en el código anterior:

id, confianza = reconocedor.predicto (parte gris de la cara)

El Recognizer.predict (), tomará como parámetro una porción capturada de la cara a analizar y devolverá su probable propietario, indicando su id y cuánta confianza tiene el reconocedor en relación con esta coincidencia.

Tenga en cuenta que el índice de confianza devolverá "cero" si se considera una coincidencia perfecta

Y por último, si el reconocedor puede predecir una cara, colocamos un texto sobre la imagen con la identificación probable y cuánto es la "probabilidad" en% de que la coincidencia sea correcta ("probabilidad" = 100 - índice de confianza). De lo contrario, se coloca una etiqueta de "desconocido" en la cara.

Debajo un-g.webp

Imagen
Imagen

En la imagen de arriba, muestro algunas pruebas realizadas con este proyecto, donde también he usado fotos para verificar si el reconocedor funciona.

Paso 8: Conclusión

Conclusión
Conclusión

Como siempre, espero que este proyecto pueda ayudar a otros a encontrar su camino hacia el apasionante mundo de la electrónica.

Para obtener detalles y el código final, visite mi depósito de GitHub: OpenCV-Face-Recognition

Para más proyectos, visite mi blog: MJRoBot.org

A continuación, un vistazo a un tutorial futuro, donde exploraremos el "seguimiento automático de rostros y otros métodos para la detección de rostros":

Imagen
Imagen

¡Saludos desde el sur del mundo!

¡Nos vemos en mi próximo instructable!

Gracias, Marcelo

Recomendado: