| | import streamlit as st |
| | import tensorflow as tf |
| | import numpy as np |
| | from PIL import Image |
| |
|
| | |
| | st.set_page_config(layout="wide") |
| |
|
| | |
| | @st.cache_resource |
| | def load_model(): |
| | return tf.keras.models.load_model('src/leaf_disease_model.h5') |
| |
|
| | model = load_model() |
| |
|
| | |
| | class_names = [ |
| | 'Tomato___Bacterial_spot', |
| | 'Tomato___Early_blight', |
| | 'Tomato___Late_blight', |
| | 'Tomato___Leaf_Mold', |
| | 'Tomato___Septoria_leaf_spot', |
| | 'Tomato___Spider_mites Two-spotted_spider_mite', |
| | 'Tomato___Target_Spot', |
| | 'Tomato___Tomato_Yellow_Leaf_Curl_Virus', |
| | 'Tomato___Tomato_mosaic_virus', |
| | 'Tomato___healthy' |
| | ] |
| |
|
| | |
| | display_names = { |
| | 'Tomato___Bacterial_spot': 'Bacterial Spot', |
| | 'Tomato___Early_blight': 'Early Blight', |
| | 'Tomato___Late_blight': 'Late Blight', |
| | 'Tomato___Leaf_Mold': 'Leaf Mold', |
| | 'Tomato___Septoria_leaf_spot': 'Septoria Leaf Spot', |
| | 'Tomato___Spider_mites Two-spotted_spider_mite': 'Spider Mites', |
| | 'Tomato___Target_Spot': 'Target Spot', |
| | 'Tomato___Tomato_Yellow_Leaf_Curl_Virus': 'Yellow Leaf Curl Virus', |
| | 'Tomato___Tomato_mosaic_virus': 'Mosaic Virus', |
| | 'Tomato___healthy': 'Healthy' |
| | } |
| |
|
| | st.title('π
Tomato Leaf Disease Classifier') |
| | st.markdown('Upload an image of a tomato leaf to detect diseases') |
| |
|
| | |
| | col1, col2 = st.columns([1.3, 1.3]) |
| |
|
| | with col1: |
| | st.markdown("### π Upload Image") |
| | uploaded_file = st.file_uploader('Choose an image...', type=['jpg', 'jpeg', 'png']) |
| | |
| | if uploaded_file is not None: |
| | image = Image.open(uploaded_file).convert('RGB') |
| | st.image(image, caption='Uploaded Image', use_container_width=True) |
| | st.write(f'**File name:** {uploaded_file.name}') |
| |
|
| | with col2: |
| | st.markdown("### π Analysis Results") |
| | |
| | if uploaded_file is not None: |
| | |
| | img = image.resize((256, 256)) |
| | img_array = np.array(img) / 255.0 |
| | img_array = np.expand_dims(img_array, axis=0) |
| |
|
| | |
| | with st.spinner('Analyzing image...'): |
| | prediction = model.predict(img_array, verbose=0) |
| | |
| | predicted_class = np.argmax(prediction, axis=1)[0] |
| | predicted_class_name = class_names[predicted_class] |
| | confidence = prediction[0][predicted_class] * 100 |
| | |
| | |
| | st.metric( |
| | label="Predicted Disease", |
| | value=display_names[predicted_class_name], |
| | delta=f"{confidence:.1f}% confidence" |
| | ) |
| | |
| | |
| | status = "π’ Healthy" if "healthy" in predicted_class_name.lower() else "π΄ Diseased" |
| | st.metric(label="Status", value=status) |
| | |
| | |
| | st.markdown('#### Confidence Scores') |
| | |
| | |
| | predictions_with_names = [(class_names[i], prediction[0][i] * 100) for i in range(len(class_names))] |
| | predictions_with_names.sort(key=lambda x: x[1], reverse=True) |
| | |
| | |
| | for i, (class_name, conf) in enumerate(predictions_with_names[:5]): |
| | display_name = display_names[class_name] |
| | if i == 0: |
| | st.markdown(f"**π₯ {display_name}:** {conf:.1f}%") |
| | elif i == 1: |
| | st.markdown(f"π₯ {display_name}: {conf:.1f}%") |
| | elif i == 2: |
| | st.markdown(f"π₯ {display_name}: {conf:.1f}%") |
| | else: |
| | st.markdown(f"β’ {display_name}: {conf:.1f}%") |
| | |
| | |
| | with st.expander("View raw prediction data"): |
| | st.write("Raw prediction array:") |
| | st.write(prediction) |
| | st.write("Class indices and names:") |
| | for i, name in enumerate(class_names): |
| | st.write(f"{i}: {name}") |
| | else: |
| | st.info("π Please upload an image on the left to see analysis results here.") |
| |
|