Detecta si una persona lleva mascarilla 馃樂 | OpenCV con Python

Por Administrador

En este tutorial te mostrar茅 como puedes construir tu propio detector de mascarillas de una forma f谩cil y r谩pida. Adem谩s estar茅 usando contenido que hab铆amos visto antes, para la detecci贸n de rostros MediaPipe Face Detection y para el entrenamiento LBPH FaceRecognizer que usamos en el tutorial de Reconocimiento Facial. 隆An铆mate a probarlo!.

CONTENIDO

Detectar si una persona lleva puesta mascarilla

  1. 聽Dataset
  2. 聽Entrenamiento
  3. 隆A probar el modelo!

Detectar si una persona lleva puesta mascarilla

Para la realizaci贸n de este proyecto necesitaremos tener instalados en聽python:聽Numpy,聽OpenCV聽Y聽MediaPipe.

He dividido a este proyecto en 3 secciones de las cuales har茅 una descripci贸n adem谩s del c贸digo empleado en cada una de ellas (a excepci贸n de la primera, ya que para esa secci贸n no usamos c贸digo).

NOTA: Para m谩s informaci贸n sobre el c贸digo que veremos en este tutorial, por favor dir铆gete al videotutorial.

1) Dataset

Figura 1: Ilustraci贸n del dataset que usaremos en este tutorial.

Para comenzar veremos un dataset con dos clases, por un lado tendremos im谩genes a color de rostros con mascarillas, y en otro directorio im谩genes de rostros de personas sin mascarillas. Estas im谩genes fueron obtenidas luego de aplicar la detecci贸n de rostros con mediapipe, para ser redimensionadas a cierto alto y ancho.聽

Para acceder a este dataset puedes visitar mi repositorio en github: https://github.com/GabySol/OmesTutorials2021/tree/main/Mascarillas%20dataset

2) Entrenamiento

Una vez que hemos descargado el dataset, vamos a entrenar un modelo con Local Binary Patter Histogram Face Recognizer, que es uno de los m茅todos que hab铆amos visto en el tutorial de reconocimiento facial. De este modo vamos a experimentar si este m茅todo nos puede servir para ver si una persona lleva mascarilla o no, ya que este m茅todo se suele usar para el reconocimiento facial. Para ello construiremos el siguiente script llamado train.py.

import cv2
import os
import numpy as np

dataPath = ".../Dataset_faces"
dir_list = os.listdir(dataPath)
print("Lista archivos:", dir_list)

labels = []
facesData = []
label = 0

for name_dir in dir_list:
     dir_path = dataPath + "/" + name_dir
     
     for file_name in os.listdir(dir_path):
          image_path = dir_path + "/" + file_name
          print(image_path)
          image = cv2.imread(image_path, 0)
          #cv2.imshow("Image", image)
          #cv2.waitKey(10)

          facesData.append(image)
          labels.append(label)
     label += 1

print("Etiqueta 0: ", np.count_nonzero(np.array(labels) == 0))
print("Etiqueta 1: ", np.count_nonzero(np.array(labels) == 1))

# LBPH FaceRecognizer
face_mask = cv2.face.LBPHFaceRecognizer_create()

# Entrenamiento
print("Entrenando...")
face_mask.train(facesData, np.array(labels))

# Almacenar modelo
face_mask.write("face_mask_model.xml")
print("Modelo almacenado")

En la l铆nea 5, debes cambiar el path por aquel en donde almacenaste la carpeta que contenga el dataset.

Al momento de ejecutar el script, ver谩s algo similar a lo siguiente:

Figura 2: Visualizaci贸n del modelo obtenido luego de entrenamiento.

En la figura 2 podemos apreciar que tenemos: la carpeta del dataset, el modelo obtenido luego de ejecutar el script train.py.

3) 隆A probar el modelo!

Figura 3: Ilustraci贸n del procedimiento que se sigue para probar las detecciones.

Por 煤ltimo, vamos a probar nuestro modelo entrenado, para ello tendremos que聽a las im谩genes de entrada, aplicarles la detecci贸n de rostros con聽mediapipe (que es lo que se aplic贸 para obtener las im谩genes del entrenamiento).

Luego tendremos que recortar la imagen del rostro, para aplicarle escala de grises y redimensionarla. De este modo estaremos aplicando los mismos procedimientos tanto a las im谩genes que ten铆amos de entrenamiento, como con las que vamos a probar nuestro modelo.

Para probar nuestro modelo crearemos un script llamado test_face_mask.py.

import cv2
import os
import mediapipe as mp

mp_face_detection = mp.solutions.face_detection

LABELS = ["Con_mascarilla", "Sin_mascarilla"]

# Leer el modelo
face_mask = cv2.face.LBPHFaceRecognizer_create()
face_mask.read("face_mask_model.xml")

cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)

with mp_face_detection.FaceDetection(
     min_detection_confidence=0.5) as face_detection:

     while True:
          ret, frame = cap.read()
          if ret == False: break
          frame = cv2.flip(frame, 1)

          height, width, _ = frame.shape
          frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
          results = face_detection.process(frame_rgb)

          if results.detections is not None:
               for detection in results.detections:
                    xmin = int(detection.location_data.relative_bounding_box.xmin * width)
                    ymin = int(detection.location_data.relative_bounding_box.ymin * height)
                    w = int(detection.location_data.relative_bounding_box.width * width)
                    h = int(detection.location_data.relative_bounding_box.height * height)
                    if xmin < 0 and ymin < 0:
                         continue
                    #cv2.rectangle(frame, (xmin, ymin), (xmin + w, ymin + h), (0, 255, 0), 5)

                    face_image = frame[ymin : ymin + h, xmin : xmin + w]
                    face_image = cv2.cvtColor(face_image, cv2.COLOR_BGR2GRAY)
                    face_image = cv2.resize(face_image, (72, 72), interpolation=cv2.INTER_CUBIC)
                    
                    result = face_mask.predict(face_image)
                    #cv2.putText(frame, "{}".format(result), (xmin, ymin - 5), 1, 1.3, (210, 124, 176), 1, cv2.LINE_AA)

                    if result[1] < 150:
                         color = (0, 255, 0) if LABELS[result[0]] == "Con_mascarilla" else (0, 0, 255)
                         cv2.putText(frame, "{}".format(LABELS[result[0]]), (xmin, ymin - 15), 2, 1, color, 1, cv2.LINE_AA)
                         cv2.rectangle(frame, (xmin, ymin), (xmin + w, ymin + h), color, 2)

          cv2.imshow("Frame", frame)
          k = cv2.waitKey(1)
          if k == 27:
               break

cap.release()
cv2.destroyAllWindows()

Recuerda que para una explicaci贸n m谩s extendida sobre el c贸digo, puedes echarle un vistazo al videotutorial.

Veamos algunas im谩genes de las pruebas que hemos hecho para probar el detector de mascarillas:

Figura 4: Pruebas realizadas de la detecci贸n de mascarillas.

Si quieres ver algunas pruebas que he realizado de este programa puedes ver el siguiente video:

Y hemos llegado al final de este tutorial, espero que te haya parecido 煤til. Nos vemos en un siguiente, 隆chao, chao!. 馃檪