Flask WebAPI with absl-py flags for an image based input-output model

Anuj Arora
Mar 4 · 2 min read

Recently, while implementing my Deep Neural Network (DNN) model into a WebAPI I faced multiple issues,

  1. my usage of absl-flags for command line arguments somehow clashed with the flask’s run command.
  2. in receiving image file back as an output from the server side, i received the following errors,

AttributeError: 'Image' object has no attribute 'read'
AttributeError: 'numpy.ndarray' object has no attribute 'read

I could have switched from using absl-py to some other module (for example, argparse) to set the default values for my command line arguments (unsure if this would have worked, since I did not test) but that would have required me to make changes all throughout my code. So, it is obvious why I was not in favor of doing that. Below I share the solution that helped me overcome these issues and finally helped me realize a working Flask WebAPI that takes in and returns an image file.

First the customary

# Import the necessary modules
import os
import sys
import iofrom absl import flags
from flask import Flask, request, send_file
from PIL import Image
# Define the flags
flags.DEFINE_enum(...)
flags.DEFINE_integer(...)
flags.DEFINE_boolean(...)
flags.DEFINE_string(...)

Up until this point, everything is as if you’d write a python code to be executed on your local machine. Below are the extra things, that need to be included to make absl-flags and flask app run smoothly together.

Include extra flags for the flask app

flags.DEFINE_string("host", None, "flag for host IP address")
flags.DEFINE_string("port", None, "flag for the port number")

without the above, we have the following error

absl.flags._exceptions.UnrecognizedFlagError: Unknown command line flag 'host'

Get the values for the FLAGs

The most important bit for obtaining the flag values, suggested here.

FLAGS(sys.argv)

Continue the way you’d normally do with a Flask API

# Preparing the model
model = Model(MODEL_DIR)
# create the Flask instance
flask_app = Flask(__name__)
# define the desired functionality@flask_app.route("/infer", methods=["POST"])def infer():
# Retrieving the image
img = Image.open(request.files["file"]).convert("RGB")

# run the model on the image
output = model.single_inference(img)

# Convert to image object
img_out = Image.fromarray(output)

Convert the image object to byte array

The only way I could figure out to receive an image file back from the server.

def infer():
...
# Convert the image to byte array
img_byte_arr = io.BytesIO()
img_out.save(img_byte_arr, format="PNG")

# move to beginning of file for `send_file()` to read from
start
img_byte_arr.seek(0)
return send_file(img_byte_arr, mimetype="image/PNG")

After finishing with all the above preparations, you can finally set up your API, with the following command line input (provided API is defined in app.py in the working directory).

python -m flask run --host=*.*.*.* --port=5000

To send a request to the server, enter the following command.

curl -X POST -H "Content-Type: multipart/form-data" http://*.*.*.*:5000/infer -F "file=@Data/input.png" > output.png

Note: Do not forget @ mark above

In this article, I share my solution to the issues I faced with implementing a Flask WebAPI for image based input/output, absl-flags for command line arguments. If you have a better solution or are facing some other hindrance, please do share.

Dive into ML/AI

Help people jump-start their ML journey

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store