Build Face Recognition as a REST API | by Peter Xie | Towards Data Science

There are many open-source face recognition packages like face_recognition which you can easily install on Linux servers. But it is very difficult or impossible to deploy them on mobile and IoT devices. One option is to use machine learning mobile frameworks such as TensorFlow Lite to call pre-trained models.
But are there easier options? Yes! With 5G coming, it will take only 0.01 second to upload a 100KB image at a speed of about 100Mbps, so we can deploy almost everything including face recognition as a service on server-side and a light app on client-side. This post will demonstrate how to build a RESTful API for face_recognition on Linux servers using Python Flask.
face_recognition is an awesome open source project for face recognition based on dlib, just as described by itself:
The world’s simplest facial recognition api for Python and the command line
With a few lines of Python code, you can compare faces, detect faces and find facial features.
For example, run the sample find_facial_features_in_picture.py (only 40 lines of code) for an Obama image, you can get all facial features drawn as below.
To install it on Linux servers, you can follow the steps in the face_recognition project on Github, or just simply download the pre-configured VM. For Windows users, the steps provided by Sasiwut Chaiyadecha works for me.
Let’s define two APIs using the face_recognition package.
Compare two faces: Upload two images and return True / False for matching
Recognize a face from a known dataset: Upload an image and return the name of the person.
Two face recognition functions are defined for the two APIs as util in file face_util.py.
The first function compare_faces compares two image files and returns True if the faces in the two images are the same person.
The second function face_rec check if the face in the image file is a known face in the dataset, and return the name of the person. There are two known faces in this example.
With the above functions, we can easily define REST API with Flask as follows.
First API is face_match. It takes two image files from form data of a POST request, and calls compare_faces to check if they are a match, then returns a JSON format result.
The second API is face_rec, which takes one image file as input and calls face_rec to check if it is a known face, then returns the name of the person in JSON format.
You can download the full flask_server_v1.py file here.
Install Flask module by pip install -U flask, then run python flask_server_v1.py to start the server API. The start-up output looks like below.
* Serving Flask app "flask_server_v1" (lazy loading)... * Debug mode: on * Running on http://0.0.0.0:5001/ (Press CTRL+C to quit)
And you access these two API with below URL in POST form data format:
Compare two faces: http://<server IP address>: 5001/face_match
Recognize a face: http://<server IP address>: 5001/face_rec
You can call the API using any programming languages. I just take Python as an example. It requires requests module which you can install by pip install -U requests.
In the first example, we call face_match API with two images of the same person.
Run the example by python demo_client_part1.py and you will get a response as follows:
{"match": true}
In the second example, we call face_rec API to find the name of a person.
Run the script and you will get a response like below:
{"name": "Obama"}
If you’ve already known HTML form data, skip this section.
Form data is nothing but an HTML form that a user submits to the server-side. Check w3school for different HTML forms. For example, a simple input form looks like below.
When you click Submit, it actually sends an HTTP POST request to the webserver with data as follows:
In our case, we use a file form. To better understand it, let’s modify the face_rec API to return an HTML form page when user access the API by GET, i.e. typing the URL in a web browser, and print the request content when it is a POST.
First, we define a new function print_request() to print URL, key headers and body content for POST request. A trick is applied to substitute raw image data with string ‘<raw image data>’ so we can print the full POST request.
Then we modify face_rec API as follows:
Add GET support in methods. (Line 1)
If it is POST, print the request. (Line 3)
If it is GET, return an HTML file form page. (Line 12–20)
You can download the full flask_server_v2.py here.
Run the new server API python flask_server_v2.py , then open a web browser and type face_rec URL, e.g. http://127.0.0.1: 5001/face_rec.
You will see the above web page, click Browse to select an image file, then click Upload button. It will send a POST request with the selected file to server-side, i.e. calling the face_rec API. So you will get the API response on the browser.
In the meantime, POST request content will be printed on the server-side as follows.
Form data to transfer image data is effective because the data is transferred in raw binary directly. But if you want to transfer images in a JSON body format, base64 encoding is a popular solution that converts binary data into printable ASCII text string, but with a 33% overhead, i.e. (8–6)/6.
With Python base64 library, it is a piece of cake. Just call the b64encode and b64decode functions. But there is a trick that you need to convert the bytes string output of b64encode to normal string, e.g. b’abc’ to ‘abc’, before passing it to a JSON object because JSON does not support Python bytes string.
We can re-write the face_rec API client using JSON format as follows.
You can download the full client script v3 here.
And modify the server-side to support JSON format accordingly as follows.
We decode the base64 string back to binary data and save it as an image file, then call the same face_rec function that we used in the form data based API. Compare the post content length and you will see the 33% overhead as follows.
Peter2.jpg file size: 89KBPost form data content length: 91162Post base64 data content length: 121396(121396 - 91162) / 91162 = 33%
You can find the full server-side script v3 here.
You can add more features to the API, for instance, to return face locations and facial features so that you can implement the same things on mobile devices as you can do on Linux servers.
I’ve implemented a version of drawing face location and facial features using REST API with additional parameters and you can download the full repository here if interested.
Thanks for reading to this end.