RuntimeError: Data adapters should be mutually exclusive for handling inputs in Streamlit only

Hi,

I have this code which works fine in my jupyter notebook.

def load_image(image):
    image = image.resize((224,224))
    img_array = np.array(image)/255 # a normalised 2D array                
    img_array = img_array.reshape(-1, 224, 224, 3)   # to shape as (1, 224, 224, 3)
    return img_array

im_path = 'C:\\Users\\..\\oneman\\image21.jpg'
img = load_image(Image.open(im_path))

model_cnn = load_model("C:/Users/.../Saved_models/cnn_model.h5")
model_cnn_ = tf.keras.models.Model(model_cnn.inputs, model_cnn.outputs)
pred_label = model_cnn_.predict(img)[0] 

if pred_label>0.5:
    print('Human is detected')
else:
    print("No human is detected: ")   

Output: 'Human is detected' (as expected)

However, when I try to implement the same in Streamlit with this code, I am getting an error.

import streamlit as st
import pandas as pd
import numpy as np
from PIL import Image 
import tensorflow as tf
from tensorflow.keras.models import load_model


st.title("Binary Human Detection Web App")
st.markdown("Is there a human in office space? 🧍")


# loading images
def load_image(image):

    image = image.resize((224,224))
    img_array = np.array(image)/255 # a normalised 2D array                
    img_array = img_array.reshape(-1, 224, 224, 3)   # to shape as (1, 224, 224, 3)
    return img_array


uploaded_file = st.sidebar.file_uploader(" ",type=['jpg', 'jpeg'])    

if uploaded_file is not None:
    
    u_img = load_image(Image.open(uploaded_file))
    img = st.image(u_img, 'Uploaded Image', use_column_width=True)

st.sidebar.write('\n')
    
if st.sidebar.button("Click Here to Predict"):
    
    if uploaded_file is None:
        
        st.sidebar.write("Please upload an Image to Classify")

    else:

        #with st.spinner('Classifying ...'):
        model_cnn = load_model("C:/Users/.../Saved_models/cnn_model.h5")
        model_cnn_ = tf.keras.models.Model(model_cnn.inputs, model_cnn.outputs)
        pred_label = model_cnn_.predict(img)[0] 


        st.sidebar.header("CNN results: ")    
        #st.write('Human is detected') if pred_label>0.5 else  st.write('No human is detected')    
        if pred_label>0.5:
            st.write('Human is detected')
        else:
            st.write('No human is detected')

the error is

Can you help me?

I have uploaded cnn_ltsm.h5, image20.jpg and image21.jpg to my github, if someone wants to reproduce my problem. GitHub - bluetail14/Thermal_data_images_project

I am running Streamlit via Anaconda in Google Chrome, Python 3.9.12 , keras 2.9.0, tensorflow 2.9.1, cudnn 8.1.0.77, cudatoolkit 11.2.2, streamlit 1.11.1, windows 64.

Thank you!

Sure! Two issues:

  1. You are passing the streamlit.image widget to the tensorflow model (which is not an image per se), not the PIL image.
  2. Once you open the image with PIL, you should close it after processing at some point! In a regular script this might (not always though) be done automagically when the script ends, but since streamlit kind of keeps the python script always running, opened elements would never get closed.

Demo:

detecthumantensorflow

Here is the code, hopefully it’s a little more readable:

import streamlit as st
import numpy as np
from PIL import Image 
import tensorflow as tf

st.title("Binary Human Detection Web App")
st.markdown("Is there a human in office space? 🧍")

## Initialize tensorflow model (This can be loaded before anything else)
path_to_model = "./cnn_model.h5"
model_loader = tf.keras.models.load_model(path_to_model)
model_cnn = tf.keras.models.Model(model_loader.inputs, model_loader.outputs)

## Preprocess images
def preprocessImage(photo):
    resize_photo = photo.resize((224,224))
    normalized_photo = np.array(resize_photo)/255 # a normalised 2D array                
    reshaped_photo = normalized_photo.reshape(-1, 224, 224, 3)   # to shape as (1, 224, 224, 3)
    return reshaped_photo

uploaded_file = st.sidebar.file_uploader(" ",type=['jpg', 'jpeg'])    

if uploaded_file is not None:
    ## Use a context manager to make sure to close the file!! 
    with Image.open(uploaded_file) as photo:
        tensorflow_image = preprocessImage(photo)
    
    ## Show preprocessed image
    streamlit_widget_image = st.image(tensorflow_image, 'Uploaded Image', use_column_width=True)

## Do prediction
if st.sidebar.button("Click Here to Predict"):
    
    if uploaded_file is None:
        st.sidebar.write("Please upload an Image to Classify")
    else:      
        ## Pass the preprocessed image to the cnn model (not the streamlit widget)
        pred_label = model_cnn.predict(tensorflow_image)[0]

        ## Print prediction
        st.sidebar.header("CNN results:") 
        if pred_label > 0.5: st.sidebar.info('Human is detected')
        else: st.sidebar.info('No human is detected')

PD. I got human detected in a nobody photo :ghost:

2 Likes

thank you so much :slight_smile: this was the image of the chair where a human has just sat, they’re thermal camera images.
yes, this cnn_ltsm_model is the worst performing with only 67% accuracy on the test set! my best ones are AlexNet and CNN with regularisation.

whats the command to close the file please? is it just tensorflow_image.close().

Closing the PIL image is an option indeed. Though, in general, it’s recommended to use context managers for that (aka the with statement, here is a nice in-depth explainer)

1 Like