Amaanali01 commited on
Commit
4e79e4b
ยท
verified ยท
1 Parent(s): b5fb899

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +317 -254
app.py CHANGED
@@ -1,364 +1,427 @@
 
 
 
 
 
1
  import streamlit as st
2
  import tensorflow as tf
3
  import numpy as np
4
  from PIL import Image
5
  import json
6
  import os
7
-
8
- # Define custom metrics (MUST be defined before loading model)
9
- def top_3_accuracy(y_true, y_pred):
10
- return tf.keras.metrics.top_k_categorical_accuracy(y_true, y_pred, k=3)
11
-
12
- def top_5_accuracy(y_true, y_pred):
13
- return tf.keras.metrics.top_k_categorical_accuracy(y_true, y_pred, k=5)
14
-
15
- # Register custom functions with Keras
16
- @tf.keras.utils.register_keras_serializable()
17
- def top_3_accuracy_serializable(y_true, y_pred):
18
- return tf.keras.metrics.top_k_categorical_accuracy(y_true, y_pred, k=3)
19
-
20
- @tf.keras.utils.register_keras_serializable()
21
- def top_5_accuracy_serializable(y_true, y_pred):
22
- return tf.keras.metrics.top_k_categorical_accuracy(y_true, y_pred, k=5)
23
-
24
- # Custom objects dictionary
25
- custom_objects = {
26
- 'top_3_accuracy': top_3_accuracy,
27
- 'top_5_accuracy': top_5_accuracy,
28
- 'top_3_accuracy_serializable': top_3_accuracy_serializable,
29
- 'top_5_accuracy_serializable': top_5_accuracy_serializable
30
- }
31
 
32
  # Page configuration
33
  st.set_page_config(
34
- page_title="Pakistan Food Classifier",
35
  page_icon="๐Ÿ›",
36
  layout="wide",
37
  initial_sidebar_state="expanded"
38
  )
39
 
40
- # Custom CSS for Pakistan theme
41
  st.markdown("""
42
- <style>
43
- .stApp {
44
- background-color: #f5f5f5;
 
45
  }
46
- .main-header {
47
- text-align: center;
 
 
48
  padding: 2rem;
49
- background: linear-gradient(135deg, #006400 0%, #ffffff 50%, #006400 100%);
50
- color: white;
51
- border-radius: 10px;
52
  margin-bottom: 2rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  }
 
 
54
  .prediction-card {
55
- background-color: white;
 
56
  padding: 1.5rem;
57
- border-radius: 10px;
58
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
59
  margin: 1rem 0;
 
 
60
  }
61
- .top1 {
 
 
 
 
 
 
 
62
  background: linear-gradient(135deg, #006400 0%, #008000 100%);
63
  color: white;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  padding: 1rem;
 
 
 
 
 
 
65
  border-radius: 10px;
66
- margin: 0.5rem 0;
67
  }
68
- .top2 {
69
- background-color: #e8f5e9;
70
- padding: 0.8rem;
71
- border-radius: 8px;
72
- margin: 0.5rem 0;
73
- border-left: 5px solid #006400;
 
 
 
 
74
  }
75
- .top3 {
76
- background-color: #f1f8e9;
77
- padding: 0.8rem;
78
- border-radius: 8px;
79
- margin: 0.5rem 0;
80
- border-left: 5px solid #8bc34a;
81
  }
82
- .pakistan-flag {
 
 
83
  text-align: center;
84
- font-size: 1.2rem;
 
 
 
 
 
 
 
 
 
 
 
85
  margin: 1rem 0;
86
  }
87
- </style>
 
 
 
 
 
 
 
 
88
  """, unsafe_allow_html=True)
89
 
90
- # Pakistan flag emoji in header
91
- st.markdown('<div class="pakistan-flag">๐Ÿ‡ต๐Ÿ‡ฐ Pakistan ๐Ÿ‡ต๐Ÿ‡ฐ</div>', unsafe_allow_html=True)
92
-
93
- # Paths for model files
94
- MODEL_PATH = "dish_classifier_final.keras"
95
- CLASSES_PATH = "class_names.json"
96
-
97
  @st.cache_resource
98
  def load_model():
99
- """Load the trained model with custom objects"""
100
-
101
- # Check if model exists
102
- if not os.path.exists(MODEL_PATH):
103
- st.error(f"""
104
- โŒ Model file not found: `{MODEL_PATH}`
105
-
106
- **Please upload the model file:**
107
- 1. Click on **"Files"** tab above
108
- 2. Click **"Add file"** โ†’ **"Upload file"**
109
- 3. Upload `dish_classifier_final.keras`
110
- 4. Upload `class_names.json`
111
- 5. Refresh this page
112
-
113
- **Note:** The model file should be around 80-100 MB.
114
- """)
115
- return None
116
-
117
  try:
118
- # Load model with custom objects
119
- model = tf.keras.models.load_model(
120
- MODEL_PATH,
121
- custom_objects=custom_objects,
122
- compile=False
123
- )
124
-
125
- # Recompile the model with the same metrics
126
- model.compile(
127
- optimizer='adam',
128
- loss='categorical_crossentropy',
129
- metrics=['accuracy', top_3_accuracy, top_5_accuracy]
130
- )
131
-
132
- st.success("โœ… Model loaded successfully!")
133
  return model
134
- except Exception as e:
135
- st.error(f"Error loading model: {str(e)}")
136
- st.info("Make sure the model file is not corrupted and was trained with TensorFlow 2.x")
137
- return None
 
 
 
138
 
139
  @st.cache_data
140
  def load_class_names():
141
- """Load class names from JSON file"""
142
- if not os.path.exists(CLASSES_PATH):
143
- st.error(f"โŒ Class names file not found: `{CLASSES_PATH}`")
144
- st.info("Please upload `class_names.json` file")
145
- return None
146
-
147
  try:
148
- with open(CLASSES_PATH, 'r') as f:
149
  class_names = json.load(f)
150
- st.success(f"โœ… Loaded {len(class_names)} Pakistani food classes!")
151
  return class_names
152
- except Exception as e:
153
- st.error(f"Error loading class names: {e}")
154
- return None
 
 
 
 
 
155
 
156
- def preprocess_image(image):
157
  """Preprocess image for model prediction"""
158
- # Convert to RGB if needed
159
  if image.mode != 'RGB':
160
  image = image.convert('RGB')
161
-
162
- # Resize to 224x224
163
- image = image.resize((224, 224))
164
-
165
- # Convert to array
166
- img_array = np.array(image)
167
-
168
- # Normalize to [0,1] range
169
- img_array = img_array / 255.0
170
-
171
- # Expand dimensions to create batch
172
  img_array = np.expand_dims(img_array, axis=0)
173
-
174
  return img_array
175
 
176
- def predict_image(model, class_names, image):
177
- """Make prediction on uploaded image"""
178
- processed_image = preprocess_image(image)
179
-
180
- # Get predictions
181
- predictions = model.predict(processed_image, verbose=0)[0]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
 
183
- # Get top 5 predictions
184
- top_5_idx = np.argsort(predictions)[-5:][::-1]
185
- top_5_labels = [class_names[idx] for idx in top_5_idx]
186
- top_5_probs = [predictions[idx] * 100 for idx in top_5_idx]
 
 
 
 
 
187
 
188
- return top_5_labels, top_5_probs
189
 
 
 
 
190
  def main():
191
- # Header with Pakistan theme
192
  st.markdown("""
193
- <div class="main-header">
194
- <h1>๐Ÿ› Pakistan Food Classifier</h1>
195
- <p>Upload a photo of Pakistani food and AI will identify it!</p>
196
- <p style="font-size: 0.9rem; opacity: 0.9;">Supports 80+ Pakistani dishes with 85% Top-5 Accuracy</p>
 
 
 
 
 
 
197
  </div>
198
  """, unsafe_allow_html=True)
199
 
200
- # Sidebar with Pakistan information
201
  with st.sidebar:
202
- st.markdown("### ๐Ÿ‡ต๐Ÿ‡ฐ Model Information")
203
  st.info("""
204
- - **Model:** EfficientNetV2S
205
- - **Classes:** 80 Pakistani Dishes
206
- - **Accuracy:** 56.25%
207
- - **Top-3 Accuracy:** 77.38%
208
- - **Top-5 Accuracy:** 84.62%
209
  """)
210
 
211
- st.markdown("### ๐Ÿฝ๏ธ Popular Pakistani Dishes")
212
- st.markdown("""
213
- - **Biryani** (Chicken, Mutton, Sindhi)
214
- - **Nihari**
215
- - **Haleem**
216
- - **Karachi Haleem**
217
- - **Chapli Kebab**
218
- - **Seekh Kebab**
219
- - **Karahi** (Chicken, Mutton)
220
- - **Daal Chawal**
221
- - **Naan** (Garlic, Plain, Roghni)
222
- - **Halwa Puri**
223
- - **Gulab Jamun**
224
- - **Kheer**
225
- - **And 68 more...**
226
- """)
227
 
228
- st.markdown("### ๐Ÿ“ How to Use")
 
 
 
 
229
  st.markdown("""
230
- 1. Click 'Browse files' below
231
- 2. Upload an image of Pakistani food
232
- 3. Wait for AI prediction
233
- 4. See top 5 predictions with confidence scores
234
  """)
235
 
236
  st.markdown("---")
237
- st.markdown("### ๐Ÿ“Š Model Performance")
238
-
239
- # Add simple gauges for accuracy
240
- st.markdown("**Exact Match Accuracy**")
241
- st.progress(0.56)
242
- st.caption("56.25%")
243
-
244
- st.markdown("**Top-3 Accuracy**")
245
- st.progress(0.77)
246
- st.caption("77.38%")
247
-
248
- st.markdown("**Top-5 Accuracy**")
249
- st.progress(0.85)
250
- st.caption("84.62%")
251
 
252
  st.markdown("---")
253
- st.markdown("Made with โค๏ธ for Pakistan")
254
 
255
  # Main content area
256
  col1, col2 = st.columns([1, 1])
257
 
258
  with col1:
259
- st.markdown("### ๐Ÿ“ค Upload Pakistani Food Image")
260
  uploaded_file = st.file_uploader(
261
  "Choose an image...",
262
  type=['jpg', 'jpeg', 'png', 'webp', 'gif'],
263
- help="Upload a clear image of Pakistani food for best results"
264
  )
265
 
266
  if uploaded_file is not None:
267
- # Display uploaded image
268
  image = Image.open(uploaded_file)
269
- st.image(image, caption='๐Ÿ“ธ Uploaded Image', use_container_width=True)
270
 
271
- # Add image info
272
- st.caption(f"Image size: {image.size[0]} x {image.size[1]} pixels")
 
 
 
 
273
 
274
  with col2:
275
  if uploaded_file is not None:
276
- st.markdown("### ๐Ÿ” Prediction Results")
277
 
278
- with st.spinner('๐Ÿ› Analyzing your Pakistani food image...'):
279
- # Load model and class names
280
  model = load_model()
281
  class_names = load_class_names()
282
 
283
  if model is not None and class_names is not None:
284
- # Make prediction
285
- top_5_labels, top_5_probs = predict_image(model, class_names, image)
 
286
 
287
- # Display results in a card
288
- st.markdown('<div class="prediction-card">', unsafe_allow_html=True)
 
 
289
 
290
- # Top 1 prediction (highlighted)
291
  st.markdown(f"""
292
- <div class="top1">
293
- <h3>๐Ÿ† Top Prediction</h3>
294
- <h2>๐Ÿฝ๏ธ {top_5_labels[0]}</h2>
295
- <p>Confidence: {top_5_probs[0]:.2f}%</p>
296
  </div>
297
  """, unsafe_allow_html=True)
298
 
299
- # Top 2 prediction
300
- st.markdown(f"""
301
- <div class="top2">
302
- <strong>๐Ÿฅˆ Most Likely:</strong><br>
303
- <span style="font-size: 1.1rem;">{top_5_labels[1]}</span><br>
304
- <span style="color: #666;">Confidence: {top_5_probs[1]:.2f}%</span>
305
- </div>
306
- """, unsafe_allow_html=True)
307
 
308
- # Top 3 prediction
309
- st.markdown(f"""
310
- <div class="top3">
311
- <strong>๐Ÿฅ‰ Could Be:</strong><br>
312
- <span style="font-size: 1.1rem;">{top_5_labels[2]}</span><br>
313
- <span style="color: #666;">Confidence: {top_5_probs[2]:.2f}%</span>
314
- </div>
315
- """, unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
316
 
317
- # Top 4 & 5
318
- st.markdown(f"""
319
- <div style="margin-top: 1rem; padding: 0.5rem;">
320
- <p><strong>4๏ธโƒฃ Other possibilities:</strong> {top_5_labels[3]} ({top_5_probs[3]:.1f}%)</p>
321
- <p><strong>5๏ธโƒฃ Also possible:</strong> {top_5_labels[4]} ({top_5_probs[4]:.1f}%)</p>
322
- </div>
323
- """, unsafe_allow_html=True)
324
 
325
- st.markdown('</div>', unsafe_allow_html=True)
326
-
327
- # Add confidence visualization
328
- st.markdown("### ๐Ÿ“Š Confidence Level")
329
- if top_5_probs[0] > 70:
330
- confidence_color = "๐ŸŸข High Confidence"
331
- elif top_5_probs[0] > 50:
332
- confidence_color = "๐ŸŸก Medium Confidence"
333
- else:
334
- confidence_color = "๐ŸŸ  Low Confidence"
335
 
336
- st.markdown(f"{confidence_color} - {top_5_probs[0]:.1f}% confident this is **{top_5_labels[0]}**")
 
 
337
 
338
- # Add suggestion for low confidence
339
- if top_5_probs[0] < 50:
340
- st.info("๐Ÿ’ก **Tip:** Try uploading a clearer image of just the dish for better accuracy")
 
 
 
341
 
342
- # Add information when no image is uploaded
343
- if not uploaded_file:
344
- st.markdown("---")
345
- st.markdown("### ๐Ÿ•Œ About This Model")
346
-
347
- col1, col2, col3 = st.columns(3)
348
- with col1:
349
- st.info("**๐Ÿ› Training Data**\n\nTrained on 3,200 images of 80+ Pakistani dishes from Pakistan's diverse cuisine")
350
- with col2:
351
- st.info("**๐Ÿค– Model Architecture**\n\nUses EfficientNetV2S, a state-of-the-art CNN pre-trained on ImageNet")
352
- with col3:
353
- st.info("**๐ŸŽฏ Purpose**\n\nHelp food enthusiasts, restaurants, and researchers identify Pakistani dishes")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
354
 
355
  # Footer
356
- st.markdown("---")
357
  st.markdown("""
358
- <div style="text-align: center; color: #666; font-size: 0.8rem;">
359
- <p>๐Ÿ‡ต๐Ÿ‡ฐ Celebrating Pakistan's rich culinary heritage ๐Ÿ‡ต๐Ÿ‡ฐ</p>
360
- <p>โš ๏ธ Note: Model accuracy is 56% for exact match, 85% for Top-5 predictions.<br>
361
- For best results, use clear, well-lit photos of individual dishes.</p>
362
  </div>
363
  """, unsafe_allow_html=True)
364
 
 
1
+ """
2
+ Indian/Pakistani Food Classifier
3
+ A deep learning model to identify 80+ Indian and Pakistani dishes
4
+ """
5
+
6
  import streamlit as st
7
  import tensorflow as tf
8
  import numpy as np
9
  from PIL import Image
10
  import json
11
  import os
12
+ import plotly.graph_objects as go
13
+ import pandas as pd
14
+ from datetime import datetime
15
+ import random
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
  # Page configuration
18
  st.set_page_config(
19
+ page_title="Pakistani & Indian Food Classifier",
20
  page_icon="๐Ÿ›",
21
  layout="wide",
22
  initial_sidebar_state="expanded"
23
  )
24
 
25
+ # Custom CSS for beautiful UI
26
  st.markdown("""
27
+ <style>
28
+ /* Main container */
29
+ .main {
30
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
31
  }
32
+
33
+ /* Header styling */
34
+ .header-container {
35
+ background: linear-gradient(135deg, #006400 0%, #008000 50%, #ffffff 100%);
36
  padding: 2rem;
37
+ border-radius: 20px;
 
 
38
  margin-bottom: 2rem;
39
+ text-align: center;
40
+ box-shadow: 0 10px 30px rgba(0,0,0,0.1);
41
+ }
42
+
43
+ .header-title {
44
+ font-size: 3rem;
45
+ font-weight: bold;
46
+ color: white;
47
+ margin-bottom: 0.5rem;
48
+ }
49
+
50
+ .header-subtitle {
51
+ font-size: 1.2rem;
52
+ color: rgba(255,255,255,0.9);
53
+ }
54
+
55
+ .pakistan-flag {
56
+ font-size: 2rem;
57
+ margin-bottom: 1rem;
58
  }
59
+
60
+ /* Card styling */
61
  .prediction-card {
62
+ background: white;
63
+ border-radius: 15px;
64
  padding: 1.5rem;
 
 
65
  margin: 1rem 0;
66
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
67
+ transition: transform 0.3s;
68
  }
69
+
70
+ .prediction-card:hover {
71
+ transform: translateY(-5px);
72
+ box-shadow: 0 6px 12px rgba(0,0,0,0.15);
73
+ }
74
+
75
+ /* Top prediction styling */
76
+ .top-prediction {
77
  background: linear-gradient(135deg, #006400 0%, #008000 100%);
78
  color: white;
79
+ border-radius: 15px;
80
+ padding: 1.5rem;
81
+ margin: 1rem 0;
82
+ text-align: center;
83
+ }
84
+
85
+ .top-prediction h2 {
86
+ font-size: 2.5rem;
87
+ margin: 0;
88
+ }
89
+
90
+ .confidence-score {
91
+ font-size: 1.2rem;
92
+ margin-top: 0.5rem;
93
+ }
94
+
95
+ /* Other predictions */
96
+ .other-prediction {
97
+ background: #f8f9fa;
98
+ border-left: 5px solid #006400;
99
+ border-radius: 10px;
100
  padding: 1rem;
101
+ margin: 0.8rem 0;
102
+ }
103
+
104
+ /* Sidebar styling */
105
+ .sidebar-content {
106
+ background: #f0f2f6;
107
  border-radius: 10px;
108
+ padding: 1rem;
109
  }
110
+
111
+ /* Button styling */
112
+ .stButton > button {
113
+ background: linear-gradient(135deg, #006400 0%, #008000 100%);
114
+ color: white;
115
+ border: none;
116
+ padding: 0.5rem 2rem;
117
+ border-radius: 25px;
118
+ font-weight: bold;
119
+ transition: all 0.3s;
120
  }
121
+
122
+ .stButton > button:hover {
123
+ transform: scale(1.05);
124
+ box-shadow: 0 4px 8px rgba(0,0,0,0.2);
 
 
125
  }
126
+
127
+ /* Footer */
128
+ .footer {
129
  text-align: center;
130
+ padding: 2rem;
131
+ color: #666;
132
+ font-size: 0.8rem;
133
+ margin-top: 3rem;
134
+ }
135
+
136
+ /* Success/Error messages */
137
+ .success-message {
138
+ background: #d4edda;
139
+ color: #155724;
140
+ padding: 1rem;
141
+ border-radius: 10px;
142
  margin: 1rem 0;
143
  }
144
+
145
+ .info-message {
146
+ background: #d1ecf1;
147
+ color: #0c5460;
148
+ padding: 1rem;
149
+ border-radius: 10px;
150
+ margin: 1rem 0;
151
+ }
152
+ </style>
153
  """, unsafe_allow_html=True)
154
 
155
+ # ============================================================
156
+ # LOAD MODEL AND CLASSES
157
+ # ============================================================
 
 
 
 
158
  @st.cache_resource
159
  def load_model():
160
+ """Load the trained model"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  try:
162
+ model = tf.keras.models.load_model('indian_food_classifier.keras')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  return model
164
+ except:
165
+ try:
166
+ model = tf.keras.models.load_model('/kaggle/working/indian_food_classifier.keras')
167
+ return model
168
+ except:
169
+ st.error("โš ๏ธ Model file not found. Please upload 'indian_food_classifier.keras'")
170
+ return None
171
 
172
  @st.cache_data
173
  def load_class_names():
174
+ """Load class names"""
 
 
 
 
 
175
  try:
176
+ with open('class_names.json', 'r') as f:
177
  class_names = json.load(f)
 
178
  return class_names
179
+ except:
180
+ try:
181
+ with open('/kaggle/working/class_names.json', 'r') as f:
182
+ class_names = json.load(f)
183
+ return class_names
184
+ except:
185
+ st.error("โš ๏ธ class_names.json not found. Please upload the file.")
186
+ return None
187
 
188
+ def preprocess_image(image, target_size=(224, 224)):
189
  """Preprocess image for model prediction"""
 
190
  if image.mode != 'RGB':
191
  image = image.convert('RGB')
192
+ image = image.resize(target_size)
193
+ img_array = np.array(image) / 255.0
 
 
 
 
 
 
 
 
 
194
  img_array = np.expand_dims(img_array, axis=0)
 
195
  return img_array
196
 
197
+ def format_food_name(name):
198
+ """Format food name for display"""
199
+ return name.replace('_', ' ').title()
200
+
201
+ def create_confidence_chart(confidences, labels, top_n=5):
202
+ """Create an interactive confidence chart"""
203
+ fig = go.Figure(data=[
204
+ go.Bar(
205
+ x=confidences[:top_n],
206
+ y=[format_food_name(l) for l in labels[:top_n]],
207
+ orientation='h',
208
+ marker=dict(
209
+ color=confidences[:top_n],
210
+ colorscale='Greens',
211
+ showscale=True,
212
+ colorbar=dict(title="Confidence (%)")
213
+ ),
214
+ text=[f"{c:.1f}%" for c in confidences[:top_n]],
215
+ textposition='outside'
216
+ )
217
+ ])
218
 
219
+ fig.update_layout(
220
+ title="Top Predictions Confidence Score",
221
+ xaxis_title="Confidence (%)",
222
+ yaxis_title="Food Item",
223
+ height=400,
224
+ margin=dict(l=0, r=0, t=40, b=0),
225
+ paper_bgcolor='rgba(0,0,0,0)',
226
+ plot_bgcolor='rgba(0,0,0,0)'
227
+ )
228
 
229
+ return fig
230
 
231
+ # ============================================================
232
+ # MAIN APP
233
+ # ============================================================
234
  def main():
235
+ # Header
236
  st.markdown("""
237
+ <div class="header-container">
238
+ <div class="pakistan-flag">
239
+ ๐Ÿ‡ต๐Ÿ‡ฐ ๐Ÿ‡ฎ๐Ÿ‡ณ ๐Ÿ‡ต๐Ÿ‡ฐ
240
+ </div>
241
+ <div class="header-title">
242
+ ๐Ÿ› Pakistani & Indian Food Classifier
243
+ </div>
244
+ <div class="header-subtitle">
245
+ AI-powered dish recognition for 80+ South Asian delicacies
246
+ </div>
247
  </div>
248
  """, unsafe_allow_html=True)
249
 
250
+ # Sidebar
251
  with st.sidebar:
252
+ st.markdown("### ๐Ÿ† Model Information")
253
  st.info("""
254
+ - **Architecture:** EfficientNetV2S
255
+ - **Classes:** 80 Indian/Pakistani Dishes
256
+ - **Accuracy:** 59.25%
257
+ - **Input Size:** 224x224 pixels
 
258
  """)
259
 
260
+ st.markdown("---")
261
+ st.markdown("### ๐Ÿฝ๏ธ Popular Dishes")
262
+
263
+ # Random popular dishes
264
+ popular_dishes = [
265
+ "Biryani", "Nihari", "Butter Chicken", "Aloo Gobi",
266
+ "Samosa", "Gulab Jamun", "Naan", "Haleem",
267
+ "Karahi", "Seekh Kebab", "Dal Makhani", "Ras Malai"
268
+ ]
 
 
 
 
 
 
 
269
 
270
+ for dish in random.sample(popular_dishes, min(6, len(popular_dishes))):
271
+ st.markdown(f"โ€ข {dish}")
272
+
273
+ st.markdown("---")
274
+ st.markdown("### ๐Ÿ“Š How It Works")
275
  st.markdown("""
276
+ 1. ๐Ÿ“ธ Upload a clear photo of food
277
+ 2. ๐Ÿค– AI analyzes the image
278
+ 3. ๐ŸŽฏ Get top 5 predictions with confidence scores
279
+ 4. ๐Ÿ“ˆ View detailed confidence chart
280
  """)
281
 
282
  st.markdown("---")
283
+ st.markdown("### ๐Ÿ’ก Tips for Best Results")
284
+ st.markdown("""
285
+ - Use well-lit photos
286
+ - Focus on the main dish
287
+ - Avoid cluttered backgrounds
288
+ - Single dish per photo works best
289
+ """)
 
 
 
 
 
 
 
290
 
291
  st.markdown("---")
292
+ st.markdown("Made with โค๏ธ for South Asian Cuisine")
293
 
294
  # Main content area
295
  col1, col2 = st.columns([1, 1])
296
 
297
  with col1:
298
+ st.markdown("### ๐Ÿ“ค Upload Food Image")
299
  uploaded_file = st.file_uploader(
300
  "Choose an image...",
301
  type=['jpg', 'jpeg', 'png', 'webp', 'gif'],
302
+ help="Upload a clear image of Pakistani or Indian food"
303
  )
304
 
305
  if uploaded_file is not None:
 
306
  image = Image.open(uploaded_file)
 
307
 
308
+ # Display image with styling
309
+ st.markdown("#### Preview")
310
+ st.image(image, caption="Uploaded Image", use_container_width=True)
311
+
312
+ # Image info
313
+ st.caption(f"๐Ÿ“ Image size: {image.size[0]} x {image.size[1]} pixels")
314
 
315
  with col2:
316
  if uploaded_file is not None:
317
+ st.markdown("### ๐Ÿ” Analysis Results")
318
 
319
+ with st.spinner("๐Ÿ› Analyzing your food image..."):
320
+ # Load model and classes
321
  model = load_model()
322
  class_names = load_class_names()
323
 
324
  if model is not None and class_names is not None:
325
+ # Preprocess and predict
326
+ processed_img = preprocess_image(image)
327
+ predictions = model.predict(processed_img, verbose=0)[0]
328
 
329
+ # Get top 5 predictions
330
+ top_5_idx = np.argsort(predictions)[-5:][::-1]
331
+ top_5_names = [class_names[idx] for idx in top_5_idx]
332
+ top_5_confidences = [predictions[idx] * 100 for idx in top_5_idx]
333
 
334
+ # Display top prediction (highlighted)
335
  st.markdown(f"""
336
+ <div class="top-prediction">
337
+ <div style="font-size: 1.2rem;">๐Ÿฅ‡ Top Prediction</div>
338
+ <h2>{format_food_name(top_5_names[0])}</h2>
339
+ <div class="confidence-score">Confidence: {top_5_confidences[0]:.2f}%</div>
340
  </div>
341
  """, unsafe_allow_html=True)
342
 
343
+ # Display other predictions
344
+ st.markdown("#### Other Possibilities")
 
 
 
 
 
 
345
 
346
+ for i in range(1, min(5, len(top_5_names))):
347
+ confidence_percent = top_5_confidences[i]
348
+
349
+ # Determine emoji based on rank
350
+ if i == 1:
351
+ emoji = "๐Ÿฅˆ"
352
+ elif i == 2:
353
+ emoji = "๐Ÿฅ‰"
354
+ else:
355
+ emoji = f"{i+1}๏ธโƒฃ"
356
+
357
+ st.markdown(f"""
358
+ <div class="other-prediction">
359
+ <strong>{emoji} {format_food_name(top_5_names[i])}</strong><br>
360
+ <span style="color: #666;">Confidence: {confidence_percent:.2f}%</span>
361
+ </div>
362
+ """, unsafe_allow_html=True)
363
 
364
+ # Confidence chart
365
+ st.markdown("---")
366
+ st.markdown("### ๐Ÿ“Š Confidence Analysis")
 
 
 
 
367
 
368
+ fig = create_confidence_chart(top_5_confidences, top_5_names, top_n=5)
369
+ st.plotly_chart(fig, use_container_width=True)
 
 
 
 
 
 
 
 
370
 
371
+ # Confidence meter for top prediction
372
+ st.markdown("#### Confidence Meter")
373
+ confidence_level = top_5_confidences[0]
374
 
375
+ if confidence_level > 70:
376
+ st.success(f"๐ŸŽฏ High confidence! The AI is very sure this is {format_food_name(top_5_names[0])}")
377
+ elif confidence_level > 50:
378
+ st.warning(f"๐Ÿค” Medium confidence. The AI thinks it's {format_food_name(top_5_names[0])}")
379
+ else:
380
+ st.info(f"๐Ÿ’ก Low confidence. Try uploading a clearer photo for better results")
381
 
382
+ # Footer with additional information
383
+ st.markdown("---")
384
+
385
+ col1, col2, col3 = st.columns(3)
386
+
387
+ with col1:
388
+ st.markdown("""
389
+ ### ๐ŸŽฏ Supported Cuisines
390
+ - Punjabi
391
+ - Mughlai
392
+ - South Indian
393
+ - Sindhi
394
+ - Kashmiri
395
+ - Hyderabadi
396
+ """)
397
+
398
+ with col2:
399
+ st.markdown("""
400
+ ### ๐Ÿœ Dish Categories
401
+ - Curries & Gravies
402
+ - Rice Dishes (Biryani)
403
+ - Breads (Naan, Roti)
404
+ - Desserts & Sweets
405
+ - Snacks & Appetizers
406
+ - Beverages
407
+ """)
408
+
409
+ with col3:
410
+ st.markdown("""
411
+ ### ๐Ÿ“ˆ Model Performance
412
+ - 59.25% Top-1 Accuracy
413
+ - 80+ Food Classes
414
+ - 3,200 Training Images
415
+ - EfficientNetV2S Backbone
416
+ - Real-time Predictions
417
+ """)
418
 
419
  # Footer
 
420
  st.markdown("""
421
+ <div class="footer">
422
+ <p>๐Ÿ‡ต๐Ÿ‡ฐ Celebrating the rich culinary heritage of Pakistan and India ๐Ÿ‡ฎ๐Ÿ‡ณ</p>
423
+ <p>โš ๏ธ Note: For best results, use clear, well-lit images of individual dishes. The model works best on traditional South Asian cuisine.</p>
424
+ <p>Made with Streamlit & TensorFlow | Model trained on 80+ dishes</p>
425
  </div>
426
  """, unsafe_allow_html=True)
427