File size: 3,125 Bytes
684ddef
 
 
 
a199367
684ddef
 
 
 
 
 
 
 
 
 
 
a199367
684ddef
f42812b
 
 
a199367
f42812b
a199367
f42812b
a199367
 
f42812b
 
a199367
 
 
f42812b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a199367
 
f42812b
a199367
 
 
 
 
 
 
 
 
 
f42812b
a199367
 
f42812b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import streamlit as st
import tensorflow as tf
import numpy as np
from PIL import Image
import os

# ================== SETTINGS ==================
IMG_SIZE = (170, 170)  # same as target_size in your ImageDataGenerator

CLASS_NAMES = [
    "Black Rot",
    "ESCA",
    "Healthy",
    "Leaf Blight",
]

TFLITE_MODEL_FILENAME = "grape_disease_model.tflite"  # new TFLite model
# =============================================


@st.cache_resource
def load_interpreter():
    """
    Load the TFLite model once and cache the interpreter.
    """
    if not os.path.exists(TFLITE_MODEL_FILENAME):
        st.error(f"Model file '{TFLITE_MODEL_FILENAME}' not found in this directory.")
        st.stop()

    interpreter = tf.lite.Interpreter(model_path=TFLITE_MODEL_FILENAME)
    interpreter.allocate_tensors()
    return interpreter


def preprocess_image(img: Image.Image) -> np.ndarray:
    """
    - Resize to IMG_SIZE
    - Convert to numpy array
    - Normalize (same as rescale=1./255 in your ImageDataGenerator)
    - Add batch dimension
    """
    img = img.resize(IMG_SIZE)
    img_array = np.array(img)

    # same normalization as during training
    img_array = img_array.astype("float32") / 255.0

    # (H, W, 3) -> (1, H, W, 3)
    img_array = np.expand_dims(img_array, axis=0)
    return img_array


def predict_image(img: Image.Image):
    """
    Run inference using the TFLite interpreter.
    Returns (predicted_label, confidence, all_probabilities).
    """
    interpreter = load_interpreter()

    input_details = interpreter.get_input_details()
    output_details = interpreter.get_output_details()

    x = preprocess_image(img).astype(np.float32)

    # feed input
    interpreter.set_tensor(input_details[0]['index'], x)
    interpreter.invoke()

    # get output
    preds = interpreter.get_tensor(output_details[0]['index'])

    probs = preds[0]
    idx = int(np.argmax(probs))
    label = CLASS_NAMES[idx]
    confidence = float(probs[idx])
    return label, confidence, probs


# ================ STREAMLIT UI =================
st.set_page_config(
    page_title="Grape Disease Classifier",
    layout="centered"
)

st.title("🍇 Grape Disease Classifier")
st.write("App loaded. Upload an image to get a prediction.")

st.write(
    "Upload a photo of a grape leaf. "
    "The model predicts whether the leaf is **Black Rot**, **ESCA**, **Healthy**, "
    "or **Leaf Blight**."
)

uploaded_file = st.file_uploader(
    "Upload an image (.jpg, .jpeg or .png)",
    type=["jpg", "jpeg", "png"]
)

if uploaded_file is not None:
    image = Image.open(uploaded_file).convert("RGB")
    st.image(image, caption="Uploaded image", use_column_width=True)

    if st.button("Predict"):
        with st.spinner("Running prediction..."):
            label, confidence, probs = predict_image(image)

        st.subheader(f"Prediction: **{label}**")
        st.write(f"Confidence: **{confidence:.2%}**")

        st.write("Class probabilities:")
        for name, p in zip(CLASS_NAMES, probs):
            st.write(f"- {name}: {float(p):.2%}")
else:
    st.info("Upload an image above to get a prediction.")