Deploying a Flask application to the cloud

If you have developed a Flask application you can run in your computer, you can easily make it public by deploying it to the cloud. There are a lot of options if you want to deploy your application to the cloud (for example, Google App Engine: https://cloud.google.com/appengine/, Microsoft Azure: https://azure.microsoft.com, Heroku: https://devcenter.heroku.com/, and Amazon Web Services: https://aws.amazon.com, among others). Additionally, you can also use PythonAnywhere (www.pythonanywhere.com), which is a Python online integrated development environment (IDE) and web hosting environment, making it easy to create and run Python programs in the cloud.

PythonAnywhere is very simple, and also the recommended way of hosting machine learning-based web applications. PythonAnywhere provides some interesting features, such as WSGI-based web hosting (for example, Django, Flask, and Web2py).

In this section, we will see how to create a Flask application and how to deploy it on PythonAnywhere.

To show you how to deploy a Flask application to the cloud using PythonAnywhere, we are going to use the code of the mysite project. This code is very similar (with minor modifications) to the minimal face API we have previously seen in this chapter. These modifications will be explained after creating the site:

  1. The first step is to create a PythonAnywhere account. For this example, a beginner account is enough (https://www.pythonanywhere.com/pricing/):

  1. After registering, you will have access to your dashboard. This can be seen in the next screenshot:

As you can see, I have created the user opencv

  1. The next step is to click on Web menu and then, click the Add new web app button, as shown in the next screenshot:

  1. At this point, you are ready to create the new web app, as shown in the next screenshot:

  1. Click Next and then, click Flask and also, click on the latest version of Python. Finally, click Next to accept the project path:

This will create a Hello world Flask application that you can see if you visit https://your_user_name.pythonanywhere.com. In my case, the URL will be https://opencv.pythonanywhere.com.

  1. At this point, we are ready to upload our own project. The first step is to click on Go to directory in the Code section of the Web menu, as shown in the next screenshot:

  1. We can upload files to our site using the Upload a file button. We have uploaded three files, as follows:
    • flask_app.py
    • face_processing.py
    • haarcascade_frontalface_alt.xml

This can be seen in the next screenshot:

You can see the uploaded content of these files by clicking the download icon. In this case, you can see the content of these files in the following URLs:

  1. Next step is to set up the virtual environment. To accomplish this, a bash console should be opened by clicking on Open Bash console here (see the previous screenshot). Once it's opened, run the following command:
$ mkvirtualenv --python=/usr/bin/python3.6 my-virtualenv

You will see the prompt changes from $ to (my-virtualenv)$. This means that the virtual environment has been activated. At this point, we will install all the required packages (flask and opencv-contrib-python):

(my-virtualenv)$ pip install flask

(my-virtualenv)$ pip install opencv-contrib-python

You can see that numpy is also installed. All these steps can be seen in the next screenshot:

If you want to install additional packages, do not forget to activate the virtual environment you have created. You can reactivate it with the following command:

$ workon my-virtualenv
(my-virtualenv)$
  1. At this point, we have almost finished. The final step is to reload the uploaded project by clicking on the Web option in the menu and reloading the site, which can be seen in the next screenshot:

Hence, we are ready to test the face API uploaded to PythonAnywhere, which can be accessed using https://opencv.pythonanywhere.com/. You will see something like the following screenshot:

You can see a JSON response. This JSON response is obtained because we have used the route() decorator to bind the info_view() function to the URL /. This is one of the modifications we have performed in this example in comparison with the minimal face API we have seen in this chapter. Therefore, we have modified the flask_app.py script to include:

@app.route('/', methods=["GET"])
def info_view():
# List of routes for this API:
output = {
'info': 'GET /',
'detect faces via POST': 'POST /detect',
'detect faces via GET': 'GET /detect',
}
return jsonify(output), 200

This way, when accessing https://opencv.pythonanywhere.com/, we will get the list of routes for this API. This is helpful when uploading a project to PythonAnywhere in order to see that everything is working fine. The second (and final) modification is performed in the face_processing.py script. In this script, we have changed the path of the haarcascade_frontalface_alt.xml file, which is used by the face detector:

class FaceProcessing(object):
def __init__(self):
self.file = "/home/opencv/mysite/haarcascade_frontalface_alt.xml"
self.face_cascade = cv2.CascadeClassifier(self.file)

See the path of the file, which matches with the new path assigned when uploading the haarcascade_frontalface_alt.xml file to PythonAnywhere.

This path should be changed according to the username (opencv in this case).

In the same way as we did in previous examples, we can perform a POST request to the face API uploaded to PythonAnywhere. This is performed in the demo_request.py script:

# Import required packages:
import cv2
import numpy as np
import requests
from matplotlib import pyplot as plt


def show_img_with_matplotlib(color_img, title, pos):
"""Shows an image using matplotlib capabilities"""

img_RGB = color_img[:, :, ::-1]

ax = plt.subplot(1, 1, pos)
plt.imshow(img_RGB)
plt.title(title)
plt.axis('off')


FACE_DETECTION_REST_API_URL = "http://opencv.pythonanywhere.com/detect"
IMAGE_PATH = "test_face_processing.jpg"

# Load the image and construct the payload:
image = open(IMAGE_PATH, "rb").read()
payload = {"image": image}

# Submit the POST request:
r = requests.post(FACE_DETECTION_REST_API_URL, files=payload)

# See the response:
print("status code: {}".format(r.status_code))
print("headers: {}".format(r.headers))
print("content: {}".format(r.json()))

# Get JSON data from the response and get 'result':
json_data = r.json()
result = json_data['result']

# Convert the loaded image to the OpenCV format:
image_array = np.asarray(bytearray(image), dtype=np.uint8)
img_opencv = cv2.imdecode(image_array, -1)

# Draw faces in the OpenCV image:
for face in result:
left, top, right, bottom = face['box']
# To draw a rectangle, you need top-left corner and bottom-right corner of rectangle:
cv2.rectangle(img_opencv, (left, top), (right, bottom), (0, 255, 255), 2)
# Draw top-left corner and bottom-right corner (checking):
cv2.circle(img_opencv, (left, top), 5, (0, 0, 255), -1)
cv2.circle(img_opencv, (right, bottom), 5, (255, 0, 0), -1)

# Create the dimensions of the figure and set title:
fig = plt.figure(figsize=(8, 6))
plt.suptitle("Using face API", fontsize=14, fontweight='bold')
fig.patch.set_facecolor('silver')

# Show the output image
show_img_with_matplotlib(img_opencv, "face detection", 1)

# Show the Figure:
plt.show()

There is nothing new in this script, with the exception of the following line:

FACE_DETECTION_REST_API_URL = "http://opencv.pythonanywhere.com/detect"

Note that we are requesting our cloud API. The output of this script can be seen in the next screenshot:

This way we can confirm that our cloud API is up and running.