Subham9126 commited on
Commit
71b9600
Β·
verified Β·
1 Parent(s): 74c7568

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +90 -80
app.py CHANGED
@@ -1,4 +1,5 @@
1
  # app.py
 
2
  import gradio as gr
3
  import numpy as np
4
  import cv2
@@ -7,24 +8,20 @@ import json
7
  import time
8
  from ultralytics import YOLO
9
  import torch
10
- from typing import List, Dict, Tuple, Optional
11
- import base64
12
- import io
13
  import os
14
 
15
- # Do NOT try to write to ~/.config/Ultralytics on HF Spaces
16
- os.environ["YOLO_CONFIG_DIR"] = "/tmp"
17
 
18
- # Global variables
19
  model = None
20
 
21
- # Selection Manager class
22
  class SelectionManager:
23
  def __init__(self):
24
  self.selections = []
25
  self.next_id = 0
26
  self.active_id = None
27
-
28
  def add_selection(self, x, y, width, height, selection_type="manual", label="", confidence=None):
29
  selection = {
30
  'id': self.next_id,
@@ -40,19 +37,19 @@ class SelectionManager:
40
  self.selections.append(selection)
41
  self.next_id += 1
42
  return selection['id']
43
-
44
  def remove_selection(self, selection_id):
45
  self.selections = [s for s in self.selections if s['id'] != selection_id]
46
  if self.active_id == selection_id:
47
  self.active_id = None
48
-
49
  def clear_all(self):
50
  self.selections = []
51
  self.active_id = None
52
-
53
  def clear_type(self, selection_type):
54
  self.selections = [s for s in self.selections if s['type'] != selection_type]
55
-
56
  def get_total_area(self, img_width, img_height):
57
  total_selected_area = sum(s['width'] * s['height'] for s in self.selections)
58
  total_image_area = img_width * img_height
@@ -61,34 +58,32 @@ class SelectionManager:
61
  # Initialize selection manager
62
  selection_manager = SelectionManager()
63
 
64
- # Load YOLO model
65
  def load_yolo_model():
66
  global model
67
  try:
68
- model = YOLO('yolov8n.pt')
69
  return "βœ… YOLO Model loaded successfully"
70
  except Exception as e:
71
  return f"❌ Error loading YOLO model: {str(e)}"
72
 
73
- # Detect objects
74
  def detect_objects(image, confidence_threshold=0.5, merge_with_existing=True):
75
  global model, selection_manager
76
-
77
  if model is None:
78
  return image, "❌ Model not loaded", get_analysis_text(image)
79
-
80
  if image is None:
81
  return None, "❌ No image provided", ""
82
-
83
  try:
84
  img_array = np.array(image)
 
85
  start_time = time.time()
86
  results = model(img_array, conf=confidence_threshold, verbose=False)
87
- detection_time = (time.time() - start_time) * 1000
88
-
89
  if not merge_with_existing:
90
  selection_manager.clear_type('yolo')
91
-
92
  detections_added = 0
93
  for result in results:
94
  boxes = result.boxes
@@ -98,7 +93,7 @@ def detect_objects(image, confidence_threshold=0.5, merge_with_existing=True):
98
  confidence = box.conf[0].cpu().numpy()
99
  class_id = int(box.cls[0].cpu().numpy())
100
  class_name = model.names[class_id]
101
-
102
  selection_manager.add_selection(
103
  x=int(x1),
104
  y=int(y1),
@@ -109,57 +104,60 @@ def detect_objects(image, confidence_threshold=0.5, merge_with_existing=True):
109
  confidence=confidence
110
  )
111
  detections_added += 1
112
-
113
  annotated_image = draw_selections(image)
114
  status_msg = f"βœ… Detected {detections_added} objects in {detection_time:.1f}ms"
115
  analysis_text = get_analysis_text(image)
116
  return annotated_image, status_msg, analysis_text
117
-
118
  except Exception as e:
119
  return image, f"❌ Detection error: {str(e)}", get_analysis_text(image)
120
 
121
- # Draw selections
122
  def draw_selections(image):
123
  if image is None:
124
  return None
125
-
126
  img_copy = image.copy()
127
  draw = ImageDraw.Draw(img_copy)
128
-
129
  try:
130
  font = ImageFont.truetype("arial.ttf", 12)
131
  except:
132
  font = ImageFont.load_default()
133
-
134
  for selection in selection_manager.selections:
135
  x, y, w, h = selection['x'], selection['y'], selection['width'], selection['height']
136
- outline_color = 'green' if selection['type'] == 'yolo' else 'blue'
137
- fill_color = (0, 255, 0, 60) if selection['type'] == 'yolo' else (0, 0, 255, 60)
138
-
 
 
 
 
 
139
  draw.rectangle([x, y, x + w, y + h], outline=outline_color, width=2)
140
-
141
  overlay = Image.new('RGBA', img_copy.size, (0, 0, 0, 0))
142
  overlay_draw = ImageDraw.Draw(overlay)
143
  overlay_draw.rectangle([x, y, x + w, y + h], fill=fill_color)
144
  img_copy = Image.alpha_composite(img_copy.convert('RGBA'), overlay).convert('RGB')
145
-
146
  if selection['label']:
147
  label_y = y - 15 if y > 15 else y + h + 5
148
  draw.text((x, label_y), selection['label'], fill=outline_color, font=font)
149
-
150
  return img_copy
151
 
152
- # Analysis text
153
  def get_analysis_text(image):
154
  if image is None:
155
  return "No image loaded"
156
-
157
  img_width, img_height = image.size
158
  total_selected_area, total_image_area = selection_manager.get_total_area(img_width, img_height)
159
-
160
  selected_percentage = (total_selected_area / total_image_area) * 100 if total_image_area > 0 else 0
161
  extra_percentage = 100 - selected_percentage
162
-
163
  analysis = f"""
164
  ## πŸ“Š Space Analysis
165
 
@@ -167,11 +165,10 @@ def get_analysis_text(image):
167
  **Total Selected Area:** {total_selected_area:,} pxΒ²
168
  **Selected Region:** {selected_percentage:.1f}% of total
169
  **Extra Space:** {extra_percentage:.1f}% of total
170
- **Number of Selections:** {len(selection_manager.selections)}
171
 
172
  ### πŸ“‹ Selection Details:
173
  """
174
-
175
  for i, selection in enumerate(selection_manager.selections, 1):
176
  area = selection['width'] * selection['height']
177
  analysis += f"""
@@ -180,35 +177,35 @@ def get_analysis_text(image):
180
  - Area: {area:,} pxΒ²
181
  - Dimensions: {selection['width']}Γ—{selection['height']}
182
  """
183
- if selection['confidence']:
184
  analysis += f"- Confidence: {selection['confidence']:.2f}\n"
185
-
186
  return analysis
187
 
188
- # Manual selection
189
  def add_manual_selection(image, selection_data):
190
  if image is None:
191
  return image, "❌ No image loaded", ""
192
-
193
  try:
194
  coords = [int(x.strip()) for x in selection_data.split(',')]
195
  if len(coords) != 4:
196
  raise ValueError("Invalid format")
197
-
198
  x, y, width, height = coords
 
199
  img_width, img_height = image.size
200
  if x < 0 or y < 0 or x + width > img_width or y + height > img_height:
201
  return image, "❌ Selection coordinates out of bounds", get_analysis_text(image)
202
-
203
- sel_id = selection_manager.add_selection(x, y, width, height, "manual", f"Manual {selection_manager.next_id}")
 
204
  annotated_image = draw_selections(image)
205
  analysis_text = get_analysis_text(image)
206
  return annotated_image, "βœ… Manual selection added", analysis_text
207
-
208
  except Exception as e:
209
  return image, f"❌ Error adding selection: {str(e)}", get_analysis_text(image)
210
 
211
- # Clear selections
212
  def clear_all_selections(image):
213
  selection_manager.clear_all()
214
  if image is not None:
@@ -229,41 +226,54 @@ def clear_manual_selections(image):
229
  return annotated_image, "βœ… Manual selections cleared", get_analysis_text(image)
230
  return None, "βœ… Manual selections cleared", ""
231
 
232
- # Process image upload
233
  def process_image_upload(image):
234
  if image is None:
235
  return None, "❌ No image uploaded", ""
236
-
237
  selection_manager.clear_all()
238
  analysis_text = get_analysis_text(image)
239
  return image, "βœ… Image loaded successfully", analysis_text
240
 
241
- # Gradio Interface
242
- with gr.Blocks(title="Image Space Analyzer with YOLO") as demo:
243
- gr.Markdown("# πŸ” Image Space Analyzer with YOLO")
244
- with gr.Row():
245
- with gr.Column(scale=2):
246
- image_input = gr.Image(type="pil", label="πŸ“Έ Upload Image", height=500)
247
- status_output = gr.Textbox(label="πŸ“‹ Status", interactive=False, max_lines=2)
248
- with gr.Column(scale=1):
249
- model_status = gr.Textbox(label="πŸ€– Model Status", value="Loading YOLO model...", interactive=False)
250
- confidence_slider = gr.Slider(0.1, 1.0, value=0.5, step=0.1, label="Confidence Threshold")
251
- merge_checkbox = gr.Checkbox(label="Merge with existing selections", value=True)
252
- detect_btn = gr.Button("πŸ” Detect Objects")
253
- manual_input = gr.Textbox(label="Selection (x,y,width,height)", placeholder="100,100,200,150")
254
- add_manual_btn = gr.Button("βž• Add Manual Selection")
255
- clear_all_btn = gr.Button("πŸ—‘οΈ Clear All")
256
- clear_yolo_btn = gr.Button("πŸ—‘οΈ Clear YOLO")
257
- clear_manual_btn = gr.Button("πŸ—‘οΈ Clear Manual")
258
-
259
- analysis_output = gr.Markdown(label="πŸ“Š Analysis Results")
260
-
261
- image_input.upload(process_image_upload, inputs=[image_input], outputs=[image_input, status_output, analysis_output])
262
- detect_btn.click(detect_objects, inputs=[image_input, confidence_slider, merge_checkbox], outputs=[image_input, status_output, analysis_output])
263
- add_manual_btn.click(add_manual_selection, inputs=[image_input, manual_input], outputs=[image_input, status_output, analysis_output])
264
- clear_all_btn.click(clear_all_selections, inputs=[image_input], outputs=[image_input, status_output, analysis_output])
265
- clear_yolo_btn.click(clear_yolo_selections, inputs=[image_input], outputs=[image_input, status_output, analysis_output])
266
- clear_manual_btn.click(clear_manual_selections, inputs=[image_input], outputs=[image_input], outputs=[image_input, status_output, analysis_output])
267
- demo.load(load_yolo_model, outputs=[model_status])
268
-
269
- # If you want to deploy in HF Spaces: Do NOT add `launch()` block! HF Spaces will auto launch this file.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # app.py
2
+
3
  import gradio as gr
4
  import numpy as np
5
  import cv2
 
8
  import time
9
  from ultralytics import YOLO
10
  import torch
 
 
 
11
  import os
12
 
13
+ # Fix Ultralytics config path for Hugging Face Spaces (read-only /home/user)
14
+ os.environ['YOLO_CONFIG_DIR'] = '/tmp'
15
 
16
+ # Global variables to maintain state
17
  model = None
18
 
 
19
  class SelectionManager:
20
  def __init__(self):
21
  self.selections = []
22
  self.next_id = 0
23
  self.active_id = None
24
+
25
  def add_selection(self, x, y, width, height, selection_type="manual", label="", confidence=None):
26
  selection = {
27
  'id': self.next_id,
 
37
  self.selections.append(selection)
38
  self.next_id += 1
39
  return selection['id']
40
+
41
  def remove_selection(self, selection_id):
42
  self.selections = [s for s in self.selections if s['id'] != selection_id]
43
  if self.active_id == selection_id:
44
  self.active_id = None
45
+
46
  def clear_all(self):
47
  self.selections = []
48
  self.active_id = None
49
+
50
  def clear_type(self, selection_type):
51
  self.selections = [s for s in self.selections if s['type'] != selection_type]
52
+
53
  def get_total_area(self, img_width, img_height):
54
  total_selected_area = sum(s['width'] * s['height'] for s in self.selections)
55
  total_image_area = img_width * img_height
 
58
  # Initialize selection manager
59
  selection_manager = SelectionManager()
60
 
 
61
  def load_yolo_model():
62
  global model
63
  try:
64
+ model = YOLO('yolov8n.pt') # This will download the model if not cached
65
  return "βœ… YOLO Model loaded successfully"
66
  except Exception as e:
67
  return f"❌ Error loading YOLO model: {str(e)}"
68
 
 
69
  def detect_objects(image, confidence_threshold=0.5, merge_with_existing=True):
70
  global model, selection_manager
 
71
  if model is None:
72
  return image, "❌ Model not loaded", get_analysis_text(image)
73
+
74
  if image is None:
75
  return None, "❌ No image provided", ""
76
+
77
  try:
78
  img_array = np.array(image)
79
+
80
  start_time = time.time()
81
  results = model(img_array, conf=confidence_threshold, verbose=False)
82
+ detection_time = (time.time() - start_time) * 1000 # ms
83
+
84
  if not merge_with_existing:
85
  selection_manager.clear_type('yolo')
86
+
87
  detections_added = 0
88
  for result in results:
89
  boxes = result.boxes
 
93
  confidence = box.conf[0].cpu().numpy()
94
  class_id = int(box.cls[0].cpu().numpy())
95
  class_name = model.names[class_id]
96
+
97
  selection_manager.add_selection(
98
  x=int(x1),
99
  y=int(y1),
 
104
  confidence=confidence
105
  )
106
  detections_added += 1
107
+
108
  annotated_image = draw_selections(image)
109
  status_msg = f"βœ… Detected {detections_added} objects in {detection_time:.1f}ms"
110
  analysis_text = get_analysis_text(image)
111
  return annotated_image, status_msg, analysis_text
112
+
113
  except Exception as e:
114
  return image, f"❌ Detection error: {str(e)}", get_analysis_text(image)
115
 
 
116
  def draw_selections(image):
117
  if image is None:
118
  return None
119
+
120
  img_copy = image.copy()
121
  draw = ImageDraw.Draw(img_copy)
122
+
123
  try:
124
  font = ImageFont.truetype("arial.ttf", 12)
125
  except:
126
  font = ImageFont.load_default()
127
+
128
  for selection in selection_manager.selections:
129
  x, y, w, h = selection['x'], selection['y'], selection['width'], selection['height']
130
+
131
+ if selection['type'] == 'yolo':
132
+ outline_color = 'green'
133
+ fill_color = (0, 255, 0, 60)
134
+ else:
135
+ outline_color = 'blue'
136
+ fill_color = (0, 0, 255, 60)
137
+
138
  draw.rectangle([x, y, x + w, y + h], outline=outline_color, width=2)
139
+
140
  overlay = Image.new('RGBA', img_copy.size, (0, 0, 0, 0))
141
  overlay_draw = ImageDraw.Draw(overlay)
142
  overlay_draw.rectangle([x, y, x + w, y + h], fill=fill_color)
143
  img_copy = Image.alpha_composite(img_copy.convert('RGBA'), overlay).convert('RGB')
144
+
145
  if selection['label']:
146
  label_y = y - 15 if y > 15 else y + h + 5
147
  draw.text((x, label_y), selection['label'], fill=outline_color, font=font)
148
+
149
  return img_copy
150
 
 
151
  def get_analysis_text(image):
152
  if image is None:
153
  return "No image loaded"
154
+
155
  img_width, img_height = image.size
156
  total_selected_area, total_image_area = selection_manager.get_total_area(img_width, img_height)
157
+
158
  selected_percentage = (total_selected_area / total_image_area) * 100 if total_image_area > 0 else 0
159
  extra_percentage = 100 - selected_percentage
160
+
161
  analysis = f"""
162
  ## πŸ“Š Space Analysis
163
 
 
165
  **Total Selected Area:** {total_selected_area:,} pxΒ²
166
  **Selected Region:** {selected_percentage:.1f}% of total
167
  **Extra Space:** {extra_percentage:.1f}% of total
168
+ **Number of Selections:** {len(selection_manager.selections)}
169
 
170
  ### πŸ“‹ Selection Details:
171
  """
 
172
  for i, selection in enumerate(selection_manager.selections, 1):
173
  area = selection['width'] * selection['height']
174
  analysis += f"""
 
177
  - Area: {area:,} pxΒ²
178
  - Dimensions: {selection['width']}Γ—{selection['height']}
179
  """
180
+ if selection['confidence'] is not None:
181
  analysis += f"- Confidence: {selection['confidence']:.2f}\n"
182
+
183
  return analysis
184
 
 
185
  def add_manual_selection(image, selection_data):
186
  if image is None:
187
  return image, "❌ No image loaded", ""
188
+
189
  try:
190
  coords = [int(x.strip()) for x in selection_data.split(',')]
191
  if len(coords) != 4:
192
  raise ValueError("Invalid format")
193
+
194
  x, y, width, height = coords
195
+
196
  img_width, img_height = image.size
197
  if x < 0 or y < 0 or x + width > img_width or y + height > img_height:
198
  return image, "❌ Selection coordinates out of bounds", get_analysis_text(image)
199
+
200
+ sel_id = selection_manager.add_selection(x, y, width, height, "manual", f"Manual Selection {selection_manager.next_id}")
201
+
202
  annotated_image = draw_selections(image)
203
  analysis_text = get_analysis_text(image)
204
  return annotated_image, "βœ… Manual selection added", analysis_text
205
+
206
  except Exception as e:
207
  return image, f"❌ Error adding selection: {str(e)}", get_analysis_text(image)
208
 
 
209
  def clear_all_selections(image):
210
  selection_manager.clear_all()
211
  if image is not None:
 
226
  return annotated_image, "βœ… Manual selections cleared", get_analysis_text(image)
227
  return None, "βœ… Manual selections cleared", ""
228
 
 
229
  def process_image_upload(image):
230
  if image is None:
231
  return None, "❌ No image uploaded", ""
232
+
233
  selection_manager.clear_all()
234
  analysis_text = get_analysis_text(image)
235
  return image, "βœ… Image loaded successfully", analysis_text
236
 
237
+ # Gradio interface
238
+ def create_interface():
239
+ with gr.Blocks(title="Image Space Analyzer with YOLO") as demo:
240
+ gr.Markdown("# πŸ” Image Space Analyzer with YOLO")
241
+
242
+ with gr.Row():
243
+ with gr.Column(scale=2):
244
+ image_input = gr.Image(type="pil", label="πŸ“Έ Upload Image", height=500)
245
+ status_output = gr.Textbox(label="πŸ“‹ Status", interactive=False, max_lines=2)
246
+ with gr.Column(scale=1):
247
+ model_status = gr.Textbox(label="πŸ€– Model Status", value="Loading YOLO model...", interactive=False)
248
+
249
+ gr.Markdown("### 🎯 YOLO Object Detection")
250
+ confidence_slider = gr.Slider(minimum=0.1, maximum=1.0, value=0.5, step=0.1, label="Confidence Threshold")
251
+ merge_checkbox = gr.Checkbox(label="Merge with existing selections", value=True)
252
+ detect_btn = gr.Button("πŸ” Detect Objects", variant="primary")
253
+
254
+ gr.Markdown("### ✏️ Manual Selection")
255
+ manual_input = gr.Textbox(label="Selection (x,y,width,height)", placeholder="100,100,200,150", info="Enter coordinates separated by commas")
256
+ add_manual_btn = gr.Button("βž• Add Manual Selection")
257
+
258
+ gr.Markdown("### πŸ—‚οΈ Selection Management")
259
+ clear_all_btn = gr.Button("πŸ—‘οΈ Clear All", variant="secondary")
260
+ clear_yolo_btn = gr.Button("πŸ—‘οΈ Clear YOLO")
261
+ clear_manual_btn = gr.Button("πŸ—‘οΈ Clear Manual")
262
+
263
+ analysis_output = gr.Markdown(label="πŸ“Š Analysis Results")
264
+
265
+ image_input.upload(process_image_upload, inputs=[image_input], outputs=[image_input, status_output, analysis_output])
266
+ detect_btn.click(detect_objects, inputs=[image_input, confidence_slider, merge_checkbox], outputs=[image_input, status_output, analysis_output])
267
+ add_manual_btn.click(add_manual_selection, inputs=[image_input, manual_input], outputs=[image_input, status_output, analysis_output])
268
+ clear_all_btn.click(clear_all_selections, inputs=[image_input], outputs=[image_input, status_output, analysis_output])
269
+ clear_yolo_btn.click(clear_yolo_selections, inputs=[image_input], outputs=[image_input, status_output, analysis_output])
270
+ clear_manual_btn.click(clear_manual_selections, inputs=[image_input], outputs=[image_input, status_output, analysis_output])
271
+
272
+ demo.load(load_yolo_model, outputs=[model_status])
273
+
274
+ return demo
275
+
276
+ if __name__ == "__main__":
277
+ print("πŸš€ Starting Image Space Analyzer on Hugging Face Spaces...")
278
+ demo = create_interface()
279
+ demo.launch(server_name="0.0.0.0", server_port=7860, share=False)