Search code examples
pythonplotlydashboardplotly-dashimage-classification

Using Dash to process an image/images and running it through a trained and saved image classification model and display results in the Dashboard


I have a Dash script so far to Drag and Drop an image on the Dashboard. I have created functions to load and preprocess the image, and turn to numpy array and running it through my saved image classification model to predict. Appreciate any help!

When I load an image, it gives an error 'OSError: [Errno 36] File name too long:....' I believe the 'contents' of the dash html base64 encodes, so might need to decode? But I am not sure or how.

import io
import dash
import time
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import base64
import tensorflow as tf
from matplotlib import image

from glob import glob
import os
import numpy as np
from PIL import Image
import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow import keras
from matplotlib import pyplot
import time


model = keras.models.load_model(filename)

app = dash.Dash(__name__)

app.layout = html.Div([
    dcc.Upload(
        id='upload-image',
        children=html.Div([
            'Drag and Drop or ',
            html.A('Select Files')
        ]),
        style={
            'width': '100%',
            'height': '60px',
            'lineHeight': '60px',
            'borderWidth': '1px',
            'borderStyle': 'dashed',
            'borderRadius': '5px',
            'textAlign': 'center',
            'margin': '10px'
        },
        # Allow multiple files to be uploaded
        multiple=True
    ),
    html.Div(id='output-image-upload'),
])

def load_and_preprocess(image):
   image1 = Image.open(image)
   rgb =  Image.new('RGB', image1.size)
   rgb.paste(image1)
   image = rgb
   test_image = image.resize((256,256))
   return test_image

def np_array_normalise(test_image):
   np_image = np.array(test_image)
   np_image = np_image / no_of_pixels
   final_image = np.expand_dims(np_image, 0)
   return final_image

@app.callback(Output('output-prediction', 'children'),
              Input('upload-image', 'contents'))

def prediction(image):
    final_img = load_and_preprocess(image)
    final_img = np_array_normalise(final_img)
    Y = model.predict(final_img)
    return Y

if __name__ == '__main__':
    app.run_server(debug=True)

Can I please get help on how to fix this?

Callback error after uploading image


Solution

  • I think I figured it out! Instead of trying to decode the 'contents', I found a much simpler solution after reading around. HTML dash component also has 'filename'..

    import io
    import dash
    import time
    from dash.dependencies import Input, Output, State
    import dash_core_components as dcc
    import dash_html_components as html
    import base64
    import tensorflow as tf
    from matplotlib import image
    
    from glob import glob
    import os
    import numpy as np
    from PIL import Image
    import tensorflow as tf
    from tensorflow.keras.preprocessing.image import ImageDataGenerator
    from tensorflow import keras
    from matplotlib import pyplot
    import time
    
    
    model = keras.models.load_model(filename)
    
    app = dash.Dash(__name__)
    
    app.layout = html.Div([
        dcc.Upload(
            id='upload-image',
            children=html.Div([
                'Drag and Drop or ',
                html.A('Select Files')
            ]),
            style={
                'width': '100%',
                'height': '60px',
                'lineHeight': '60px',
                'borderWidth': '1px',
                'borderStyle': 'dashed',
                'borderRadius': '5px',
                'textAlign': 'center',
                'margin': '10px'
            },
            # Allow multiple files to be uploaded
            multiple=True
        ),
        html.Div(id='output-image-upload'),
    ])
    
    def load_and_preprocess(image):
       image1 = Image.open(image)
       rgb =  Image.new('RGB', image1.size)
       rgb.paste(image1)
       image = rgb
       test_image = image.resize((256,256))
       return test_image
    
    def np_array_normalise(test_image):
       np_image = np.array(test_image)
       np_image = np_image / no_of_pixels
       final_image = np.expand_dims(np_image, 0)
       return final_image
    
    @app.callback(Output('output-prediction', 'children'),
                  Input('upload-image', 'filename'))
    
    def prediction(image):
        if image is None:
            raise dash.exceptios.PreventUpdate()
        final_img = load_and_preprocess(image)
        final_img = np_array_normalise(final_img)
        Y = model.predict(final_img)
        return Y
    
    if __name__ == '__main__':
        app.run_server(debug=True)