Spaces:
Sleeping
Sleeping
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"
)
|