How to build face mask detector application?

Marcin Laskowski
detect face mask

More and more companies struggle with a difficult Covid situation. In the following tutorial, we would like to show you a simple, and fast way to build a face mask detector app.

Introduction

In the following tutorial, we will show you how to Develop, Deploy, and Integrate a Keras Face Mask Detector algorithm using Syndicai Platform. For this purpose, we will use Chandrika Deb implementation that is one of the best available on Github. The main goal of that algorithm is to detect whether a person in the picture is wearing a mask, or not. If you would like to try the state of the art of the basic object detection algorithm, check out how to deploy yolov5.

Let’s start!

Step 1 | Develop

In the first phase of the tutorial, we need to prepare a model for deployment. In order to do it in the right way, the best way is to follow the checklist below.

1. Train your model

Before you start model preparation you need to be sure that your model is trained. In our case, a model is already trained so we don’t have to go through that task. However, if you would like to explore object detection training workflow, please go to train yolov5 algorithm.

2. Create a Git repository

Your main model files need to be placed in a git repository. However, if you have large files (e.g. with model weights) you can store them in a separate storage or drive so that Syndicai will download them during model initialization.

In our model storing in separate storage is not necessary, because MobileNetV2 architecture is very lightweight and can be easily placed in a Github repository directly.

repository with a face mask detector
Repository with a Face Mask Detector

3. Add syndicai.py & requirements.txt

In order to deploy a model with Syndicai you need to have syndicai.py and requirements.txt placed in your main directory.

syndicai.py is the main file with the PythonPredictor python class responsible for model prediction. It consist of two methods __init__and predict that are necessary to properly run a model.

import os
import cv2
import numpy as np

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 utils import url_to_image, b64_to_image, image_to_base64


args = {
    "image": "sample_data/out.jpg",
    "face": "face_detector",
    "model": "model/mask_detector.model",
    "confidence": 0.5,
}


class PythonPredictor:

    def __init__(self, config):
        # load our serialized face detector model from disk
        print("[INFO] loading face detector model...")
        prototxtPath = os.path.sep.join([args["face"], "deploy.prototxt"])
        weightsPath = os.path.sep.join([args["face"],
                                        "res10_300x300_ssd_iter_140000.caffemodel"])
        self.net = cv2.dnn.readNet(prototxtPath, weightsPath)

        # load the face mask detector model from disk
        print("[INFO] loading face mask detector model...")
        self.model = load_model(args["model"])

    def predict(self, payload):

        # Get image from url
        try: 
            image = url_to_image(payload["image_url"])
        except:
            image = b64_to_image(payload["image_b64"])
        orig = image.copy()
        (h, w) = image.shape[:2]

        # construct a blob from the image
        blob = cv2.dnn.blobFromImage(image, 1.0, (300, 300),
                                     (104.0, 177.0, 123.0))

        # pass the blob through the network and obtain the face detections
        print("[INFO] computing face detections...")
        self.net.setInput(blob)
        detections = self.net.forward()

        # 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 > args["confidence"]:
                # 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 = image[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)
                face = np.expand_dims(face, axis=0)

                # pass the face through the model to determine if the face
                # has a mask or not
                (mask, withoutMask) = self.model.predict(face)[0]

                # 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(image, label, (startX, startY - 10),
                                    cv2.FONT_HERSHEY_SIMPLEX, 0.45, color, 2)
                cv2.rectangle(
                    image, (startX, startY), (endX, endY), color, 2)

        return image_to_base64(image)d

requirements.txt – a file with all libraries and frameworks needed to recreate the model’s environment

tensorflow==1.15.2
keras==2.3.1
imutils==0.5.3
numpy==1.18.2
opencv-python==4.2.0.*
matplotlib==3.2.1
argparse==1.1
scipy==1.4.1
scikit-learn==0.23.1
pillow==7.2.0

For the Face Mask Detector, we also need other functions and files, so you can explore them in the main repository.

It is important to notice that model weights are initialized in the init method which is run only once, before the model is in the Active state.

Step 2 | Deploy

In order to deploy a model, you need connect your repo to the Syndicai Platform, so that the whole infrastructure will be created.

1. Connect a git repository

Go to Syndicai Platform and press New Model on the “Overview” page. You will be redirected to a short form. Place the URL for your model (In our case it is: https://github.com/syndicai/models/tree/master/keras/face_mask_detector)

Press “Continue” and “Deploy” in the next card.

Deploy a model via Syndicai Platform
When you press ‘New Model’ you will be redirected to a quick form to Connect a repo.

2. Wait for the Active model

Now the whole magic happens. Syndicai creates a webservice, builds a docker, and run a model on the scalable Kubernetes cluster automatically so that you don’t need to care about the infrastructure setup. You can go to the Model “Builds” section to see logs from the build.

You need to have a build with status success and model with status Active.

Face Mask Detection algorithm deployed via Syndicai
When build will turn into success state you will notice that your model is Active.

Step 3 | Integrate

Congratulations, You have deployed your model!

Now you can go to the model page and Run it on the platform in the “Run a model” section. Our syndicai.py file was written in a way that can handle two different image input formats: URL or base64.

{
	"image_url": "https://bsmedia.business-standard.com/_media/bs/img/article/2020-07/12/full/1594519569-3012.JPG"
}
{
	"image_b64": "/9j/4AAQSkZJRgABAQAAAQABA..."
}

You can copy one of them and paste it in the “Run a model” section.

Run a Face Mask detection model
Paste a sample input JSON in order to run a model

When a model is working properly you can go to the “Integrate” subpage and use REST API to integrate a model with a frontend page. For the frontend page, you can use React, Nextjs or other frameworks. However, you can also try our ready-made template with a Face Mask Detector showcase. The whole code for that demo page is open-source so you can fork and play with it as you like.

Closing remarks

The main goal of that tutorial was first of all to inspire you and then show that you can deploy any trained AI model in minutes. No config needed, no deep tech knowledge required – just a simple way from a model to actual use case with a click of a button.

If you like this kind of content or would like to see how to deploy some particular mode please, drop us a line or find us on slack!