Deploy Deep learning Models as Rest APIs using Keras and access from a Flutter App

Zakaria El bazi
Aug 29, 2019 · 4 min read

A Flutter app for garbage classification using Flutter, Flask and Keras

Lately machine learning and deep learning has become the most trendy and hot topics in IT world and every software product (web and mobile apps mainly) use somehow and somewhere Machine learning. In this article I will explain how I did to upload photos to server for image classification (garbage classification using a mobileNet v2 tuned model) using a Keras model deployed with Flask from Flutter mobile app camera.

Flask & Keras part:

It’s a python microframework for easy and quick web apps deployment, used for full stack development just like Django and many others. For our app we will be using it as backend of our REST API to run a keras model for image classification. The model is trained and saved as an .h5 file using Keras (a mobileNet V2 tunned model to classify garbage in a photo).

Defining a route in Flask is pretty simple , use the decorator @app.route(’/’) , where @app is the name of the object containing our Flask app.

from flask import Flask 
app = Flask(__name__)@app.route(’/’)
def hello_world():
return ‘Hello, World!’

Import Flask from flask and provide a name for app , here ‘app’ is name of object containing our app. Next, we will use the decorator to define route so that whenever a request comes to that route(Eg: flask will automatically return Hello, World !

For our app ,we will define a route @app.route(’/classifier/run’), to call our model as shown in the code bellow :

def classify():
app.logger.debug('Running classifier')
upload = request.files['data']
#load_image() is to process image :
image = load_image(upload)
print('image ready')
prediction = run_model(image)[0]
return _json_parse({"prediction": prediction})
except FileNotFoundError as e:
return abort('Unable to locate image: %s.' % str(e), 503)
except Exception as e:
return abort('Unable to process image: %s.' % str(e), 500)

The above route accepts as POST request and checks for file then the image is passed in the data of the post request request.files[‘data’] and save it as upload to pass it to the load _image() to process it and then run the model with it.

The load_image() function to process (resize it to 224*224 and reshape it to 4 dim as keras requires for the input 1,224,224,3 ) the image :

def load_image(filename):
img = load_img(filename, target_size=(224, 224))
img = img_to_array(img)
img = img.reshape(1, 224, 224, 3)
img = img.astype('float32')
return img

The run_model() function to run the model and classify the image :

labels = ['cardboard', 'glass', 'metal', 'paper', 'plastic', 'trash']
def run_model(img):
app.logger.error('Loading model')
try :
model = load_model('tf_model_tuned.h5')
except FileNotFoundError as e :
return abort('Unable to find the file: %s.' % str(e), 503)
pred = model.predict(img)
prediction = labels[np.argmax(pred)]
return prediction

the load_model() function in keras load the saved weights as h5 file . The function will raise an exception if the file not found or damaged. The .predict() keras function will run the model and give a 6 elements array where all the elements are equal to zero except the one that represents the predicted class.

PS : You did import all the necessary libs to run the flask and keras model correctly

from importlib import import_module
import os
import jsonpickle
from flask import Flask,Response , request , flash , url_for,jsonify
import logging
from logging.config
import dictConfig
import numpy as np
from PIL import Image
from keras.models import load_model
from keras.preprocessing.image import load_img, img_to_array

to test it , save your file as and execute it . The API by defaut will run on port 5000. Then use Postman or Postwoman or just a curl command on the terminal by typing :

$ curl -X POST http://localhost:5000/classifier/run -F "data=@[image_file_here]"

Flutter part :

The flutter part is the easiest one , I used a package named Dio to send the photos to the server and to fetch the response that contains the model’s inference results as shown bellow :

import 'dart:io';                       
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:async';
import 'dart:convert';
import 'package:path/path.dart';
import 'package:dio/dio.dart';
import 'package:async/async.dart';
// The API Endpoint here :
final String url_API = ""; //Post the image to the Object detection API for classification Future <Response> dio_upload(String imagePath) async {
Dio dio = new Dio();
FormData formdata = new FormData();
var _image = File(imagePath);
var uploadURL = url_API;
formdata.add("data", new UploadFileInfo(_image,basename(_image.path)));
var response =, data: formdata, options: Options(method: 'POST',responseType: ResponseType.plain));
return response;

The imagePath is the image taken by the mobile camera , it can also be a photo from your gallery (by using imagepicker package). Dio sends it to the server and get the response as json format or plain text format (like the case here in the example above : responseType: ResponseType.plain ).

child: FutureBuilder<Response>(                                   future: dio_upload(imagePath),                                   builder: (context, snapshot){                                     if (snapshot.hasData){
var result =;
return text(result) }

Then you can access the response from the server using a FutureBuilder and display it in the app .


It is through sharing knowledge,that our civilization come to be

Zakaria El bazi

Written by

#Z4ck404 | Cybersecurity and data science engineer @ExcelerateStystems .



It is through sharing knowledge,that our civilization come to be

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade