Rudra-barman commited on
Commit
f43b048
·
verified ·
1 Parent(s): 6fc6cd2

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -1076
app.py DELETED
@@ -1,1076 +0,0 @@
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