An image classification app in Android using Keras and Tensorflow

Vishnu Sivan
Coinmonks
16 min readSep 18, 2022

--

Image classification is the process of categorizing and labeling images based on specific rules. It can be beneficial for object identification in satellite images, brake light detection, traffic control systems etc.

To create an image classification app for Android using the Tensorflow lite plugin follow the below link.

These apps are useful for performing image classification using the lightweight tflite models. Edge devices require more processing when the model size increases. TFLite android package supports only tflite models. Edge devices may not be a great option for creating / training / running models whose size is large. To overcome the limitation, use the Flask server-based model deployment.

In this session, we will create a Keras model and deploy it on the Flask server. We can use flask APIs to access the model in the android app. Also, we will host the flask server on the Heroku cloud.

Getting Started

In this session, we will create an android application that classifies handwritten digits from the input image. To reduce the efforts for data collection and cleaning, we will be using the MNIST dataset for the application.

We have divided this tutorial into three parts,

  1. Creation and deployment of Keras image classification model
  2. Create an android application for image classification
  3. Flask server deployment on Heroku

Part 1: Creation and deployment of Keras image classification model

In this section, we will create a multilayer perceptron (MLP) model using Keras, which is trained on the MNIST dataset.

Table of Contents

Install the dependencies

It is advised to install the dependencies on a virtual environment instead of installing them globally.

  • Create a virtual environment using the following command
  • Switch to the virtual environment in Windows
  • Install the dependencies using the following command,

Prepare the MNIST Dataset

The MNIST dataset is a handwritten digit recognition dataset for digits 0 to 9. It has 70,000 images — 60,000 samples for training, and 10,000 for testing. Every single image is a gray image of size 28x28. Samples from the dataset are shown below.

Import the mnist dataset to the project using the following code,

Keras module allows us to download certain datasets automatically. We can download the dataset from Keras module using keras.datasets. Import keras.datasets.mnist to the code for performing various operations on the mnist dataset. Use the load_data() function to load the dataset in the project. This function returns a tuple of 2 elements as follows:

  • (x_train, y_train) — Training inputs & labels.
  • (x_test, y_test) — Test inputs & labels.

We can determine the size of the dataset using the shape element of the array. The shape of the training inputs array (x_train) is (60000, 28, 28), which means there are 60,000 samples and the size of each sample image is 28x28.

We will be building an MLP model which accepts a vector and not an array as an input. We require to convert each array into a vector. It can be done using the reshape() function. Use the following code to reshape the input array.

The data type of the images is uint8 where each pixel ranges from 0 to 255. Rescaling is useful to reduce the gradients in the backpropagation phase.

As per the shape of the train and test labels, there’s a single value assigned for each sample. There are 10 classes in the MNIST dataset where each sample must be assigned a binary vector of length 10. The index of the element corresponds to the class label.

For example, if a sample has a class label 2, create a vector of 10 elements where all elements are zeros except for the element at index 2 which is 1,

To do the conversion, use the keras.utils.to_categorical() function.

The complete code for data preparation is given below,

Build the MLP model

Declare the MLP model as a sequential model using the keras.models.Sequential() function.

The sequential model contains 3 dense and 2 dropout layers. The first dense layer accepts a vector image of shape 784 which contains 512 neurons. The last dense layer uses the softmax function with 10 neurons, which returns the probability of each class.

After building the model, print a summary of the model using the model.summary() function. It lists Layer, Output Shape and Params.

The Param column gives the total number of parameters of the layer, as the product of the number of inputs (784) and the number of neurons in the layer (512) which results in 784 * 512 = 401,408. Some neurons tend to have bias, so additional 512 parameters are added to the total which results in 401,920.

Define the loss function, optimizer, and metrics for training the model using the compile() function. Set loss function as categorical_crossentropy, optimizer as Root Mean Square Propagation (RMSprop) and metric as classification accuracy.

Train the MLP model

Train the model using the fit() function as given below.

It accepts the training inputs (x_train), training labels (y_train), batch size (128), and number of epochs (20). The verbose=1 is added to the input to print messages while the model is being trained, and the validation data.

The evaluate() function is used to evaluate the model with respect to the validation data as follows.

Save the Model

Use the model.save() function to save the model for future reference.

The complete code to prepare the data, build, train, and save the model is given below.

NB: If you are running the code from the git repo provided in this tutorial then try to install dependencies from the requirements.txt file using pip install -r requirements.txt command.

Make predictions using the saved model

Load the model using the keras.models.load_model() function and predict the classes using the predict_classes() function.

Create a Flask API for image classification

Flask is a lightweight web framework written in Python.

Create a file named server.py and add the following code to it to return “Hello World” text when hitting the server.

The app.route() decorator function associates a URL with a callback function. In this example, the function is named welcome() which returns the “Hello World” text when the user hits the default route (“/”). We set the host set to “0.0.0.0” and port to 5000.

Let’s try to create a route “/predict” to predict the class based on the input image. For which, create a file named server.py and add the following code to it.

Let’s understand the code,

  • imageio.imread reads an image as grayscale and reshapes it into (28, 28).
  • Load the pre trained model using models.load_model(‘model.h5’)
  • Use the loaded_model.predict() function to predict the class label using the Keras pre-trained model, and return the classification label as a string.

Start the server by running the following command from the FlaskServer/app folder.

NB: If you are running the code from the git repo provided in this tutorial then try to install dependencies from the requirements.txt file using pip install -r requirements.txt command.

Part 2: Create an android application for image classification

Now, we can create a client-side android application that uploads an image to the flask server which we created in the previous step. The app has an option to select the image from the gallery. The selected image is converted into a byte array which is sent to the Flask server. We can handle the HTTP requests and responses using OkHttp.

Table of contents

Create the app

Open android studio and Click on New project button and provide the necessary information.

Design the layout

Define a basic layout with editText, buttons, imageViews and textViews. It contains 3 buttons — Capture Image, Select Image and Predict class and editText — for inputting server URL (IP address and port).

Add the following code to activity_main.xml to define the layout.

The resultant layout is as shown below,

Communicate to the flask server

  • Add the following line to the dependencies section of the apps build.gradle and sync your project.
  • Add the following code to the AndroidManifest.xml file to request camera, internet and storage permissions in the app.
  • Request permissions on the activity initialization.
  • Create a method, captureImage in MainActivity.java to capture an image from the camera. Create a URI of the captured image and assign it to the imageView. Create a byteArray of the image and add it to the OkHttp request body.
  • Create a method, selectImage to browse images from the gallery. Create a URI of the selected image and assigned it to the imageView. Create a byteArray of the image and add it to the OkHttp request body.
  • Create a method, getImageUri to get the image path from the Bitmap image data.
  • Create a method, getFileName to get the file name from Uri.
  • Create a method, postRequest which accepts postUrl and postBody. The method sends the image to the server and receives the response in the app. Set the result on the responseText.
  • The request is created using the Request.Builder class. This class is responsible for mapping the destination URL with the request body. The url() method accepts the URL and the post() method accepts the request body. Finally, the request is built using the build() method.
  • Send the request via the instance of the OkHttpClient using a method called newCall(). There are 2 callback methods based on the state of the call:
  • onFailure(): Called when the request couldn’t be executed due to cancellation, a connectivity problem, or a timeout.
  • onResponse(): Called when the HTTP response is successfully returned by the remote server.
  • Create a method, connectServer to get the image information from the file system and to send requests to the server.
  • The full code of the MainActivity is given below,

Test the app

Connect your device to the machine. Click on the Play button ▶ to run the app.

You can either use the local machine flask server address (if both mobile and the machine are connected to the same network) or the remote address (https://androidflaskdemo.herokuapp.com/) as the server URL.

Part 3: Flask server deployment on Heroku

Heroku is a container based cloud platform as a service (PaaS) which is used for deploying your applications on the web. It received interest in recent years due to its simple setup and budget friendly pricing.

Create a Heroku account if you don’t have one already. Login to your account and create a project by clicking on the Create new app button. You can choose any app name (Eg: androidflaskdemo).

Even though Heroku provides instructions to deploy your app in Heroku, you have to include some necessary configuration files into the project to identify the platform, build tools and all.

The flask app deployment requires three files in your project root folder.

  1. Procfile
  2. requirements.txt
  3. runtime.txt
  • Open the terminal in the project root folder and run the following commands to create Procfile and runtime.txt files.
  • Create the requirements.txt file using pip freeze from the virtual environment.

Now we can move to the deployment process.

  • Download and install Heroku CLI into your machine.
  • Log in to the Heroku account in the terminal by executing the following command:
  • Execute the commands that are provided in the deploy tab in the Heroku website.

We have successfully deployed our Flask server on Heroku. You can use the local flask server or https://androidflaskdemo.herokuapp.com/ links to run the classification in the mobile app.

Thanks for reading this article.

Thanks Gowri M Bhatt for reviewing the content.

If you enjoyed this article, please click on the clap button 👏 and share to help others find it!

The article is also available on Dev.

The full source code for this tutorial can be found here,

New to trading? Try crypto trading bots or copy trading

--

--

Vishnu Sivan
Coinmonks

Try not to become a man of SUCCESS but rather try to become a man of VALUE