Face Mask Detection in 5 minutes with dploy.ai & Go

Dylan Meeus
dploy.ai
Published in
4 min readMay 26, 2020

At dploy.ai we have made it easy to deploy AI models (it’s in the name really 😃) and use them from anywhere, with any language. Well, as long as you can make POST requests that is. As usually my blogs use Go, that will be our language of choice this time as well 😃

First things first, head over to app.dploy.ai where you will find a small selection of ML models on the (provided by dploy.ai or Dataroots). Currently we have a small selection but expect this to grow as we open up the platform to more users. Anyway, in our case, let’s go ahead and click on “try model” for the Face Mask Detection model by Dataroots. This will bring you to the overview page, where you can read up on some detail of how to use this model with curl. The curl line also tells us which URL we need to use, in this case: https://3345423f-8bbf-4215-8004-215a3da67b60.users.dploy.ai/

First we need to ‘subscribe’ to a model, which will generate some keys for us as will be shown below. Save these keys for later 😉

The Go Part

As usual, if you just want to see the code, it’s all over on Github.

Now that we have our keys, we can use them to make requests to the dploy.ai API from anywhere we want. In the high-level overview our program exists out of three steps:

  1. Read an image from the program arguments
  2. Pass this image as b64 to the app.dploy.ai API
  3. Write the returned image to disk

Let’s start by setting up our constants in Go, which we will need for making our HTTP requests:

const(
// paste your api key and user token here
key = "your-key-here"
user = "your-user-token-here"
url = "https://3345423f-8bbf-4215-8004-215a3da67b60.users.dploy.ai/"
)

Next, we need to load an image. We’ll just assume the image is passed as the first argument to the command line (e.g: go run main.go image.jpg). The API will need to know what type of image we are using, so we’ll also extract the filetype when reading the filename, and return this together as a Payload for the API.

type Payload struct {
Image string `json:"image"`
Type string `json:"type"`
}

func loadImage() (Payload, error) {
file := os.Args[1]
bs, err := ioutil.ReadFile(file)
if err != nil {
return Payload{}, err
}
return Payload{
Image: base64.StdEncoding.EncodeToString(bs),
Type: strings.Split(file, ".")[1],
}, nil
}

As good Gophers, we’ll return errors along the way. We’ll panic in our main function though. 🙊

Now that we can extract a Payload from the command line, we’ll need to construct a request. Again, quite simple with Go, all the tools are build-in to do this. Our request will need to know our api key and api user as x-api-key and x-api-user respectively, hence make sure they are set!

func main() {
payload, err := loadImage()
if err != nil {
panic(err)
}
c := http.Client{}

data, err := json.Marshal(payload)
if err != nil {
panic(err)
}
req, err := http.NewRequest("POST", url, strings.NewReader(string(data)))
// set our API keys
req.Header.Set("x-api-key", key)
req.Header.Set("x-api-user", user)
req.Header.Set("content-type", "application/json")
resp, err := c.Do(req)
defer resp.Body.Close()

If all went well up until this point, we have send a request to the API. Ideally, you should want to do something with the output. The model returns multiple values, such as an array of detected faces, associated confidences an annotated image. We’ll just extract the annotated image so we have something a bit more visual.

ResponseBody := struct {
AnnotatedImage string `json:"annotated_image"`
}{}
err := json.NewDecoder(resp.Body).Decode(&ResponseBody)
if err != nil {
panic(err)
}
WriteResponse(ResponseBody.AnnotatedImage, fmt.Sprintf("output.%s", payload.Type))

All that is left is to implement the “WriteResponse” code, where we turn a base64 encoded image into an actual image, and write it to disk as output.filetype

// save the response as an image
func WriteResponse(image, outputfile string) error {
bs, err := base64.StdEncoding.DecodeString(image)
if err != nil {
return err
}
ioutil.WriteFile(outputfile, bs, 0644)
return nil
}

The result

Now when you run this program with go run main.go selfie.jpeg it writes a new file output.jpeg to my desk, returning an image like the following:

Yup, definitely wearing a face mask! 😷

If you liked this post and 💙 Go as well, consider:

  • Following me here, on Medium
  • Or twitter Twitter

--

--