File size: 3,866 Bytes
e951894
 
 
 
 
 
 
 
 
 
 
 
 
 
d6c875b
 
e951894
d6c875b
 
 
 
 
 
e951894
d6c875b
e951894
d6c875b
e951894
d6c875b
 
 
e951894
d6c875b
 
 
 
 
 
 
e951894
d6c875b
 
 
 
e951894
 
 
d6c875b
e951894
 
d6c875b
e951894
 
 
 
 
 
 
d6c875b
e951894
 
 
 
d6c875b
 
 
 
 
e951894
 
 
d6c875b
 
e951894
d6c875b
e951894
 
 
 
 
 
 
 
d6c875b
 
e951894
d6c875b
e951894
d6c875b
e951894
d6c875b
 
e951894
d6c875b
e951894
d6c875b
e951894
 
 
 
 
 
d6c875b
 
e951894
 
 
d6c875b
e951894
d6c875b
e951894
d6c875b
e951894
 
 
 
 
 
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
116
117
118
119

import streamlit as st
import tensorflow as tf
from PIL import Image
import numpy as np
import json
import os
import pandas as pd

st.set_page_config(page_title="Food Image Classification", layout="centered")

@st.cache_resource
def load_model_and_metadata():
    """
    Load the saved Keras model (best_model.keras) and metadata.json
    from the current directory.
    """
    cwd = os.getcwd()
    # 1. Load model file
    model_file = os.path.join(cwd, "best_model.keras")
    if not os.path.exists(model_file):
        st.error(f"Model file not found at '{model_file}'. Ensure best_model.keras is present.")
        return None, None, None, None
    try:
        model = tf.keras.models.load_model(model_file)
    except Exception as e:
        st.error(f"Failed to load model from {model_file}: {e}")
        return None, None, None, None

    # 2. Load metadata.json at root
    meta_path = os.path.join(cwd, "metadata.json")
    if not os.path.exists(meta_path):
        st.error(f"metadata.json not found at '{meta_path}'.")
        return model, None, None, None
    try:
        with open(meta_path, "r") as f:
            metadata = json.load(f)
    except Exception as e:
        st.error(f"Failed to read metadata.json: {e}")
        return model, None, None, None

    class_names = metadata.get("class_names")
    IMG_HEIGHT = metadata.get("IMG_HEIGHT")
    IMG_WIDTH = metadata.get("IMG_WIDTH")
    if class_names is None or IMG_HEIGHT is None or IMG_WIDTH is None:
        st.error("metadata.json must contain 'class_names', 'IMG_HEIGHT', and 'IMG_WIDTH'")
        return model, None, None, None

    return model, class_names, IMG_HEIGHT, IMG_WIDTH


model, class_names, IMG_HEIGHT, IMG_WIDTH = load_model_and_metadata()
if model is None or class_names is None:
    st.stop()



st.title("Food Image Classification")
st.write("Upload a food image (Bread / Soup / Vegetable-Fruit) to classify.")

with st.sidebar:
    st.header("Instructions")
    st.write(
        f"""
        - Upload a JPG/PNG image of food.
        - The model expects images resized to {IMG_HEIGHT}×{IMG_WIDTH}.
        - The model classes: {', '.join(class_names)}.
        - For best results, upload a clear image of a single food item.
        """
    )


st.subheader("Image Prediction")
uploaded_file = st.file_uploader("Choose an image...", type=["jpg","jpeg","png"], key="single")

if uploaded_file is not None:
    try:
        image = Image.open(uploaded_file).convert("RGB")
    except Exception as e:
        st.error(f"Cannot open image: {e}")
        image = None
    if image:
        st.image(image, caption="Uploaded Image", use_column_width=True)

        # Preprocess: resize and scale to [0,1]
        img_resized = image.resize((IMG_WIDTH, IMG_HEIGHT))
        img_array = np.array(img_resized).astype("float32") / 255.0
        input_tensor = np.expand_dims(img_array, axis=0)  # shape (1, H, W, 3)

        # Predict
        preds = model.predict(input_tensor, verbose=0)
        pred_idx = int(np.argmax(preds[0]))
        pred_class = class_names[pred_idx]
        confidence = float(preds[0][pred_idx])
        st.write(f"**Prediction:** {pred_class}  \n**Confidence:** {confidence:.3f}")

        # Show full probability distribution
        prob_df = pd.DataFrame({
            "class": class_names,
            "probability": preds[0]
        })
        st.bar_chart(data=prob_df.set_index("class"))

        # Download result as CSV
        result_df = pd.DataFrame([{
            "filename": uploaded_file.name,
            "predicted_class": pred_class,
            "confidence": confidence
        }])

        csv = result_df.to_csv(index=False).encode('utf-8')

        st.download_button(
            label="Download prediction as CSV",
            data=csv,
            file_name="prediction.csv",
            mime="text/csv"
        )