Время прочтения: 3 мин.

В данной статье мы постараемся решить достаточно актуальную задачу для нашего времени, а именно методами computer vision будем определять наличие на лице маски. Данную задачу можно разбить на две части: нужно найти лицо человека, после чего определить есть ли на нем маска. Для написания данной программы возьмем уже обученную нейронную сеть для второй части (ссылка), для обнаружения лица будем использовать стандартное решение для такого рода задач — каскады Хаара (ссылка). Модель обучалась на ~ 1300 примерах изображений лиц людей, 50% которых были в масках, остальные 50% без масок.

Данную программу мы реализуем в Colab, у которого не всегда работает отображение картинок от OpenCV, поэтому импортируем некоторые дополнительные модули.

import cv2
from tensorflow.keras.preprocessing.image import img_to_array
from tensorflow.keras.models import load_model
from tensorflow.keras.applications.mobilenet_v2 import preprocess_input
import numpy as np
from google.colab.patches import cv2_imshow

Загружаем каскады и модель.

faceCascade = cv2.CascadeClassifier("haarcascade_frontalface_alt2.xml")
model = load_model("mask_recog.h5")

Далее создадим функцию face_mask_detector, которая принимает на вход картинку, а на выходе выдает ее же с информацией о наличии маски.

Для начала нужно полученное изображение перевести из цветного в изображение в оттенках серого (BGR -> GRAY), далее определяем лица людей на картинке, добавляя их в список. После этого проверяем наличие маски, при условии найденного лица и в отдельный список добавляем “уверенность” нашей модели в результате. В зависимости от результата выделяем лицо на изображении зеленым цветом, если маска есть, красным — если ее нет. Выводим текст и прямоугольник на картинку.

def face_mask_detector(frame):

  gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
  faces = faceCascade.detectMultiScale(gray,
                                        scaleFactor = 1.1,
                                        minNeighbors = 5,
                                        minSize = (60, 60),
                                        flags = cv2.CASCADE_SCALE_IMAGE)
  
  faces_list = []
  preds = []
  
  for (x, y, w, h) in faces:
      face_frame = frame[y:y + h, x:x + w]
      face_frame = cv2.cvtColor(face_frame, cv2.COLOR_BGR2RGB)
      face_frame = cv2.resize(face_frame, (224, 224))
      face_frame = img_to_array(face_frame)
      face_frame = np.expand_dims(face_frame, axis = 0)
      face_frame =  preprocess_input(face_frame)
      faces_list.append(face_frame)
      
      if len(faces_list) > 0:
          preds = model.predict(faces_list)
      
      for pred in preds:
          (mask, withoutMask) = pred
      
      label = "Mask" if mask > withoutMask else "No Mask"
      color = (0, 255, 0) if label == "Mask" else (0, 0, 255)
      label = "{}: {}%".format(label, int(max(mask, withoutMask) * 100))
      cv2.putText(frame, label, (x, y - 10),
                  cv2.FONT_HERSHEY_SIMPLEX, 1, color, 2)
      cv2.rectangle(frame, (x, y), (x + w, y + h),color, 3)

  return frame

Протестируем работу данной программы. Загрузим новую картинку и передадим ее в нашу функцию, выводим результат на экран.

input_image = cv2.imread("image.jpg")
output = face_mask_detector(input_image)
cv2_imshow(output)

Модель показывает неплохие результаты и достаточно точно определяет наличие маски. Данный скрипт можно использовать для работы  в реальном времени (немного его изменив), допустим, используя веб-камеру, обрабатывать каждый кадр.