Hi guys! In this article, I’m going to tell you how to create your own face mask detector model. I’ll be using a Face Mask dataset created by Prajna Bhandary. This dataset consists of 1,376 images belonging to two classes, with mask and without mask.

The main focus of this model is to detect whether a person is wearing a mask or not.

Overview

Firstly, we get the image with the face and run it through a cascade classifier. The classifier will give the region of interest of the face (height and width).

Secondly, we will resize the region of interest and pass it to a pre-trained CNN, it will give us the probability as an output.

Dataset

To train a deep learning model to classify whether a person is wearing a mask or not, we need to find a good dataset with a fair amount of images for both classes:

  • wearing a mask
  • not wearing a mask

I have used the face mask dataset created by Prajna Bhandary. You can access the dataset here.

Building Face Mask Detector model

For building the model, I am going to use Keras and TensorFlow to train a classifier to automatically detect whether a person is wearing a mask or not.

I’ll be fine-tuning the MobileNet V2 architecture with pre-trained ImageNet weights, a highly efficient architecture that can be applied to embedded devices with limited computational capacity.

Import necessary libraries

from tensorflow.keras.preprocessing.image import ImageDataGenerator, img_to_array, load_img
from tensorflow.keras.applications import MobileNetV2
from tensorflow.keras.layers import AveragePooling2D, Dropout, Flatten, Dense, Input
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.applications.mobilenet_v2 import preprocess_input
from tensorflow.keras.utils import to_categorical
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from imutils import paths
import numpy as np
import os

I’ll be using:

  • tensorflow.keras for data augmentation, loading the MobilNetV2 classifier, building a new fully-connected (FC) head, pre-processing and loading image data
  • scikit-learn (sklearn) for binarizing class labels, segmenting our dataset, and printing a classification report.
  • imutils paths implementation will help us to find and list images in our dataset.
  • matplotlib to plot our training curves

Define path to Dataset

Now, provide a path to the dataset which contains with masks and without masks images.

dataset_path = "dataset"

Define Parameters

Next, I’ll define parameters which will hold the initial learning rate, number of epochs and batch size.

INIT_LR = 1e-4
EPOCHS = 20
BS = 32

Load and pre-process data

Now, I’ll be loading and pre-processing the data.

imagePaths = list(paths.list_images(dataset_path))
images = []
labels = []

for img_path in imagePaths:
    # extract the class label from the filename
    label = img_path.split(os.path.sep)[-2]

    # load the input image (224x224) and preprocess it
    image = load_img(img_path, target_size=(224, 224))
    image = img_to_array(image)
    image = preprocess_input(image)

    # update the data and labels lists, respectively
    images.append(image)
    labels.append(label)

Firstly, I have grabbed paths of all the images in imagePaths variable. Then, I have initialized images and labels list. Next, I’ll loop over imagePaths and extract the lable from the image path which will later be appended to labels list. Images will be pre-processed and then they are appended to images list.

Now, I’ll convert images and labels into numpy array and the result will be stored in data and labels variable.

data = np.array(images, dtype="float32")
labels = np.array(labels)

Next, I’ll perform one-hot encoding on our class labels.

# perform one-hot encoding on the labels
labelbinarizer = LabelBinarizer()
labels = labelbinarizer.fit_transform(labels)
labels = to_categorical(labels)

Next, I’ll be segmenting our data into training and testing part using scikit’s learn train_test_split. I’ll use 80% data for training and rest 20% for testing.

(trainX, testX, trainY, testY) = train_test_split(data, labels, test_size=0.20, stratify=labels, random_state=42)

To improve generalization, I’ll perform data augmentation where the random rotation, zoom, shear, shift, and flip parameters are established.

# construct the training image generator for data augmentation
datagen = ImageDataGenerator(
    rotation_range=25,
    zoom_range=0.2,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.2,
    horizontal_flip=True,
    fill_mode="nearest")

Fine-tuning

Next, I’ll be preparing MobileNetV2 classifier for fine-tuning.

bModel = MobileNetV2(weights="imagenet", include_top=False, input_tensor=Input(shape=(224, 224, 3)))

# construct the head of the model that will be placed on top of the the base model
hModel = bModel.output
hModel = AveragePooling2D(pool_size=(5, 5))(hModel)
hModel = Flatten(name="flatten")(hModel)
hModel = Dense(128, activation="relu")(hModel)
hModel = Dropout(0.5)(hModel)
hModel = Dense(2, activation="softmax")(hModel)

model = Model(inputs=bModel.input, outputs=hModel)

for layer in bModel.layers:
    layer.trainable = False

To perform fine-tuning, firstly I’ll load MobileNet with pre-trained ImageNet weights, leaving off head of the network. Then, I’ll construct a new Fully connected head and replace in with the old head in base (line 11). Next, I’ll freeze the base layers of the network. The weights of these base layers will not be updated during the process of backpropagation, whereas the head layer weights will be tuned.

Training and Compiling the model

Now, as our data have been prepared and model architecture is ready, we are now ready to compile and train our face mask detector model.

# compile our model
opt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS)
model.compile(loss="binary_crossentropy", optimizer=opt, metrics=["accuracy"])

# train the head
H = model.fit(
    datagen.flow(trainX, trainY, batch_size=BS),
    steps_per_epoch=len(trainX) // BS,
    validation_data=(testX, testY),
    validation_steps=len(testX) // BS,
    epochs=EPOCHS)

I have used Adam optimizer and binary cross-entropy to compile the model. 

Saving the model

Lastly, I’ll be saving the model so that it can be used in future.

#save the model
print("saving the mask detector model...")
model.save("model_mask.h5")
print('MODEL SAVED')

Conclusion

Our face mask detector is accurate, and since we used the MobileNetV2 architecture, it’s also computationally efficient. We can deploy this model to embedded systems as well. If we deployed it correctly, we can help ensure the safety of others. You can access the entire code here.

That’s it for the article. I hope it’ll be useful for someone.

If you enjoyed this article, share it with your friends and colleagues! Thank you and stay safe!

-Pratiksha Goyal


7 Comments

Kostik · June 4, 2020 at 6:11 pm

Thanks a lot for the article post.Much thanks again. Fantastic.

Mansi · June 7, 2020 at 3:59 pm

Thanks so much for the post.Really thank you! Great.

Anit kumar · June 11, 2020 at 8:35 am

Thanks a lot for the article post.Much thanks again. Fantastic.

Aayush · June 23, 2020 at 10:21 am

Thank you for your blog post.Really thank you! Awesome.

Viagra per super-prestazioni · June 28, 2020 at 7:31 pm

Thanks so much for the post.Really thank you! Keep writing.viagra per super-prestazioni

Milley · July 4, 2020 at 12:26 pm

Thanks so much for the post.Really thank you! Keep writing.

ปั้มไลค์ · July 9, 2020 at 3:40 pm

Like!! I blog quite often and I genuinely thank you for your information. The article has truly peaked my interest.

Leave a Reply

Your email address will not be published. Required fields are marked *

Insert math as
Block
Inline
Additional settings
Formula color
Text color
#333333
Type math using LaTeX
Preview
\({}\)
Nothing to preview
Insert