En este artículo, analizaremos nuestro detector de máscara facial COVID-19 de dos fases y detallaremos cómo se implementará nuestra canalización de aprendizaje profundo/visión por computadora.
Usaremos este script de Python para entrenar un detector de mascarillas y revisar los resultados. Dado el detector de máscara facial COVID-19 capacitado, procederemos a implementar dos scripts de Python adicionales que se utilizan para:
- Detectar máscaras faciales COVID-19 en imágenes
- Detecta máscaras faciales en transmisiones de video en tiempo real
Diagrama de flujo del sistema de detección de mascarillas
Para entrenar un detector de máscara facial personalizado, debemos dividir nuestro proyecto en dos fases distintas, cada una con sus respectivos subpasos (como se muestra en la Figura 1 anterior):
- Entrenamiento: aquí nos centraremos en cargar nuestro conjunto de datos de detección de máscaras faciales desde el disco, entrenar un modelo (usando Keras/TensorFlow) en este conjunto de datos y luego serializar el detector de máscaras faciales en el disco.
- Despliegue: una vez que se entrena el detector de mascarillas, podemos pasar a cargar el detector de mascarillas, realizar la detección de rostros y luego clasificar cada rostro como con_mascarilla o sin_mascarilla.
Usaremos estas imágenes para construir un modelo CNN usando TensorFlow para detectar si está usando una máscara facial usando la cámara web de su PC. ¡Además, también puedes usar la cámara de tu teléfono para hacer lo mismo!
Implementación paso a paso
Paso 1: visualización de datos
En el primer paso, visualicemos el número total de imágenes en nuestro conjunto de datos en ambas categorías. Podemos ver que hay 690 imágenes en la clase ‘sí’ y 686 imágenes en la clase ‘no’.
Número de imágenes con máscara facial etiquetada como ‘sí’: 690
Número de imágenes con máscara facial etiquetada como ‘no’: 686
Paso 2: aumento de datos
En el siguiente paso, aumentamos nuestro conjunto de datos para incluir más imágenes para nuestro entrenamiento. En este paso de aumento de datos, rotamos y volteamos cada una de las imágenes en nuestro conjunto de datos. Vemos que, después del aumento de datos, tenemos un total de 2751 imágenes con 1380 imágenes en la clase ‘sí’ y ‘1371’ imágenes en la clase ‘no’.
Número de ejemplos: 2751
Porcentaje de ejemplos positivos: 50,163576881134134 %, número de ejemplos pos: 1380
Porcentaje de ejemplos negativos: 49,836423118865866 %, número de ejemplos negativos: 1371
Paso 3: dividir los datos
En este paso, dividimos nuestros datos en el conjunto de entrenamiento que contendrá las imágenes en las que se entrenará el modelo CNN y el conjunto de prueba con las imágenes en las que se probará nuestro modelo. En esto, tomamos split_size =0.8, lo que significa que el 80 % del total de imágenes se destinará al conjunto de entrenamiento y el 20 % restante de las imágenes se destinará al conjunto de prueba.
El número de imágenes con máscara facial en el conjunto de entrenamiento con la etiqueta ‘sí’: 1104
El número de imágenes con máscara facial en el conjunto de prueba con la etiqueta ‘sí’: 276
El número de imágenes sin máscara facial en el conjunto de entrenamiento con la etiqueta ‘no’: 1096
El número de imágenes sin máscara facial en el conjunto de prueba etiquetadas como ‘no’: 275
Después de dividir, vemos que el porcentaje deseado de imágenes se ha distribuido tanto al conjunto de entrenamiento como al conjunto de prueba como se mencionó anteriormente.
Paso 4: Construcción del modelo
En el siguiente paso, construimos nuestro modelo de CNN secuencial con varias capas, como Conv2D, MaxPooling2D, Flatten, Dropout y Dense. En la última capa densa, usamos la función ‘softmax’ para generar un vector que da la probabilidad de cada una de las dos clases.
Python3
model = tf.keras.models.Sequential([ tf.keras.layers.Conv2D(100, (3, 3), activation='relu', input_shape=(150, 150, 3)), tf.keras.layers.MaxPooling2D(2, 2), tf.keras.layers.Conv2D(100, (3, 3), activation='relu'), tf.keras.layers.MaxPooling2D(2, 2), tf.keras.layers.Flatten(), tf.keras.layers.Dropout(0.5), tf.keras.layers.Dense(50, activation='relu'), tf.keras.layers.Dense(2, activation='softmax') ]) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
Aquí, usamos el optimizador ‘adam’ y ‘binary_crossentropy’ como nuestra función de pérdida ya que solo hay dos clases. Además, incluso puede usar MobileNetV2 para una mayor precisión.
Paso 5: Pre-entrenamiento del modelo CNN
Después de construir nuestro modelo, creemos ‘train_generator’ y ‘validation_generator’ para adaptarlos a nuestro modelo en el siguiente paso. Vemos que hay un total de 2200 imágenes en el conjunto de entrenamiento y 551 imágenes en el conjunto de prueba.
Encontradas 2200 imágenes pertenecientes a 2 clases.
Encontradas 551 imágenes pertenecientes a 2 clases.
Paso 6: Entrenamiento del modelo CNN
Este paso es el paso principal en el que ajustamos nuestras imágenes en el conjunto de entrenamiento y el conjunto de prueba en nuestro modelo secuencial que construimos usando la biblioteca keras. He entrenado el modelo durante 30 épocas (iteraciones). Sin embargo, podemos entrenar para una mayor cantidad de épocas para lograr una mayor precisión para que no se produzca un ajuste excesivo.
history = model.fit_generator(train_generator, epochs
=30,
validation_data=validation_generator,
callbacks=[checkpoint])
>>Época 30/30
220/220 [================== ============] – 231 s 1 s/paso – pérdida: 0,0368 – acc: 0,9886 – val_loss: 0,1072 – val_acc: 0,9619
Vemos que después de la época 30, nuestro modelo tiene una precisión del 98,86 % con el conjunto de entrenamiento y una precisión del 96,19 % con el conjunto de prueba. Esto implica que está bien entrenado sin ningún tipo de ajuste excesivo.
Paso 7: Etiquetado de la información
Después de construir el modelo, etiquetamos dos probabilidades para nuestros resultados. [‘0’ como ‘sin_máscara’ y ‘1’ como ‘con_máscara’] . También estoy configurando el color del rectángulo límite usando los valores RGB. [‘ROJO’ para ‘sin_mascarilla’ y ‘VERDE’ para ‘con_mascarilla]
etiquetas_dict={0:’sin_máscara’,1:’con_máscara’}
color_dict={0:(0,0,255),1:(0,255,0)}
Paso 8: Importación del programa de detección de rostros
Después de esto, pretendemos usarlo para detectar si estamos usando una máscara facial usando la cámara web de nuestra PC. Para esto, primero, necesitamos implementar la detección de rostros. En esto, estamos utilizando los clasificadores en cascada basados en características de Haar para detectar las características faciales.
face_clsfr=cv2.CascadeClassifier(‘haarcascade_frontalface_default.xml’)
Este clasificador en cascada está diseñado por OpenCV para detectar el rostro frontal entrenando miles de imágenes. El archivo .xml para el mismo debe descargarse y usarse para detectar el rostro. Hemos subido el archivo al repositorio de GitHub.
Paso 9: Detección de rostros con y sin máscaras
En el último paso, usamos la biblioteca OpenCV para ejecutar un bucle infinito para usar nuestra cámara web en la que detectamos la cara usando el Clasificador en cascada. El código webcam = cv2.VideoCapture(0) indica el uso de la cámara web.
El modelo predecirá la posibilidad de cada una de las dos clases ([sin_máscara, con_máscara]) . Según la probabilidad más alta, la etiqueta se elegirá y se mostrará alrededor de nuestras caras.
principal.py
Python3
# import the necessary packages from tensorflow.keras.applications.mobilenet_v2 import preprocess_input from tensorflow.keras.preprocessing.image import img_to_array from tensorflow.keras.models import load_model from imutils.video import VideoStream import numpy as np import imutils import time import cv2 import os def detect_and_predict_mask(frame, faceNet, maskNet): # grab the dimensions of the frame and # then construct a blob from it (h, w) = frame.shape[:2] blob = cv2.dnn.blobFromImage(frame, 1.0, (224, 224), (104.0, 177.0, 123.0)) # pass the blob through the network # and obtain the face detections faceNet.setInput(blob) detections = faceNet.forward() print(detections.shape) # initialize our list of faces, their # corresponding locations, and the list # of predictions from our face mask network faces = [] locs = [] preds = [] # loop over the detections for i in range(0, detections.shape[2]): # extract the confidence (i.e., # probability) associated with # the detection confidence = detections[0, 0, i, 2] # filter out weak detections by # ensuring the confidence is # greater than the minimum confidence if confidence > 0.5: # compute the (x, y)-coordinates # of the bounding box for # the object box = detections[0, 0, i, 3:7] * np.array([w, h, w, h]) (startX, startY, endX, endY) = box.astype("int") # ensure the bounding boxes fall # within the dimensions of # the frame (startX, startY) = (max(0, startX), max(0, startY)) (endX, endY) = (min(w - 1, endX), min(h - 1, endY)) # extract the face ROI, convert it # from BGR to RGB channel # ordering, resize it to 224x224, # and preprocess it face = frame[startY:endY, startX:endX] face = cv2.cvtColor(face, cv2.COLOR_BGR2RGB) face = cv2.resize(face, (224, 224)) face = img_to_array(face) face = preprocess_input(face) # add the face and bounding boxes # to their respective lists faces.append(face) locs.append((startX, startY, endX, endY)) # only make a predictions if at least one # face was detected if len(faces) > 0: # for faster inference we'll make # batch predictions on *all* # faces at the same time rather # than one-by-one predictions # in the above `for` loop faces = np.array(faces, dtype="float32") preds = maskNet.predict(faces, batch_size=32) # return a 2-tuple of the face locations # and their corresponding locations return (locs, preds) # load our serialized face detector model from disk prototxtPath = r"face_detector\deploy.prototxt" weightsPath = r"face_detector\res10_300x300_ssd_iter_140000.caffemodel" faceNet = cv2.dnn.readNet(prototxtPath, weightsPath) # load the face mask detector model from disk maskNet = load_model("mask_detector.model") # initialize the video stream print("[INFO] starting video stream...") vs = VideoStream(src=0).start() # loop over the frames from the video stream while True: # grab the frame from the threaded # video stream and resize it # to have a maximum width of 400 pixels frame = vs.read() frame = imutils.resize(frame, width=400) # detect faces in the frame and # determine if they are wearing a # face mask or not (locs, preds) = detect_and_predict_mask(frame, faceNet, maskNet) # loop over the detected face # locations and their corresponding # locations for (box, pred) in zip(locs, preds): # unpack the bounding box and predictions (startX, startY, endX, endY) = box (mask, withoutMask) = pred # determine the class label and # color we'll use to draw # the bounding box and text label = "Mask" if mask > withoutMask else "No Mask" color = (0, 255, 0) if label == "Mask" else (0, 0, 255) # include the probability in the label label = "{}: {:.2f}%".format(label, max(mask, withoutMask) * 100) # display the label and bounding box # rectangle on the output frame cv2.putText(frame, label, (startX, startY - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.45, color, 2) cv2.rectangle(frame, (startX, startY), (endX, endY), color, 2) # show the output frame cv2.imshow("Frame", frame) key = cv2.waitKey(1) & 0xFF # if the `q` key was pressed, break from the loop if key == ord("q"): break # do a bit of cleanup cv2.destroyAllWindows() vs.stop()
Producción:
Publicación traducida automáticamente
Artículo escrito por diveshmandhyanlkodm03 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA