Manvikk commited on
Commit
d6f9a3b
·
verified ·
1 Parent(s): 0a93b23

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +115 -78
app.py CHANGED
@@ -15,21 +15,30 @@ app.secret_key = 'your_secret_key' # Replace with a secure secret key
15
  #########################################
16
 
17
  # --- Roboflow Box Detection Model ---
18
- API_KEY = "wLjPoPYaLmrqCIOFA0RH" # Replace with your actual API key
19
- PROJECT_ID = "base-model-box-r4suo-8lkk1-6dbqh" # Replace with your Roboflow project ID
20
- VERSION_NUMBER = "2" # Replace with your trained model version number
21
 
22
- rf = roboflow.Roboflow(api_key=API_KEY)
23
- workspace = rf.workspace()
24
- project = workspace.project(PROJECT_ID)
25
- version = project.version(VERSION_NUMBER)
26
- box_model = version.model # This model is trained for detecting boxes
 
 
 
 
 
27
 
28
  # --- YOLOv5 Pretrained Model for Persons & Cars ---
29
- # Using Ultralytics YOLOv5s (pretrained) from Torch Hub
30
- yolov5_model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)
31
- # We'll filter YOLO detections to only include persons and cars.
32
- YOLO_FILTER_CLASSES = {"person", "car"}
 
 
 
 
33
 
34
  #########################################
35
  # 2. Helper Functions
@@ -63,55 +72,68 @@ def custom_nms(preds, iou_threshold=0.3):
63
  return filtered_preds
64
 
65
  def process_image(image_path):
66
- """
67
- Process the uploaded image using both detection pipelines:
68
- (a) Box detection via Roboflow (with measurement using an ArUco marker).
69
- (b) YOLOv5 detection for persons and cars.
70
- Returns the annotated image and a list of detection info dictionaries.
71
- """
72
  image = cv2.imread(image_path)
73
  if image is None:
 
74
  return None, "Could not read the image."
 
75
  img_height, img_width = image.shape[:2]
76
-
77
  detection_info = [] # List to hold all detection results for display
78
 
79
  # --- (a) Roboflow Box Detection & Measurement ---
80
- results = box_model.predict(image_path, confidence=50, overlap=30).json()
81
- predictions = results.get("predictions", [])
 
 
 
 
 
 
 
 
82
  processed_preds = []
83
  for prediction in predictions:
84
- x, y, width, height = prediction["x"], prediction["y"], prediction["width"], prediction["height"]
85
- x1 = int(round(x - width / 2))
86
- y1 = int(round(y - height / 2))
87
- x2 = int(round(x + width / 2))
88
- y2 = int(round(y + height / 2))
89
- # Clamp coordinates to image dimensions
90
- x1 = max(0, min(x1, img_width - 1))
91
- y1 = max(0, min(y1, img_height - 1))
92
- x2 = max(0, min(x2, img_width - 1))
93
- y2 = max(0, min(y2, img_height - 1))
94
- processed_preds.append({
95
- "box": (x1, y1, x2, y2),
96
- "class": prediction["class"],
97
- "confidence": prediction["confidence"]
98
- })
 
 
 
 
 
99
  box_detections = custom_nms(processed_preds, iou_threshold=0.3)
100
-
101
  # Detect ArUco marker for measurement (only applicable for boxes)
102
  marker_real_width_cm = 10.0 # The marker is 10cm x 10cm
103
- gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
104
- aruco_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_6X6_250)
105
- aruco_params = cv2.aruco.DetectorParameters()
106
- corners, ids, _ = cv2.aruco.detectMarkers(gray, aruco_dict, parameters=aruco_params)
107
- if ids is not None and len(corners) > 0:
108
- marker_corners = corners[0].reshape((4, 2))
109
- cv2.aruco.drawDetectedMarkers(image, corners, ids)
110
- marker_width_pixels = np.linalg.norm(marker_corners[0] - marker_corners[1])
111
- marker_height_pixels = np.linalg.norm(marker_corners[1] - marker_corners[2])
112
- marker_pixel_size = (marker_width_pixels + marker_height_pixels) / 2.0
113
- conversion_factor = marker_real_width_cm / marker_pixel_size
114
- else:
 
 
 
 
115
  conversion_factor = None
116
 
117
  # Draw box detections and record measurement info (only for boxes)
@@ -144,32 +166,38 @@ def process_image(image_path):
144
  (text_width, text_height), baseline = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
145
  cv2.rectangle(image, (x1, y1 - text_height - baseline - 5), (x1 + text_width, y1 - 5), (0, 255, 0), -1)
146
  cv2.putText(image, text, (x1, y1 - 5 - baseline), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1)
147
-
148
  # --- (b) YOLOv5 for Persons & Cars ---
149
- # Convert image to RGB for YOLO (it expects RGB)
150
- img_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
151
- yolo_results = yolov5_model(img_rgb)
152
- df = yolo_results.pandas().xyxy[0]
153
- for _, row in df.iterrows():
154
- if row['name'] in YOLO_FILTER_CLASSES:
155
- xmin = int(row['xmin'])
156
- ymin = int(row['ymin'])
157
- xmax = int(row['xmax'])
158
- ymax = int(row['ymax'])
159
- conf = row['confidence']
160
- label = row['name']
161
- cv2.rectangle(image, (xmin, ymin), (xmax, ymax), (255, 0, 0), 2)
162
- text = f"{label} ({conf:.2f})"
163
- (text_width, text_height), baseline = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
164
- cv2.rectangle(image, (xmin, ymin - text_height - baseline - 5), (xmin + text_width, ymin - 5), (255, 0, 0), -1)
165
- cv2.putText(image, text, (xmin, ymin - 5 - baseline), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1)
166
- detection_info.append({
167
- "class": label,
168
- "confidence": f"{conf:.2f}",
169
- "width_cm": "N/A",
170
- "height_cm": "N/A"
171
- })
172
-
 
 
 
 
 
 
173
  # --- Build Top Summary Text ---
174
  detection_counts = Counter(det["class"] for det in detection_info)
175
  if detection_counts:
@@ -177,7 +205,7 @@ def process_image(image_path):
177
  (info_width, info_height), info_baseline = cv2.getTextSize(top_text, cv2.FONT_HERSHEY_SIMPLEX, 1, 2)
178
  cv2.rectangle(image, (5, 5), (5 + info_width, 5 + info_height + info_baseline), (0, 255, 0), -1)
179
  cv2.putText(image, top_text, (5, 5 + info_height), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
180
-
181
  return image, detection_info
182
 
183
  #########################################
@@ -197,14 +225,22 @@ def index():
197
  flash('No selected file')
198
  return redirect(request.url)
199
  upload_path = "uploaded.jpg"
200
- file.save(upload_path)
 
 
 
 
 
201
  processed_image, detection_info = process_image(upload_path)
202
  if processed_image is None:
203
- flash("Error processing image.")
204
  else:
205
  retval, buffer = cv2.imencode('.jpg', processed_image)
206
  image_data = base64.b64encode(buffer).decode('utf-8')
207
- os.remove(upload_path)
 
 
 
208
  return render_template_string('''
209
  <!doctype html>
210
  <html>
@@ -334,4 +370,5 @@ def index():
334
  #########################################
335
 
336
  if __name__ == '__main__':
 
337
  app.run(host="0.0.0.0", port=7860)
 
15
  #########################################
16
 
17
  # --- Roboflow Box Detection Model ---
18
+ API_KEY = "wLjPoPYaLmrqCIOFA0RH" # Your Roboflow API key
19
+ PROJECT_ID = "base-model-box-r4suo-8lkk1-6dbqh" # Your Roboflow project ID
20
+ VERSION_NUMBER = "2" # Your trained model version number
21
 
22
+ try:
23
+ rf = roboflow.Roboflow(api_key=API_KEY)
24
+ workspace = rf.workspace()
25
+ project = workspace.project(PROJECT_ID)
26
+ version = project.version(VERSION_NUMBER)
27
+ box_model = version.model # This model is trained for detecting boxes
28
+ print("Roboflow model loaded successfully.")
29
+ except Exception as e:
30
+ print("Error initializing Roboflow model:", e)
31
+ box_model = None
32
 
33
  # --- YOLOv5 Pretrained Model for Persons & Cars ---
34
+ try:
35
+ yolov5_model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)
36
+ # Filter YOLO detections to only include persons and cars.
37
+ YOLO_FILTER_CLASSES = {"person", "car"}
38
+ print("YOLOv5 model loaded successfully.")
39
+ except Exception as e:
40
+ print("Error loading YOLOv5 model:", e)
41
+ yolov5_model = None
42
 
43
  #########################################
44
  # 2. Helper Functions
 
72
  return filtered_preds
73
 
74
  def process_image(image_path):
75
+ # Load image
 
 
 
 
 
76
  image = cv2.imread(image_path)
77
  if image is None:
78
+ print("DEBUG: cv2.imread failed to load the image from", image_path)
79
  return None, "Could not read the image."
80
+
81
  img_height, img_width = image.shape[:2]
 
82
  detection_info = [] # List to hold all detection results for display
83
 
84
  # --- (a) Roboflow Box Detection & Measurement ---
85
+ if box_model is None:
86
+ print("DEBUG: Roboflow model is not initialized.")
87
+ return None, "Roboflow model is not available."
88
+ try:
89
+ results = box_model.predict(image_path, confidence=50, overlap=30).json()
90
+ predictions = results.get("predictions", [])
91
+ except Exception as e:
92
+ print("DEBUG: Error during Roboflow prediction:", e)
93
+ return None, "Error during Roboflow prediction."
94
+
95
  processed_preds = []
96
  for prediction in predictions:
97
+ try:
98
+ x, y, width, height = prediction["x"], prediction["y"], prediction["width"], prediction["height"]
99
+ x1 = int(round(x - width / 2))
100
+ y1 = int(round(y - height / 2))
101
+ x2 = int(round(x + width / 2))
102
+ y2 = int(round(y + height / 2))
103
+ # Clamp coordinates to image dimensions
104
+ x1 = max(0, min(x1, img_width - 1))
105
+ y1 = max(0, min(y1, img_height - 1))
106
+ x2 = max(0, min(x2, img_width - 1))
107
+ y2 = max(0, min(y2, img_height - 1))
108
+ processed_preds.append({
109
+ "box": (x1, y1, x2, y2),
110
+ "class": prediction["class"],
111
+ "confidence": prediction["confidence"]
112
+ })
113
+ except Exception as e:
114
+ print("DEBUG: Error processing a prediction:", e)
115
+ continue
116
+
117
  box_detections = custom_nms(processed_preds, iou_threshold=0.3)
118
+
119
  # Detect ArUco marker for measurement (only applicable for boxes)
120
  marker_real_width_cm = 10.0 # The marker is 10cm x 10cm
121
+ try:
122
+ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
123
+ aruco_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_6X6_250)
124
+ aruco_params = cv2.aruco.DetectorParameters()
125
+ corners, ids, _ = cv2.aruco.detectMarkers(gray, aruco_dict, parameters=aruco_params)
126
+ if ids is not None and len(corners) > 0:
127
+ marker_corners = corners[0].reshape((4, 2))
128
+ cv2.aruco.drawDetectedMarkers(image, corners, ids)
129
+ marker_width_pixels = np.linalg.norm(marker_corners[0] - marker_corners[1])
130
+ marker_height_pixels = np.linalg.norm(marker_corners[1] - marker_corners[2])
131
+ marker_pixel_size = (marker_width_pixels + marker_height_pixels) / 2.0
132
+ conversion_factor = marker_real_width_cm / marker_pixel_size
133
+ else:
134
+ conversion_factor = None
135
+ except Exception as e:
136
+ print("DEBUG: Error during ArUco detection:", e)
137
  conversion_factor = None
138
 
139
  # Draw box detections and record measurement info (only for boxes)
 
166
  (text_width, text_height), baseline = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
167
  cv2.rectangle(image, (x1, y1 - text_height - baseline - 5), (x1 + text_width, y1 - 5), (0, 255, 0), -1)
168
  cv2.putText(image, text, (x1, y1 - 5 - baseline), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1)
169
+
170
  # --- (b) YOLOv5 for Persons & Cars ---
171
+ if yolov5_model is None:
172
+ print("DEBUG: YOLOv5 model is not initialized.")
173
+ else:
174
+ try:
175
+ img_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
176
+ yolo_results = yolov5_model(img_rgb)
177
+ df = yolo_results.pandas().xyxy[0]
178
+ for _, row in df.iterrows():
179
+ if row['name'] in YOLO_FILTER_CLASSES:
180
+ xmin = int(row['xmin'])
181
+ ymin = int(row['ymin'])
182
+ xmax = int(row['xmax'])
183
+ ymax = int(row['ymax'])
184
+ conf = row['confidence']
185
+ label = row['name']
186
+ cv2.rectangle(image, (xmin, ymin), (xmax, ymax), (255, 0, 0), 2)
187
+ text = f"{label} ({conf:.2f})"
188
+ (text_width, text_height), baseline = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
189
+ cv2.rectangle(image, (xmin, ymin - text_height - baseline - 5), (xmin + text_width, ymin - 5), (255, 0, 0), -1)
190
+ cv2.putText(image, text, (xmin, ymin - 5 - baseline), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1)
191
+ detection_info.append({
192
+ "class": label,
193
+ "confidence": f"{conf:.2f}",
194
+ "width_cm": "N/A",
195
+ "height_cm": "N/A"
196
+ })
197
+ except Exception as e:
198
+ print("DEBUG: Error during YOLOv5 inference:", e)
199
+ return None, "Error during YOLOv5 inference."
200
+
201
  # --- Build Top Summary Text ---
202
  detection_counts = Counter(det["class"] for det in detection_info)
203
  if detection_counts:
 
205
  (info_width, info_height), info_baseline = cv2.getTextSize(top_text, cv2.FONT_HERSHEY_SIMPLEX, 1, 2)
206
  cv2.rectangle(image, (5, 5), (5 + info_width, 5 + info_height + info_baseline), (0, 255, 0), -1)
207
  cv2.putText(image, top_text, (5, 5 + info_height), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
208
+
209
  return image, detection_info
210
 
211
  #########################################
 
225
  flash('No selected file')
226
  return redirect(request.url)
227
  upload_path = "uploaded.jpg"
228
+ try:
229
+ file.save(upload_path)
230
+ except Exception as e:
231
+ print("DEBUG: Error saving uploaded file:", e)
232
+ flash("Error saving uploaded file.")
233
+ return redirect(request.url)
234
  processed_image, detection_info = process_image(upload_path)
235
  if processed_image is None:
236
+ flash("Error Processing Image: " + detection_info)
237
  else:
238
  retval, buffer = cv2.imencode('.jpg', processed_image)
239
  image_data = base64.b64encode(buffer).decode('utf-8')
240
+ try:
241
+ os.remove(upload_path)
242
+ except Exception as e:
243
+ print("DEBUG: Error removing uploaded file:", e)
244
  return render_template_string('''
245
  <!doctype html>
246
  <html>
 
370
  #########################################
371
 
372
  if __name__ == '__main__':
373
+ # Ensure the app runs on 0.0.0.0 and port 7860 for Hugging Face Spaces.
374
  app.run(host="0.0.0.0", port=7860)