Thiresh's picture
Upload folder using huggingface_hub
d6c875b verified
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"
)