omasteam commited on
Commit
c27dc96
·
verified ·
1 Parent(s): f3e492f

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +208 -0
app.py ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ from transformers import AutoImageProcessor, AutoModelForImageClassification
4
+ from PIL import Image
5
+ import requests
6
+ from io import BytesIO
7
+ import datetime
8
+ import random
9
+
10
+ # Load a pretrained model from Hugging Face Hub
11
+ model_name = "google/vit-base-patch16-224" # You can replace this with a food-specific model
12
+ processor = AutoImageProcessor.from_pretrained(model_name)
13
+ model = AutoModelForImageClassification.from_pretrained(model_name)
14
+
15
+ # Map model outputs to food categories (this would need adjustment based on your specific model)
16
+ food_categories = {
17
+ 0: "fresh_fruits",
18
+ 1: "fresh_vegetables",
19
+ 2: "spoiled_fruits",
20
+ 3: "spoiled_vegetables",
21
+ 4: "dairy",
22
+ 5: "bakery",
23
+ 6: "meat",
24
+ 7: "other"
25
+ }
26
+
27
+ # Recipe database
28
+ def get_recipes(food_category, freshness):
29
+ recipes = {
30
+ 'fresh_fruits': {
31
+ 'fresh': ["Fresh Fruit Salad", "Fruit Smoothie", "Fruit Parfait"],
32
+ 'moderate': ["Baked Fruits", "Fruit Compote", "Fruit Crumble"],
33
+ 'aging': ["Fruit Jam", "Fruit Puree", "Infused Water"],
34
+ 'spoiled': ["Compost", "Dispose responsibly"]
35
+ },
36
+ 'fresh_vegetables': {
37
+ 'fresh': ["Fresh Salad", "Vegetable Stir-fry", "Crudités"],
38
+ 'moderate': ["Roasted Vegetables", "Vegetable Soup", "Steamed Vegetables"],
39
+ 'aging': ["Vegetable Stock", "Compost", "Puree for Soups"],
40
+ 'spoiled': ["Compost", "Dispose responsibly"]
41
+ },
42
+ 'dairy': {
43
+ 'fresh': ["Yogurt Parfait", "Cheese Plate", "Milk-based Smoothie"],
44
+ 'moderate': ["Yogurt Marinade", "Pancakes", "Custard"],
45
+ 'aging': ["Yogurt Cheese", "Baking buttermilk", "Cultured butter"],
46
+ 'spoiled': ["Dispose responsibly", "Not recommended for consumption"]
47
+ },
48
+ 'bakery': {
49
+ 'fresh': ["Fresh Bread with Olive Oil", "Sandwiches", "Bread with Soup"],
50
+ 'moderate': ["Croutons", "Bread Pudding", "French Toast"],
51
+ 'aging': ["Bread Crumbs", "Bread-based Stuffing", "Bread Salad"],
52
+ 'spoiled': ["Compost", "Bird Feed", "Dispose responsibly"]
53
+ },
54
+ 'meat': {
55
+ 'fresh': ["Grilled Meat", "Stew", "Stir-fry"],
56
+ 'moderate': ["Slow-cooked Dish", "Meat Sauce", "Pot Pie"],
57
+ 'aging': ["Not recommended for consumption", "Dispose responsibly"],
58
+ 'spoiled': ["Dispose responsibly", "Not safe for consumption"]
59
+ },
60
+ 'other': {
61
+ 'fresh': ["Use soon", "Store properly"],
62
+ 'moderate': ["Consider using in cooked dishes", "Check for signs of spoilage"],
63
+ 'aging': ["Compost if possible", "Dispose responsibly"],
64
+ 'spoiled': ["Dispose responsibly", "Not safe for consumption"]
65
+ }
66
+ }
67
+
68
+ return recipes.get(food_category, {}).get(freshness, ["No recipes available"])
69
+
70
+ # Waste log
71
+ waste_log = []
72
+
73
+ def predict_image(image):
74
+ # Preprocess the image
75
+ inputs = processor(images=image, return_tensors="pt")
76
+
77
+ # Make prediction
78
+ with torch.no_grad():
79
+ outputs = model(**inputs)
80
+ logits = outputs.logits
81
+ predicted_class_idx = logits.argmax(-1).item()
82
+
83
+ # Get confidence scores
84
+ probabilities = torch.nn.functional.softmax(logits, dim=1)[0]
85
+ confidence_score = probabilities[predicted_class_idx].item()
86
+
87
+ # Map to food category (this is a simplification - you'd need to adjust based on your model)
88
+ food_category = food_categories.get(predicted_class_idx % len(food_categories), "other")
89
+
90
+ # Determine freshness based on confidence and category (this is a heuristic)
91
+ if confidence_score > 0.8:
92
+ freshness = 'fresh'
93
+ days_remaining = random.randint(3, 7)
94
+ elif confidence_score > 0.5:
95
+ freshness = 'moderate'
96
+ days_remaining = random.randint(1, 3)
97
+ else:
98
+ freshness = 'aging'
99
+ days_remaining = random.randint(0, 1)
100
+
101
+ # Special handling for categories that might indicate spoilage
102
+ if 'spoiled' in food_category:
103
+ freshness = 'spoiled'
104
+ days_remaining = 0
105
+
106
+ # Get recipe suggestions
107
+ recipes = get_recipes(food_category, freshness)
108
+
109
+ # Format results
110
+ result_html = f"""
111
+ <div style='padding: 10px; border-radius: 5px; background-color: #f0f8ff; margin-bottom: 10px;'>
112
+ <h3>Analysis Results</h3>
113
+ <p><b>Category:</b> {food_category.replace('_', ' ').title()}</p>
114
+ <p><b>Freshness:</b> {freshness.title()}</p>
115
+ <p><b>Confidence:</b> {confidence_score*100:.1f}%</p>
116
+ <p><b>Days Remaining:</b> {days_remaining}</p>
117
+ </div>
118
+ """
119
+
120
+ # Format recipes
121
+ recipes_html = "<h3>Recipe Suggestions</h3><ul>"
122
+ for recipe in recipes:
123
+ recipes_html += f"<li>{recipe}</li>"
124
+ recipes_html += "</ul>"
125
+
126
+ # Environmental impact
127
+ impact_html = f"""
128
+ <div style='padding: 10px; border-radius: 5px; background-color: #e8f5e9; margin-top: 10px;'>
129
+ <h3>Environmental Impact</h3>
130
+ <p>By properly managing this {food_category.replace('_', ' ')}, you could save approximately {random.uniform(0.1, 0.5):.2f} kg CO2 emissions.</p>
131
+ <p>Consider composting if the food is no longer edible.</p>
132
+ </div>
133
+ """
134
+
135
+ # Add to waste log
136
+ waste_log.append({
137
+ "item": food_category.replace('_', ' ').title(),
138
+ "category": food_category,
139
+ "date": datetime.datetime.now().strftime("%Y-%m-%d"),
140
+ "freshness": freshness,
141
+ "action": "analyzed",
142
+ "confidence": f"{confidence_score*100:.1f}%"
143
+ })
144
+
145
+ return result_html + recipes_html + impact_html
146
+
147
+ def update_waste_log():
148
+ if not waste_log:
149
+ return "<h3>No waste entries yet. Upload an image to get started!</h3>"
150
+
151
+ log_html = "<h3>Recent Waste Log</h3><table style='width:100%; border-collapse: collapse;'>"
152
+ log_html += "<tr style='background-color: #f2f2f2;'><th>Item</th><th>Category</th><th>Date</th><th>Freshness</th><th>Confidence</th></tr>"
153
+
154
+ for entry in waste_log[-5:]: # Show last 5 entries
155
+ log_html += f"<tr><td>{entry['item']}</td><td>{entry['category']}</td><td>{entry['date']}</td><td>{entry['freshness']}</td><td>{entry['confidence']}</td></tr>"
156
+
157
+ log_html += "</table>"
158
+
159
+ # Statistics
160
+ fresh_count = sum(1 for entry in waste_log if entry['freshness'] == 'fresh')
161
+ moderate_count = sum(1 for entry in waste_log if entry['freshness'] == 'moderate')
162
+ aging_count = sum(1 for entry in waste_log if entry['freshness'] == 'aging')
163
+ spoiled_count = sum(1 for entry in waste_log if entry['freshness'] == 'spoiled')
164
+
165
+ stats_html = f"""
166
+ <div style='margin-top: 20px;'>
167
+ <h3>Waste Statistics</h3>
168
+ <p>Fresh Items: {fresh_count}</p>
169
+ <p>Moderate Freshness: {moderate_count}</p>
170
+ <p>Aging Items: {aging_count}</p>
171
+ <p>Spoiled Items: {spoiled_count}</p>
172
+ </div>
173
+ """
174
+
175
+ return log_html + stats_html
176
+
177
+ # Create Gradio interface
178
+ with gr.Blocks(title="Food Waste Manager", theme=gr.themes.Soft()) as demo:
179
+ gr.Markdown("# 🍃 Smart Food Waste Manager")
180
+ gr.Markdown("Upload an image of food to analyze its freshness and get recipe suggestions to reduce waste!")
181
+
182
+ with gr.Row():
183
+ with gr.Column():
184
+ image_input = gr.Image(label="Upload Food Image", type="pil")
185
+ analyze_btn = gr.Button("Analyze Food", variant="primary")
186
+
187
+ with gr.Column():
188
+ analysis_output = gr.HTML(label="Analysis Results")
189
+
190
+ with gr.Row():
191
+ waste_log_output = gr.HTML()
192
+
193
+ # Set up event handlers
194
+ analyze_btn.click(
195
+ fn=predict_image,
196
+ inputs=image_input,
197
+ outputs=analysis_output
198
+ ).then(
199
+ fn=update_waste_log,
200
+ inputs=None,
201
+ outputs=waste_log_output
202
+ )
203
+
204
+ # Initialize waste log
205
+ demo.load(update_waste_log, None, waste_log_output)
206
+
207
+ if __name__ == "__main__":
208
+ demo.launch()