AymanFahim commited on
Commit
4bc7c48
·
verified ·
1 Parent(s): aab199a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +169 -50
app.py CHANGED
@@ -1,68 +1,187 @@
1
  import gradio as gr
2
  from ultralytics import YOLO
3
  import PIL.Image
 
 
4
 
5
- # Load your model
6
  model = YOLO('best.pt')
7
 
8
- def process_multiple_images(file_paths):
9
  """
10
- This function now accepts a LIST of file paths,
11
- loops through them, and combines the results.
 
 
 
 
 
12
  """
13
- if not file_paths:
14
- return [], "No files uploaded."
15
-
16
- gallery_images = []
17
- all_detected_ingredients = set()
18
-
19
- # Loop through every image uploaded
20
- for image_path in file_paths:
21
- # Run the model on this specific image
22
- # Using conf=0.5 as a balanced starting point
23
- results = model.predict(source=image_path, conf=0.5, iou=0.3, imgsz=640)
24
 
25
- # 1. Process the Image (Draw boxes)
26
- res_plotted = results[0].plot()
27
- # Convert BGR (OpenCV) to RGB (Gradio/PIL)
28
- res_rgb = res_plotted[..., ::-1]
29
- pil_img = PIL.Image.fromarray(res_rgb)
30
 
31
- # Add to our list of images to display
32
- gallery_images.append(pil_img)
33
 
34
- # 2. Extract Ingredients
 
 
 
35
  for box in results[0].boxes:
36
- cls_id = int(box.cls)
37
- name = model.names[cls_id]
38
- all_detected_ingredients.add(name)
39
-
40
- # Create a master list of unique ingredients found across ALL photos
41
- master_list_text = ", ".join(all_detected_ingredients)
42
- if not master_list_text:
43
- master_list_text = "No ingredients detected."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
- return gallery_images, master_list_text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
- # Build the Interface
48
- demo = gr.Interface(
49
- fn=process_multiple_images,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
 
51
- # INPUT CHANGE: Use gr.File allows selecting multiple files at once
52
- inputs=gr.File(
53
- file_count="multiple",
54
- file_types=["image"],
55
- label="Upload Multiple Photos (Fridge & Pantry)"
56
- ),
57
 
58
- # OUTPUT CHANGE: Use gr.Gallery to show a carousel of images
59
- outputs=[
60
- gr.Gallery(label="Processed Images", columns=2),
61
- gr.Textbox(label="Master Ingredient List")
62
- ],
 
63
 
64
- title="Bulk Ingredient Scanner",
65
- description="Upload multiple photos at once. The AI will combine all ingredients into one list."
66
- )
 
 
 
 
 
67
 
68
- demo.launch()
 
 
 
1
  import gradio as gr
2
  from ultralytics import YOLO
3
  import PIL.Image
4
+ import numpy as np
5
+ from typing import List, Tuple
6
 
7
+ # Load the trained model
8
  model = YOLO('best.pt')
9
 
10
+ def detect_ingredients(images: List) -> Tuple[List, str]:
11
  """
12
+ Process multiple images and return detected ingredients.
13
+
14
+ Args:
15
+ images: List of uploaded images (file paths)
16
+
17
+ Returns:
18
+ Tuple of (processed_images, ingredient_list_text)
19
  """
20
+ if not images or len(images) == 0:
21
+ return [], "**No images uploaded.**"
22
+
23
+ processed_images = []
24
+ all_detected_items = set()
25
+
26
+ # Process each uploaded image
27
+ for image_file in images:
28
+ if image_file is None:
29
+ continue
 
30
 
31
+ # Get file path (Gradio File component returns file objects)
32
+ image_path = image_file.name if hasattr(image_file, 'name') else image_file
 
 
 
33
 
34
+ # Run prediction with your local settings (conf=0.7)
35
+ results = model.predict(source=image_path, conf=0.7, iou=0.3, verbose=False)
36
 
37
+ # Get the image with bounding boxes drawn
38
+ result_image = results[0].plot()
39
+
40
+ # Extract detected ingredients from this image
41
  for box in results[0].boxes:
42
+ class_id = int(box.cls)
43
+ class_name = model.names[class_id]
44
+ all_detected_items.add(class_name)
45
+
46
+ # Convert numpy array to PIL Image for display
47
+ # YOLO returns BGR, convert to RGB
48
+ if len(result_image.shape) == 3:
49
+ result_image_rgb = result_image[..., ::-1] # BGR to RGB
50
+ processed_images.append(PIL.Image.fromarray(result_image_rgb))
51
+ else:
52
+ processed_images.append(PIL.Image.fromarray(result_image))
53
+
54
+ # Create formatted ingredient list
55
+ if all_detected_items:
56
+ ingredient_list = sorted(list(all_detected_items))
57
+ ingredient_list_text = "**Detected Ingredients:**\n\n"
58
+ ingredient_list_text += "\n".join([f"• {item.capitalize()}" for item in ingredient_list])
59
+ ingredient_list_text += f"\n\n**Total unique items:** {len(ingredient_list)}"
60
+ else:
61
+ ingredient_list_text = "**No ingredients detected.**\n\nTry adjusting the image quality or lighting."
62
+
63
+ return processed_images, ingredient_list_text
64
 
65
+ # Custom CSS for a modern, clean interface
66
+ custom_css = """
67
+ .gradio-container {
68
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
69
+ }
70
+ .main-header {
71
+ text-align: center;
72
+ padding: 20px;
73
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
74
+ color: white;
75
+ border-radius: 10px;
76
+ margin-bottom: 20px;
77
+ }
78
+ .description-box {
79
+ background: #f8f9fa;
80
+ padding: 15px;
81
+ border-radius: 8px;
82
+ border-left: 4px solid #667eea;
83
+ margin-bottom: 20px;
84
+ color: #000000 !important;
85
+ }
86
+ .description-box * {
87
+ color: #000000 !important;
88
+ }
89
+ .ingredient-list {
90
+ background: #ffffff;
91
+ padding: 20px;
92
+ border-radius: 8px;
93
+ box-shadow: 0 2px 8px rgba(0,0,0,0.1);
94
+ min-height: 200px;
95
+ color: #000000 !important;
96
+ }
97
+ .ingredient-list * {
98
+ color: #000000 !important;
99
+ }
100
+ .ingredient-list p, .ingredient-list strong {
101
+ color: #000000 !important;
102
+ }
103
+ """
104
 
105
+ # Create the Gradio interface
106
+ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
107
+ gr.Markdown(
108
+ """
109
+ # 🥗 Fridge Ingredient Scanner
110
+
111
+ Upload photos of your fridge, pantry, or groceries to automatically detect ingredients!
112
+ """,
113
+ elem_classes=["main-header"]
114
+ )
115
+
116
+ gr.Markdown(
117
+ """
118
+ <div class="description-box">
119
+ <strong>📸 How to use:</strong><br>
120
+ 1. Click "Upload Images" or drag and drop multiple photos<br>
121
+ 2. Wait for the AI to analyze your ingredients<br>
122
+ 3. View all processed images with detection boxes and the complete ingredient list
123
+ </div>
124
+ """,
125
+ elem_classes=["description-box"]
126
+ )
127
+
128
+ with gr.Row():
129
+ with gr.Column(scale=1):
130
+ image_input = gr.File(
131
+ file_count="multiple",
132
+ file_types=["image"],
133
+ label="📁 Upload Images",
134
+ height=200
135
+ )
136
+
137
+ process_btn = gr.Button(
138
+ "🔍 Detect Ingredients",
139
+ variant="primary",
140
+ size="lg"
141
+ )
142
+
143
+ gr.Markdown("---")
144
+
145
+ ingredient_output = gr.Markdown(
146
+ label="📋 Detected Ingredients",
147
+ elem_classes=["ingredient-list"]
148
+ )
149
+
150
+ with gr.Column(scale=2):
151
+ gallery_output = gr.Gallery(
152
+ label="🖼️ Processed Images with Detections",
153
+ show_label=True,
154
+ elem_id="gallery",
155
+ columns=2,
156
+ rows=2,
157
+ height="auto",
158
+ allow_preview=True,
159
+ preview=True
160
+ )
161
 
162
+ # Process images when button is clicked
163
+ process_btn.click(
164
+ fn=detect_ingredients,
165
+ inputs=image_input,
166
+ outputs=[gallery_output, ingredient_output]
167
+ )
168
 
169
+ # Also process when images are uploaded (auto-detect)
170
+ image_input.upload(
171
+ fn=detect_ingredients,
172
+ inputs=image_input,
173
+ outputs=[gallery_output, ingredient_output]
174
+ )
175
 
176
+ gr.Markdown(
177
+ """
178
+ ---
179
+ <div style="text-align: center; color: #666; padding: 20px;">
180
+ <small>Powered by YOLOv11 | Upload multiple images to scan your entire fridge!</small>
181
+ </div>
182
+ """
183
+ )
184
 
185
+ # Launch the app
186
+ if __name__ == "__main__":
187
+ demo.launch()