Detecta si una persona lleva mascarilla ? | OpenCV con Python
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
- Dataset
- Entrenamiento
- ¡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!. ?
Excelente video, me sirvió mucho y despertó curiosidad para desarrollar cosas referentes a la pandemia en mi, gracias mucho exito.
Muchas gracias Fernando! 🙂
OpenCV(4.2.0) C:\projects\opencv-python\opencv\modules\imgproc\src\color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function ‘cv::cvtColor’
File «C:\Users\Martin\Desktop\Deteccion de barbijo\test_face_mask.py», line 37, in
face_image = cv2.cvtColor(face_image, cv2.COLOR_BGR2GRAY)
Hola me da este error cuando saco la cara de la camara y la vuelvo a poner. Hay alguna solución?
Hola Martin, al parecer no se obtuvo ninguna imagen en face_image.
Hola Gaby, perdona que te moleste es que me está dando este error al momento de entrenar el algoritmo y no se me crea el modelo.
cv2.error: OpenCV(4.5.4-dev) D:\a\opencv-python\opencv-python\opencv\modules\core\src\matrix.cpp:250: error: (-215:Assertion failed) s >= 0 in function ‘cv::setSize’
Hola Nicole, está correctamente leída la imagen?. Trata de solo visualizar la imagen a ver si el problema va por allí.
Hola, disculpa, pudiste solucionar el error?
Hola hermosa, siempre sigo tus tutoriales pero esta vez algo no me funciona durante el entrenamiento, me sale este error:
Etiqueta 0: 385
Etiqueta 1: 385
Entrenando…
Traceback (most recent call last):
File «d:\Dropbox\2021-II\PROGRAMACIÓN PARA ANALÍTICA DE DATOS\Proyectos\Detección de Tapabocas\train_mask.py», line 37, in
face_mask.train(facesData, np.array(labels))
cv2.error: OpenCV(4.5.4-dev) D:\a\opencv-python\opencv-python\opencv\modules\core\src\matrix.cpp:250: error: (-215:Assertion failed) s >= 0 in function ‘cv::setSize’
¿Sabes qué puede ser?
Hola Carlos, si no me equivoco, parece que alguna imagen no se ha leído correctamennte.
Hola Carlos, si no me equivoco, parece que alguna imagen no se ha leído correctamente.
Estoy con el mismo problema no puede guardar el modelop creado y no se para donde darle el numpy es el problema
Hola, podrías mostrar un script para hacer la detección y redimensión del nuevo dataset?. Esque estoy usando el mismo método pero para otra detección, y el dataset que encontre el internet pesa demasiado y quiero tenerlo en 72×72 como en tu video
Excelente contenido, pregunta, ¿es posible aplicar el detector de rostros aun teniendo la mascarilla?, es decir poder idetificar a cada quien aun con la mascarilla puesta.
Hola! Buen dia, En primera darte las gracias por tan excelente conetido.
En segunda, veo que otros comentarios hablan sobre el error que les da al momento de ntrenar el modelo y tambien al guardarlo. A mi me da este error:
cv2.error: OpenCV(4.6.0) :-1: error: (-5:Bad argument) in function ‘train’
> Overload resolution failed:
> – Can’t parse ‘src’. Sequence item with index 0 has a wrong type
Como podria solucionarlo?
Aqui dejo la parte del codigo de la que me marca error:
#Entrenamiento
print(‘Entrenando….’)
face_mask.train(faces_data,np.array(labels))
#Almacenamiento modelo
face_mask.write(«face_mask_model.xml»)
print(«Modelo almacenado»)
Muchas gracias, buen dia
Hola que tal, tengo una duda, si lo que yo quiero entrenar es una base de datos de imagenes de cacao en las siguientes lineas del Codigo
# LBPH FaceRecognizer
face_mask = cv2.face.LBPHFaceRecognizer_create()
que deberia poner, ya que esta se utiliza para la deteccion de rostros pero en mi caso no estoy utilizando rostros, si me podrias ayudar estaria muy agradecida
como puedo cambiar el valor de confianza a un 100%