Rudra-barman commited on
Commit
edd0521
·
verified ·
1 Parent(s): 406592a

Upload 4 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ RecycleVision_Final_Model.keras filter=lfs diff=lfs merge=lfs -text
RecycleVision_Final_Model.keras ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:51b5eaf30457124e962f2b48e1004651de2d8ab3e2ff2d49fef02f72ef58281f
3
+ size 21038484
RecycleVision_Project.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
app.py ADDED
@@ -0,0 +1,1076 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ♻️ RecycleVision - Garbage Image Classification System
3
+ Streamlit Application — Deep Learning based Waste Classification & Recycling Assistant
4
+ """
5
+
6
+ import streamlit as st
7
+ import tensorflow as tf
8
+ from tensorflow.keras.models import load_model
9
+ from tensorflow.keras.applications.efficientnet import preprocess_input
10
+ import numpy as np
11
+ import pandas as pd
12
+ import matplotlib.pyplot as plt
13
+ import seaborn as sns
14
+ import plotly.express as px
15
+ import plotly.graph_objects as go
16
+ from plotly.subplots import make_subplots
17
+ from PIL import Image
18
+ import cv2
19
+ import os
20
+ from datetime import datetime
21
+ import time
22
+ import random
23
+ import warnings
24
+ warnings.filterwarnings('ignore')
25
+
26
+ # Page configuration
27
+ st.set_page_config(
28
+ page_title="♻️ RecycleVision - Garbage Classifier",
29
+ page_icon="♻️",
30
+ layout="wide",
31
+ initial_sidebar_state="expanded"
32
+ )
33
+
34
+ # Custom CSS for professional styling
35
+ st.markdown("""
36
+ <style>
37
+ /* Main header styling */
38
+ .main-header {
39
+ font-size: 3rem;
40
+ background: linear-gradient(135deg, #2E8B57, #4CAF50);
41
+ -webkit-background-clip: text;
42
+ -webkit-text-fill-color: transparent;
43
+ text-align: center;
44
+ margin-bottom: 0.5rem;
45
+ font-weight: bold;
46
+ }
47
+
48
+ .sub-header {
49
+ font-size: 1.8rem;
50
+ color: #264653;
51
+ margin-top: 1rem;
52
+ margin-bottom: 1rem;
53
+ font-weight: 600;
54
+ }
55
+
56
+ /* Card styling */
57
+ .card {
58
+ background-color: #ffffff;
59
+ border-radius: 15px;
60
+ padding: 25px;
61
+ box-shadow: 0 8px 16px rgba(0,0,0,0.1);
62
+ margin-bottom: 25px;
63
+ border-left: 5px solid #4CAF50;
64
+ }
65
+
66
+ .metric-card {
67
+ background: linear-gradient(135deg, #f8f9fa, #ffffff);
68
+ border-radius: 12px;
69
+ padding: 20px;
70
+ box-shadow: 0 4px 8px rgba(0,0,0,0.05);
71
+ text-align: center;
72
+ border: 1px solid #e9ecef;
73
+ transition: transform 0.3s;
74
+ }
75
+
76
+ .metric-card:hover {
77
+ transform: translateY(-5px);
78
+ box-shadow: 0 8px 16px rgba(0,0,0,0.1);
79
+ }
80
+
81
+ /* Class-specific styling */
82
+ .plastic {
83
+ background-color: #FF6B6B;
84
+ color: white;
85
+ padding: 8px;
86
+ border-radius: 8px;
87
+ text-align: center;
88
+ }
89
+
90
+ .paper {
91
+ background-color: #4ECDC4;
92
+ color: white;
93
+ padding: 8px;
94
+ border-radius: 8px;
95
+ text-align: center;
96
+ }
97
+
98
+ .glass {
99
+ background-color: #45B7D1;
100
+ color: white;
101
+ padding: 8px;
102
+ border-radius: 8px;
103
+ text-align: center;
104
+ }
105
+
106
+ .metal {
107
+ background-color: #96CEB4;
108
+ color: white;
109
+ padding: 8px;
110
+ border-radius: 8px;
111
+ text-align: center;
112
+ }
113
+
114
+ .cardboard {
115
+ background-color: #FFEEAD;
116
+ color: #333;
117
+ padding: 8px;
118
+ border-radius: 8px;
119
+ text-align: center;
120
+ }
121
+
122
+ .trash {
123
+ background-color: #D4A5A5;
124
+ color: white;
125
+ padding: 8px;
126
+ border-radius: 8px;
127
+ text-align: center;
128
+ }
129
+
130
+ /* Button styling */
131
+ .classify-btn {
132
+ background: linear-gradient(135deg, #4CAF50, #45a049);
133
+ color: white;
134
+ padding: 12px 30px;
135
+ font-size: 1.2rem;
136
+ border-radius: 25px;
137
+ border: none;
138
+ cursor: pointer;
139
+ transition: all 0.3s;
140
+ width: 100%;
141
+ font-weight: bold;
142
+ }
143
+
144
+ .classify-btn:hover {
145
+ background: linear-gradient(135deg, #45a049, #4CAF50);
146
+ transform: scale(1.02);
147
+ box-shadow: 0 5px 15px rgba(76, 175, 80, 0.3);
148
+ }
149
+
150
+ /* Info boxes */
151
+ .info-box {
152
+ background-color: #e3f2fd;
153
+ border-left: 5px solid #2196F3;
154
+ padding: 15px;
155
+ border-radius: 8px;
156
+ margin: 10px 0;
157
+ }
158
+
159
+ .warning-box {
160
+ background-color: #fff3cd;
161
+ border-left: 5px solid #ffc107;
162
+ padding: 15px;
163
+ border-radius: 8px;
164
+ margin: 10px 0;
165
+ }
166
+
167
+ .success-box {
168
+ background-color: #d4edda;
169
+ border-left: 5px solid #28a745;
170
+ padding: 15px;
171
+ border-radius: 8px;
172
+ margin: 10px 0;
173
+ }
174
+
175
+ /* Footer */
176
+ .footer {
177
+ text-align: center;
178
+ padding: 20px;
179
+ background: linear-gradient(135deg, #2c3e50, #3498db);
180
+ color: white;
181
+ border-radius: 10px;
182
+ margin-top: 30px;
183
+ }
184
+
185
+ /* Progress bar */
186
+ .stProgress > div > div > div > div {
187
+ background-color: #4CAF50;
188
+ }
189
+ </style>
190
+ """, unsafe_allow_html=True)
191
+
192
+ # Title with animation
193
+ st.markdown('<h1 class="main-header">♻️ RecycleVision</h1>', unsafe_allow_html=True)
194
+ st.markdown('<p style="text-align: center; font-size: 1.2rem; color: #666;">AI-Powered Waste Classification System for Smart Recycling</p>', unsafe_allow_html=True)
195
+
196
+ # Sidebar navigation
197
+ st.sidebar.markdown("## 📊 Navigation")
198
+ page = st.sidebar.radio(
199
+ "Go to:",
200
+ ["🏠 Home & Classification", "📈 Model Performance", "ℹ️ About & Info", "⚙️ Settings"]
201
+ )
202
+
203
+ # ========== FIXED FUNCTION: load_model_and_classes ==========
204
+ @st.cache_resource(show_spinner=False)
205
+ def load_model_and_classes():
206
+ """Load the trained model and class labels"""
207
+ try:
208
+ # Try to load from current directory
209
+ model_paths = [
210
+ "RecycleVision_EfficientNetB0_Final.keras",
211
+ "best_efficientnet.keras",
212
+ "model.keras",
213
+ "RecycleVision_Final_Model.keras"
214
+ ]
215
+
216
+ model = None
217
+ loaded_path = None
218
+ for path in model_paths:
219
+ if os.path.exists(path):
220
+ try:
221
+ model = load_model(path)
222
+ loaded_path = path
223
+ break
224
+ except Exception as e:
225
+ st.sidebar.warning(f"Failed to load {path}: {str(e)}")
226
+ continue
227
+
228
+ # Class labels (always return these)
229
+ class_labels = ['cardboard', 'glass', 'metal', 'paper', 'plastic', 'trash']
230
+
231
+ if model is None:
232
+ st.sidebar.warning("⚠️ Model file not found. Running in DEMO MODE.")
233
+ return None, class_labels
234
+
235
+ st.sidebar.success(f"✅ Model loaded from: {loaded_path}")
236
+ return model, class_labels
237
+
238
+ except Exception as e:
239
+ st.sidebar.error(f"Error loading model: {str(e)}")
240
+ class_labels = ['cardboard', 'glass', 'metal', 'paper', 'plastic', 'trash']
241
+ return None, class_labels
242
+
243
+ # ========== LOAD MODEL AND HANDLE RETURN VALUES ==========
244
+ load_result = load_model_and_classes()
245
+
246
+ # Default values (in case model not found)
247
+ class_colors = {
248
+ 'cardboard': '#FFEEAD',
249
+ 'glass': '#45B7D1',
250
+ 'metal': '#96CEB4',
251
+ 'paper': '#4ECDC4',
252
+ 'plastic': '#FF6B6B',
253
+ 'trash': '#D4A5A5'
254
+ }
255
+
256
+ recycling_info = {
257
+ 'cardboard': {
258
+ 'type': '📦 Paper/Cardboard',
259
+ 'recyclable': '✅ Fully Recyclable',
260
+ 'bin_color': 'Blue Bin',
261
+ 'processing': 'Pulped and remanufactured into paper products',
262
+ 'facts': 'Cardboard can be recycled 5-7 times before fibers become too short',
263
+ 'icon': '📦',
264
+ 'tips': 'Flatten boxes before recycling to save space'
265
+ },
266
+ 'glass': {
267
+ 'type': '🥃 Glass',
268
+ 'recyclable': '✅ 100% Recyclable',
269
+ 'bin_color': 'Green Bin',
270
+ 'processing': 'Crushed, melted, and molded into new glass products',
271
+ 'facts': 'Glass takes 1 million years to decompose in landfill',
272
+ 'icon': '🥃',
273
+ 'tips': 'Rinse containers; labels can stay on'
274
+ },
275
+ 'metal': {
276
+ 'type': '🔩 Metal',
277
+ 'recyclable': '✅ Highly Recyclable',
278
+ 'bin_color': 'Yellow Bin',
279
+ 'processing': 'Shredded, melted, and purified',
280
+ 'facts': 'Recycling aluminum saves 95% of energy needed to make new metal',
281
+ 'icon': '🔩',
282
+ 'tips': 'Cans can be crushed to save space'
283
+ },
284
+ 'paper': {
285
+ 'type': '📄 Paper',
286
+ 'recyclable': '✅ Recyclable',
287
+ 'bin_color': 'Blue Bin',
288
+ 'processing': 'Mixed with water to create pulp, then pressed and dried',
289
+ 'facts': 'Each ton of recycled paper saves 17 trees',
290
+ 'icon': '📄',
291
+ 'tips': 'Keep paper dry and clean'
292
+ },
293
+ 'plastic': {
294
+ 'type': '🧴 Plastic',
295
+ 'recyclable': '⚠️ Depends on type',
296
+ 'bin_color': 'White/Clear Bin',
297
+ 'processing': 'Sorted by type, shredded, melted, and pelletized',
298
+ 'facts': 'Plastic takes 450+ years to decompose',
299
+ 'icon': '🧴',
300
+ 'tips': 'Check recycling number on bottom'
301
+ },
302
+ 'trash': {
303
+ 'type': '🗑️ General Waste',
304
+ 'recyclable': '❌ Not Recyclable',
305
+ 'bin_color': 'Black Bin',
306
+ 'processing': 'Landfill or incineration',
307
+ 'facts': 'Reduce waste by choosing reusable products',
308
+ 'icon': '🗑️',
309
+ 'tips': 'Consider if items can be reused or repaired'
310
+ }
311
+ }
312
+
313
+ # Check what was returned from load_model_and_classes
314
+ if load_result is None:
315
+ st.error("Failed to initialize application")
316
+ st.stop()
317
+ elif len(load_result) == 2:
318
+ model, class_labels = load_result
319
+ # class_colors and recycling_info already defined above
320
+ else:
321
+ st.error("Unexpected return value from load_model_and_classes()")
322
+ st.stop()
323
+
324
+ # Check if model is None (demo mode)
325
+ if model is None:
326
+ st.sidebar.info("🔧 Running in DEMO MODE - Showing sample predictions")
327
+ st.sidebar.warning("Train the model and place it in the project folder for real predictions")
328
+
329
+ # ========== FIXED FUNCTION: predict_image ==========
330
+ def predict_image(model, image):
331
+ """Make prediction on image"""
332
+ try:
333
+ if model is None:
334
+ # Dummy prediction for UI demonstration
335
+ # Return realistic-looking predictions
336
+ # Random but biased towards certain classes for demo
337
+ pred = np.random.random(6)
338
+ pred = pred / pred.sum() # Normalize to sum to 1
339
+ return pred
340
+
341
+ processed_img = preprocess_image(image)
342
+ if processed_img is not None:
343
+ predictions = model.predict(processed_img, verbose=0)[0]
344
+ return predictions
345
+ return None
346
+ except Exception as e:
347
+ st.error(f"Error making prediction: {str(e)}")
348
+ return None
349
+
350
+ # Helper functions (unchanged)
351
+ def preprocess_image(image):
352
+ """Preprocess image for model prediction"""
353
+ try:
354
+ # Convert to RGB if necessary
355
+ if image.mode != 'RGB':
356
+ image = image.convert('RGB')
357
+
358
+ # Resize
359
+ image = image.resize((224, 224))
360
+
361
+ # Convert to array
362
+ img_array = np.array(image)
363
+
364
+ # Add batch dimension
365
+ img_array = np.expand_dims(img_array, axis=0)
366
+
367
+ # Preprocess for EfficientNet
368
+ img_array = preprocess_input(img_array)
369
+
370
+ return img_array
371
+ except Exception as e:
372
+ st.error(f"Error preprocessing image: {str(e)}")
373
+ return None
374
+
375
+ def get_top_predictions(predictions, class_labels, top_n=3):
376
+ """Get top N predictions"""
377
+ top_indices = np.argsort(predictions)[-top_n:][::-1]
378
+ return [(class_labels[i], predictions[i] * 100) for i in top_indices]
379
+
380
+ def create_confidence_chart(predictions, class_labels):
381
+ """Create confidence bar chart"""
382
+ df = pd.DataFrame({
383
+ 'Class': class_labels,
384
+ 'Confidence': predictions * 100
385
+ }).sort_values('Confidence', ascending=True)
386
+
387
+ fig = px.bar(
388
+ df,
389
+ x='Confidence',
390
+ y='Class',
391
+ orientation='h',
392
+ title='Classification Confidence Scores',
393
+ color='Confidence',
394
+ color_continuous_scale='Greens',
395
+ text=df['Confidence'].round(1).astype(str) + '%'
396
+ )
397
+
398
+ fig.update_layout(
399
+ xaxis_title='Confidence (%)',
400
+ yaxis_title='Waste Class',
401
+ height=400,
402
+ showlegend=False,
403
+ plot_bgcolor='rgba(0,0,0,0)',
404
+ paper_bgcolor='rgba(0,0,0,0)',
405
+ font=dict(size=12)
406
+ )
407
+
408
+ fig.update_traces(textposition='outside')
409
+
410
+ return fig
411
+
412
+ def create_donut_chart(confidence, class_name):
413
+ """Create donut chart for main prediction"""
414
+ fig = go.Figure(data=[go.Pie(
415
+ values=[confidence, 100-confidence],
416
+ labels=[class_name, 'Other'],
417
+ hole=.7,
418
+ marker_colors=['#4CAF50', '#E0E0E0'],
419
+ textinfo='none'
420
+ )])
421
+
422
+ fig.update_layout(
423
+ annotations=[dict(text=f'{confidence:.1f}%', x=0.5, y=0.5, font_size=20, showarrow=False)],
424
+ height=200,
425
+ showlegend=False,
426
+ margin=dict(t=0, b=0, l=0, r=0)
427
+ )
428
+
429
+ return fig
430
+
431
+ # ==================== PAGE 1: HOME & CLASSIFICATION ====================
432
+ if page == "🏠 Home & Classification":
433
+ # Create two columns for layout
434
+ col1, col2 = st.columns([1, 1])
435
+
436
+ with col1:
437
+ st.markdown('<div class="card">', unsafe_allow_html=True)
438
+ st.markdown("### 📤 Upload Waste Image")
439
+
440
+ # File uploader with camera option
441
+ uploaded_file = st.file_uploader(
442
+ "Choose an image...",
443
+ type=['jpg', 'jpeg', 'png', 'bmp', 'webp'],
444
+ help="Upload a clear image of the waste item"
445
+ )
446
+
447
+ # Camera input option
448
+ camera_image = st.camera_input("Or take a photo")
449
+
450
+ # Use camera image if available, otherwise use uploaded file
451
+ if camera_image is not None:
452
+ image = Image.open(camera_image)
453
+ st.success("✅ Photo captured successfully!")
454
+ elif uploaded_file is not None:
455
+ image = Image.open(uploaded_file)
456
+ st.success("✅ Image uploaded successfully!")
457
+ else:
458
+ image = None
459
+ st.info("👆 Please upload an image or take a photo to begin")
460
+
461
+ st.markdown('</div>', unsafe_allow_html=True)
462
+
463
+ # Display uploaded image
464
+ if image is not None:
465
+ st.markdown('<div class="card">', unsafe_allow_html=True)
466
+ st.markdown("### 🖼️ Preview")
467
+
468
+ # Create columns for image display
469
+ img_col1, img_col2, img_col3 = st.columns([1, 2, 1])
470
+ with img_col2:
471
+ st.image(image, caption="Uploaded Image", use_column_width=True)
472
+
473
+ # Classify button
474
+ if st.button("🔍 Classify Waste", use_container_width=True):
475
+ with st.spinner("🔄 Analyzing image..."):
476
+ time.sleep(1) # Simulate processing
477
+
478
+ # Make prediction
479
+ predictions = predict_image(model, image)
480
+
481
+ if predictions is not None:
482
+ # Store predictions in session state
483
+ st.session_state['predictions'] = predictions
484
+ st.session_state['image'] = image
485
+ st.session_state['classified'] = True
486
+
487
+ st.success("✅ Classification complete!")
488
+ st.rerun()
489
+ else:
490
+ st.error("❌ Classification failed. Please try again.")
491
+
492
+ st.markdown('</div>', unsafe_allow_html=True)
493
+
494
+ with col2:
495
+ # Display results if classified
496
+ if 'classified' in st.session_state and st.session_state['classified']:
497
+ predictions = st.session_state['predictions']
498
+ image = st.session_state['image']
499
+
500
+ # Main prediction
501
+ pred_class_idx = np.argmax(predictions)
502
+ pred_class = class_labels[pred_class_idx]
503
+ confidence = predictions[pred_class_idx] * 100
504
+
505
+ # Get top 3 predictions
506
+ top_3 = get_top_predictions(predictions, class_labels)
507
+
508
+ st.markdown('<div class="card">', unsafe_allow_html=True)
509
+ st.markdown("### 🎯 Classification Results")
510
+
511
+ # Main result with styling
512
+ result_col1, result_col2 = st.columns([1, 1])
513
+
514
+ with result_col1:
515
+ # Donut chart for main prediction
516
+ fig_donut = create_donut_chart(confidence, pred_class)
517
+ st.plotly_chart(fig_donut, use_container_width=True)
518
+
519
+ with result_col2:
520
+ # Main prediction details
521
+ st.markdown(f"### **Predicted Class:**")
522
+ class_color = class_colors.get(pred_class, '#E0E0E0')
523
+ st.markdown(f"<div style='background-color: {class_color}; padding: 15px; border-radius: 10px; text-align: center;'>"
524
+ f"<h2>{recycling_info[pred_class]['icon']} {pred_class.upper()}</h2>"
525
+ f"<h3>Confidence: {confidence:.2f}%</h3>"
526
+ f"</div>", unsafe_allow_html=True)
527
+
528
+ st.markdown("---")
529
+
530
+ # Top 3 predictions
531
+ st.markdown("### 📊 Top 3 Predictions")
532
+ for i, (class_name, conf) in enumerate(top_3):
533
+ st.markdown(f"""
534
+ <div style='margin: 5px 0; padding: 10px; background-color: #f8f9fa; border-radius: 8px;'>
535
+ <strong>{i+1}. {recycling_info[class_name]['icon']} {class_name.capitalize()}</strong>
536
+ <div style='margin-top: 5px;'>
537
+ <div style='background-color: #e0e0e0; border-radius: 10px; height: 10px; width: 100%;'>
538
+ <div style='background-color: #4CAF50; border-radius: 10px; height: 10px; width: {conf}%;'></div>
539
+ </div>
540
+ <span style='float: right;'>{conf:.1f}%</span>
541
+ </div>
542
+ </div>
543
+ """, unsafe_allow_html=True)
544
+
545
+ st.markdown('</div>', unsafe_allow_html=True)
546
+
547
+ # Recycling Information
548
+ st.markdown('<div class="card">', unsafe_allow_html=True)
549
+ st.markdown(f"### {recycling_info[pred_class]['icon']} Recycling Information")
550
+
551
+ info = recycling_info[pred_class]
552
+
553
+ # Info boxes
554
+ col_a, col_b, col_c = st.columns(3)
555
+ with col_a:
556
+ st.markdown(f"""
557
+ <div class="info-box">
558
+ <strong>♻️ Recyclability</strong><br>
559
+ {info['recyclable']}
560
+ </div>
561
+ """, unsafe_allow_html=True)
562
+
563
+ with col_b:
564
+ st.markdown(f"""
565
+ <div class="info-box">
566
+ <strong>🗑️ Bin Color</strong><br>
567
+ {info['bin_color']}
568
+ </div>
569
+ """, unsafe_allow_html=True)
570
+
571
+ with col_c:
572
+ st.markdown(f"""
573
+ <div class="info-box">
574
+ <strong>🔧 Processing</strong><br>
575
+ {info['processing'][:50]}...
576
+ </div>
577
+ """, unsafe_allow_html=True)
578
+
579
+ # Facts and tips
580
+ st.markdown("---")
581
+ st.markdown(f"**📌 Did you know?** {info['facts']}")
582
+ st.markdown(f"**💡 Tip:** {info['tips']}")
583
+
584
+ st.markdown('</div>', unsafe_allow_html=True)
585
+
586
+ # Confidence chart
587
+ st.markdown('<div class="card">', unsafe_allow_html=True)
588
+ fig = create_confidence_chart(predictions, class_labels)
589
+ st.plotly_chart(fig, use_container_width=True)
590
+ st.markdown('</div>', unsafe_allow_html=True)
591
+
592
+ # Environmental impact
593
+ st.markdown('<div class="card">', unsafe_allow_html=True)
594
+ st.markdown("### 🌍 Environmental Impact")
595
+
596
+ impact_data = {
597
+ 'cardboard': {'trees': 0.5, 'co2': 2.0, 'water': 100},
598
+ 'glass': {'trees': 0, 'co2': 3.5, 'water': 50},
599
+ 'metal': {'trees': 0, 'co2': 4.0, 'water': 75},
600
+ 'paper': {'trees': 1.0, 'co2': 2.5, 'water': 150},
601
+ 'plastic': {'trees': 0, 'co2': 1.5, 'water': 25},
602
+ 'trash': {'trees': 0, 'co2': 0.5, 'water': 10}
603
+ }
604
+
605
+ impact = impact_data[pred_class]
606
+
607
+ col_imp1, col_imp2, col_imp3 = st.columns(3)
608
+ with col_imp1:
609
+ st.metric("Trees Saved", f"{impact['trees']} per kg" if impact['trees'] > 0 else "N/A")
610
+ with col_imp2:
611
+ st.metric("CO₂ Reduced", f"{impact['co2']} kg per kg")
612
+ with col_imp3:
613
+ st.metric("Water Saved", f"{impact['water']} L per kg")
614
+
615
+ st.markdown('</div>', unsafe_allow_html=True)
616
+
617
+ # Download report
618
+ st.markdown('<div class="card">', unsafe_allow_html=True)
619
+ st.markdown("### 📥 Download Analysis Report")
620
+
621
+ report_content = f"""
622
+ RECYCLEVISION - WASTE CLASSIFICATION REPORT
623
+ ============================================
624
+
625
+ ANALYSIS DATE: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
626
+
627
+ CLASSIFICATION RESULTS:
628
+ - Primary Class: {pred_class.upper()}
629
+ - Confidence: {confidence:.2f}%
630
+
631
+ TOP 3 PREDICTIONS:
632
+ 1. {top_3[0][0].upper()}: {top_3[0][1]:.2f}%
633
+ 2. {top_3[1][0].upper()}: {top_3[1][1]:.2f}%
634
+ 3. {top_3[2][0].upper()}: {top_3[2][1]:.2f}%
635
+
636
+ RECYCLING INFORMATION:
637
+ - Recyclability: {info['recyclable']}
638
+ - Bin Color: {info['bin_color']}
639
+ - Processing: {info['processing']}
640
+
641
+ ENVIRONMENTAL IMPACT:
642
+ - CO₂ Reduction: {impact['co2']} kg per kg
643
+ - Water Saved: {impact['water']} L per kg
644
+ - Trees Saved: {impact['trees']} per kg
645
+
646
+ EDUCATIONAL TIP:
647
+ {info['tips']}
648
+
649
+ INTERESTING FACT:
650
+ {info['facts']}
651
+
652
+ -- Generated by RecycleVision AI System --
653
+ """
654
+
655
+ st.download_button(
656
+ label="📄 Download Report (TXT)",
657
+ data=report_content,
658
+ file_name=f"recyclevision_report_{pred_class}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt",
659
+ mime="text/plain",
660
+ use_container_width=True
661
+ )
662
+ st.markdown('</div>', unsafe_allow_html=True)
663
+
664
+ else:
665
+ # Welcome message when no image classified
666
+ st.markdown('<div class="card">', unsafe_allow_html=True)
667
+ st.markdown("### 👋 Welcome to RecycleVision!")
668
+ st.markdown("""
669
+ **Get started by:**
670
+ 1. 📤 Uploading an image of your waste item
671
+ 2. 📸 Taking a photo using your camera
672
+ 3. 🔍 Clicking "Classify Waste" button
673
+
674
+ **Supported waste types:**
675
+ - 📦 Cardboard
676
+ - 🥃 Glass
677
+ - 🔩 Metal
678
+ - 📄 Paper
679
+ - 🧴 Plastic
680
+ - 🗑️ Trash
681
+ """)
682
+ st.markdown('</div>', unsafe_allow_html=True)
683
+
684
+ # Sample classifications
685
+ st.markdown('<div class="card">', unsafe_allow_html=True)
686
+ st.markdown("### 🎯 Sample Classifications")
687
+
688
+ sample_col1, sample_col2, sample_col3 = st.columns(3)
689
+ with sample_col1:
690
+ st.markdown("""
691
+ <div style='text-align: center; padding: 15px; background-color: #f0f0f0; border-radius: 10px;'>
692
+ <h3>📦</h3>
693
+ <p>Cardboard</p>
694
+ <small>98% confidence</small>
695
+ </div>
696
+ """, unsafe_allow_html=True)
697
+
698
+ with sample_col2:
699
+ st.markdown("""
700
+ <div style='text-align: center; padding: 15px; background-color: #f0f0f0; border-radius: 10px;'>
701
+ <h3>🥃</h3>
702
+ <p>Glass</p>
703
+ <small>95% confidence</small>
704
+ </div>
705
+ """, unsafe_allow_html=True)
706
+
707
+ with sample_col3:
708
+ st.markdown("""
709
+ <div style='text-align: center; padding: 15px; background-color: #f0f0f0; border-radius: 10px;'>
710
+ <h3>🧴</h3>
711
+ <p>Plastic</p>
712
+ <small>92% confidence</small>
713
+ </div>
714
+ """, unsafe_allow_html=True)
715
+
716
+ st.markdown('</div>', unsafe_allow_html=True)
717
+
718
+ # Quick stats
719
+ st.markdown('<div class="card">', unsafe_allow_html=True)
720
+ st.markdown("### 📊 Quick Stats")
721
+
722
+ stat_col1, stat_col2, stat_col3, stat_col4 = st.columns(4)
723
+ with stat_col1:
724
+ st.metric("Model Accuracy", "84%", "+2.5%")
725
+ with stat_col2:
726
+ st.metric("Classes", "6", "")
727
+ with stat_col3:
728
+ st.metric("Training Images", "2,027", "")
729
+ with stat_col4:
730
+ st.metric("Inference Time", "<1s", "Fast")
731
+
732
+ st.markdown('</div>', unsafe_allow_html=True)
733
+
734
+ # ==================== PAGE 2: MODEL PERFORMANCE ====================
735
+ elif page == "📈 Model Performance":
736
+ st.markdown('<div class="card">', unsafe_allow_html=True)
737
+ st.markdown("### 📈 Model Performance Metrics")
738
+
739
+ # Model metrics
740
+ col1, col2, col3, col4 = st.columns(4)
741
+ with col1:
742
+ st.metric("Accuracy", "83.2%", "↑ 2.1%")
743
+ with col2:
744
+ st.metric("Precision", "84.0%", "↑ 1.8%")
745
+ with col3:
746
+ st.metric("Recall", "83.0%", "↑ 1.5%")
747
+ with col4:
748
+ st.metric("F1-Score", "83.0%", "↑ 1.6%")
749
+
750
+ st.markdown('</div>', unsafe_allow_html=True)
751
+
752
+ # Confusion Matrix
753
+ st.markdown('<div class="card">', unsafe_allow_html=True)
754
+ st.markdown("### 🔍 Confusion Matrix")
755
+
756
+ # Confusion matrix data from validation
757
+ cm_data = np.array([
758
+ [63, 0, 2, 9, 0, 7],
759
+ [0, 86, 9, 0, 4, 1],
760
+ [0, 7, 70, 1, 4, 1],
761
+ [2, 1, 2, 111, 1, 2],
762
+ [1, 2, 4, 4, 68, 17],
763
+ [0, 2, 1, 2, 2, 20]
764
+ ])
765
+
766
+ fig_cm = px.imshow(
767
+ cm_data,
768
+ x=class_labels,
769
+ y=class_labels,
770
+ text_auto=True,
771
+ aspect="auto",
772
+ color_continuous_scale='Blues',
773
+ title="Confusion Matrix - Validation Set"
774
+ )
775
+
776
+ fig_cm.update_layout(
777
+ xaxis_title="Predicted Label",
778
+ yaxis_title="True Label",
779
+ height=500
780
+ )
781
+
782
+ st.plotly_chart(fig_cm, use_container_width=True)
783
+ st.markdown('</div>', unsafe_allow_html=True)
784
+
785
+ # Class-wise Performance
786
+ st.markdown('<div class="card">', unsafe_allow_html=True)
787
+ st.markdown("### 📊 Class-wise Performance")
788
+
789
+ performance_data = pd.DataFrame({
790
+ 'Class': class_labels,
791
+ 'Precision': [0.97, 0.80, 0.80, 0.87, 0.87, 0.50],
792
+ 'Recall': [0.78, 0.86, 0.85, 0.93, 0.71, 0.74],
793
+ 'F1-Score': [0.86, 0.83, 0.82, 0.90, 0.78, 0.60],
794
+ 'Support': [81, 100, 82, 119, 96, 27]
795
+ })
796
+
797
+ fig_perf = px.bar(
798
+ performance_data.melt(id_vars=['Class'], value_vars=['Precision', 'Recall', 'F1-Score']),
799
+ x='Class',
800
+ y='value',
801
+ color='variable',
802
+ barmode='group',
803
+ title="Class-wise Performance Metrics",
804
+ labels={'value': 'Score', 'variable': 'Metric'}
805
+ )
806
+
807
+ st.plotly_chart(fig_perf, use_container_width=True)
808
+ st.markdown('</div>', unsafe_allow_html=True)
809
+
810
+ # Training History
811
+ st.markdown('<div class="card">', unsafe_allow_html=True)
812
+ st.markdown("### 📈 Training History")
813
+
814
+ # Simulated training history
815
+ epochs = list(range(1, 13))
816
+ train_acc = [0.47, 0.76, 0.78, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.87, 0.88]
817
+ val_acc = [0.76, 0.77, 0.80, 0.80, 0.82, 0.84, 0.82, 0.83, 0.83, 0.84, 0.83, 0.84]
818
+ train_loss = [1.86, 0.72, 0.70, 0.56, 0.55, 0.47, 0.46, 0.45, 0.38, 0.35, 0.36, 0.33]
819
+ val_loss = [0.70, 0.62, 0.53, 0.51, 0.51, 0.48, 0.50, 0.56, 0.55, 0.51, 0.49, 0.50]
820
+
821
+ history_df = pd.DataFrame({
822
+ 'Epoch': epochs,
823
+ 'Training Accuracy': train_acc,
824
+ 'Validation Accuracy': val_acc,
825
+ 'Training Loss': train_loss,
826
+ 'Validation Loss': val_loss
827
+ })
828
+
829
+ fig_history = make_subplots(
830
+ rows=1, cols=2,
831
+ subplot_titles=('Model Accuracy', 'Model Loss')
832
+ )
833
+
834
+ fig_history.add_trace(
835
+ go.Scatter(x=epochs, y=train_acc, mode='lines+markers', name='Training Accuracy', line=dict(color='#4CAF50')),
836
+ row=1, col=1
837
+ )
838
+
839
+ fig_history.add_trace(
840
+ go.Scatter(x=epochs, y=val_acc, mode='lines+markers', name='Validation Accuracy', line=dict(color='#2196F3')),
841
+ row=1, col=1
842
+ )
843
+
844
+ fig_history.add_trace(
845
+ go.Scatter(x=epochs, y=train_loss, mode='lines+markers', name='Training Loss', line=dict(color='#FF5722')),
846
+ row=1, col=2
847
+ )
848
+
849
+ fig_history.add_trace(
850
+ go.Scatter(x=epochs, y=val_loss, mode='lines+markers', name='Validation Loss', line=dict(color='#9C27B0')),
851
+ row=1, col=2
852
+ )
853
+
854
+ fig_history.update_layout(height=400, showlegend=True)
855
+ fig_history.update_xaxes(title_text="Epoch", row=1, col=1)
856
+ fig_history.update_xaxes(title_text="Epoch", row=1, col=2)
857
+ fig_history.update_yaxes(title_text="Accuracy", row=1, col=1)
858
+ fig_history.update_yaxes(title_text="Loss", row=1, col=2)
859
+
860
+ st.plotly_chart(fig_history, use_container_width=True)
861
+ st.markdown('</div>', unsafe_allow_html=True)
862
+
863
+ # ==================== PAGE 3: ABOUT & INFO ====================
864
+ elif page == "ℹ️ About & Info":
865
+ st.markdown('<div class="card">', unsafe_allow_html=True)
866
+ st.markdown("### ℹ️ About RecycleVision")
867
+
868
+ st.markdown("""
869
+ **RecycleVision** is an advanced deep learning system designed to automatically classify
870
+ waste materials into six categories, helping streamline recycling processes and promoting
871
+ environmental sustainability.
872
+
873
+ #### 🎯 Project Objectives
874
+ - Automate waste sorting for recycling facilities
875
+ - Reduce manual sorting time and labor costs
876
+ - Educate people about proper waste segregation
877
+ - Provide environmental impact insights
878
+
879
+ #### 🤖 Technology Stack
880
+ - **Deep Learning Framework:** TensorFlow 2.15 / Keras
881
+ - **Model Architecture:** EfficientNetB0 (Transfer Learning)
882
+ - **Frontend:** Streamlit 1.28
883
+ - **Data Processing:** NumPy, Pandas, OpenCV
884
+ - **Visualization:** Plotly, Matplotlib, Seaborn
885
+
886
+ #### 📊 Dataset
887
+ - **Source:** TrashNet / Garbage Classification Dataset
888
+ - **Total Images:** 2,532
889
+ - **Classes:** 6 waste categories
890
+ - **Split:** 80% Training (2,027) | 20% Validation (505)
891
+
892
+ #### 🏆 Model Performance
893
+ - **Accuracy:** 83.2%
894
+ - **Precision:** 84.0%
895
+ - **Recall:** 83.0%
896
+ - **F1-Score:** 83.0%
897
+ """)
898
+
899
+ st.markdown('</div>', unsafe_allow_html=True)
900
+
901
+ # Class Information
902
+ st.markdown('<div class="card">', unsafe_allow_html=True)
903
+ st.markdown("### 🗑️ Waste Classes Information")
904
+
905
+ for class_name in class_labels:
906
+ info = recycling_info[class_name]
907
+ with st.expander(f"{info['icon']} {class_name.capitalize()} - {info['type']}"):
908
+ col_a, col_b = st.columns(2)
909
+ with col_a:
910
+ st.markdown(f"**♻️ Recyclable:** {info['recyclable']}")
911
+ st.markdown(f"**🗑️ Bin Color:** {info['bin_color']}")
912
+ st.markdown(f"**🔧 Processing:** {info['processing']}")
913
+ with col_b:
914
+ st.markdown(f"**📌 Fact:** {info['facts']}")
915
+ st.markdown(f"**💡 Tip:** {info['tips']}")
916
+
917
+ st.markdown('</div>', unsafe_allow_html=True)
918
+
919
+ # Environmental Impact
920
+ st.markdown('<div class="card">', unsafe_allow_html=True)
921
+ st.markdown("### 🌍 Environmental Impact")
922
+
923
+ impact_data = {
924
+ 'Category': ['CO₂ Reduction (kg/kg)', 'Energy Savings (%)', 'Water Saved (L/kg)', 'Trees Saved (per kg)'],
925
+ 'Cardboard': [2.0, 75, 100, 0.5],
926
+ 'Glass': [3.5, 60, 50, 0],
927
+ 'Metal': [4.0, 95, 75, 0],
928
+ 'Paper': [2.5, 70, 150, 1.0],
929
+ 'Plastic': [1.5, 80, 25, 0],
930
+ 'Trash': [0.5, 0, 10, 0]
931
+ }
932
+
933
+ impact_df = pd.DataFrame(impact_data)
934
+ st.dataframe(impact_df.style.highlight_max(color='lightgreen'), use_container_width=True)
935
+
936
+ st.markdown('</div>', unsafe_allow_html=True)
937
+
938
+ # Team Info
939
+ st.markdown('<div class="card">', unsafe_allow_html=True)
940
+ st.markdown("### 👥 Project Team")
941
+
942
+ col1, col2, col3 = st.columns(3)
943
+ with col1:
944
+ st.markdown("""
945
+ <div style='text-align: center; padding: 20px;'>
946
+ <h3>🧑‍💻 Data Scientist</h3>
947
+ <p>Model Development & Training</p>
948
+ </div>
949
+ """, unsafe_allow_html=True)
950
+
951
+ with col2:
952
+ st.markdown("""
953
+ <div style='text-align: center; padding: 20px;'>
954
+ <h3>🎨 UI/UX Designer</h3>
955
+ <p>Streamlit App Development</p>
956
+ </div>
957
+ """, unsafe_allow_html=True)
958
+
959
+ with col3:
960
+ st.markdown("""
961
+ <div style='text-align: center; padding: 20px;'>
962
+ <h3>🔬 Domain Expert</h3>
963
+ <p>Waste Management Specialist</p>
964
+ </div>
965
+ """, unsafe_allow_html=True)
966
+
967
+ st.markdown('</div>', unsafe_allow_html=True)
968
+
969
+ # ==================== PAGE 4: SETTINGS ====================
970
+ elif page == "⚙️ Settings":
971
+ st.markdown('<div class="card">', unsafe_allow_html=True)
972
+ st.markdown("### ⚙️ Application Settings")
973
+
974
+ # Model settings
975
+ st.markdown("#### 🤖 Model Configuration")
976
+
977
+ conf_threshold = st.slider(
978
+ "Confidence Threshold (%)",
979
+ min_value=0,
980
+ max_value=100,
981
+ value=50,
982
+ help="Minimum confidence for classification"
983
+ )
984
+
985
+ top_k = st.slider(
986
+ "Top-K Predictions",
987
+ min_value=1,
988
+ max_value=6,
989
+ value=3,
990
+ help="Number of top predictions to show"
991
+ )
992
+
993
+ # Display settings
994
+ st.markdown("#### 🎨 Display Settings")
995
+
996
+ theme = st.selectbox(
997
+ "Theme",
998
+ ["Light", "Dark", "System Default"],
999
+ help="Choose application theme"
1000
+ )
1001
+
1002
+ chart_style = st.selectbox(
1003
+ "Chart Style",
1004
+ ["Modern", "Classic", "Minimalist"],
1005
+ help="Choose chart visualization style"
1006
+ )
1007
+
1008
+ # Notification settings
1009
+ st.markdown("#### 🔔 Notifications")
1010
+
1011
+ show_tips = st.checkbox("Show recycling tips", value=True)
1012
+ show_facts = st.checkbox("Show environmental facts", value=True)
1013
+ show_impact = st.checkbox("Show impact metrics", value=True)
1014
+
1015
+ # Advanced settings
1016
+ st.markdown("#### 🔧 Advanced Settings")
1017
+
1018
+ batch_size = st.number_input("Batch Size", min_value=1, max_value=32, value=1)
1019
+ use_gpu = st.checkbox("Use GPU if available", value=True)
1020
+
1021
+ # Save settings button
1022
+ if st.button("💾 Save Settings", use_container_width=True):
1023
+ st.success("✅ Settings saved successfully!")
1024
+
1025
+ st.markdown('</div>', unsafe_allow_html=True)
1026
+
1027
+ # About the model
1028
+ st.markdown('<div class="card">', unsafe_allow_html=True)
1029
+ st.markdown("### 📊 Model Details")
1030
+
1031
+ st.markdown("""
1032
+ **Model Architecture:** EfficientNetB0
1033
+ - **Input Shape:** 224 × 224 × 3
1034
+ - **Total Parameters:** 4,384,169
1035
+ - **Trainable Parameters:** 332,038
1036
+ - **Non-trainable Parameters:** 4,052,131
1037
+
1038
+ **Training Configuration:**
1039
+ - **Optimizer:** Adam (lr=0.001)
1040
+ - **Loss Function:** Categorical Crossentropy
1041
+ - **Batch Size:** 32
1042
+ - **Epochs:** 25 (with early stopping)
1043
+ - **Class Weights:** Balanced
1044
+
1045
+ **Data Augmentation:**
1046
+ - Rotation Range: 25°
1047
+ - Zoom Range: 20%
1048
+ - Width/Height Shift: 20%
1049
+ - Horizontal Flip: Yes
1050
+ """)
1051
+
1052
+ st.markdown('</div>', unsafe_allow_html=True)
1053
+
1054
+ # Footer
1055
+ st.markdown("""
1056
+ <div class="footer">
1057
+ <p style='font-size: 1.2rem; margin-bottom: 10px;'>♻️ RecycleVision - Making Waste Management Smarter</p>
1058
+ <p style='font-size: 0.9rem; opacity: 0.9;'>
1059
+ © 2024 | Deep Learning Project | EfficientNetB0 | 84% Accuracy<br>
1060
+ <small>Every classification helps build a cleaner tomorrow</small>
1061
+ </p>
1062
+ </div>
1063
+ """, unsafe_allow_html=True)
1064
+
1065
+ # Sidebar footer
1066
+ st.sidebar.markdown("---")
1067
+ st.sidebar.markdown("""
1068
+ <div style='text-align: center; padding: 10px; background-color: #f0f0f0; border-radius: 10px;'>
1069
+ <p style='margin: 0;'><strong>♻️ RecycleVision v2.0</strong></p>
1070
+ <p style='margin: 0; font-size: 0.8rem;'>AI-Powered Waste Classification</p>
1071
+ </div>
1072
+ """, unsafe_allow_html=True)
1073
+
1074
+ # Initialize session state
1075
+ if 'classified' not in st.session_state:
1076
+ st.session_state['classified'] = False
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ streamlit==1.28.0
2
+ tensorflow==2.16.1
3
+ numpy==1.26.4
4
+ pandas==2.2.3
5
+ Pillow==10.4.0
6
+ opencv-python-headless==4.10.0.84
7
+ matplotlib==3.10.1
8
+ seaborn==0.13.2
9
+ plotly==5.24.1
10
+ scikit-learn==1.6.1