Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -76,6 +76,119 @@
|
|
76 |
# if __name__ == "__main__":
|
77 |
# iface.launch(share=False)
|
78 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
import gradio as gr
|
80 |
import io
|
81 |
from ultralytics import YOLO
|
@@ -90,7 +203,7 @@ multi_animal_model = YOLO("avatar_ckpt.pt") # Multi-animal model
|
|
90 |
|
91 |
def detect_keypoints(image, mode="single"):
|
92 |
"""
|
93 |
-
Run YOLO inference and return keypoints data
|
94 |
Args:
|
95 |
image: PIL Image
|
96 |
mode: "single" or "multi" to determine which model to use
|
@@ -124,9 +237,30 @@ def detect_keypoints(image, mode="single"):
|
|
124 |
verbose=False
|
125 |
)
|
126 |
|
127 |
-
|
128 |
if results and len(results) > 0:
|
129 |
result = results[0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
130 |
if result.keypoints is not None:
|
131 |
kpts = result.keypoints.xy.cpu().numpy()
|
132 |
conf = result.keypoints.conf.cpu().numpy()
|
@@ -144,27 +278,67 @@ def detect_keypoints(image, mode="single"):
|
|
144 |
"y": float(y),
|
145 |
"confidence": float(confidence)
|
146 |
})
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
|
169 |
except Exception as e:
|
170 |
return {"success": False, "error": str(e), "mode": mode}
|
@@ -178,7 +352,7 @@ iface = gr.Interface(
|
|
178 |
],
|
179 |
outputs=gr.JSON(),
|
180 |
title="YOLO Keypoint Detection",
|
181 |
-
description="Upload an image to detect keypoints using custom YOLO model. Choose single or multi-animal mode.",
|
182 |
api_name="predict" # This enables API access at /api/predict
|
183 |
)
|
184 |
|
|
|
76 |
# if __name__ == "__main__":
|
77 |
# iface.launch(share=False)
|
78 |
|
79 |
+
|
80 |
+
|
81 |
+
|
82 |
+
# import gradio as gr
|
83 |
+
# import io
|
84 |
+
# from ultralytics import YOLO
|
85 |
+
# import cv2
|
86 |
+
# import numpy as np
|
87 |
+
# from PIL import Image
|
88 |
+
# import json
|
89 |
+
|
90 |
+
# # Load both models
|
91 |
+
# single_animal_model = YOLO("fentanyl_oft.pt") # Single animal model
|
92 |
+
# multi_animal_model = YOLO("avatar_ckpt.pt") # Multi-animal model
|
93 |
+
|
94 |
+
# def detect_keypoints(image, mode="single"):
|
95 |
+
# """
|
96 |
+
# Run YOLO inference and return keypoints data
|
97 |
+
# Args:
|
98 |
+
# image: PIL Image
|
99 |
+
# mode: "single" or "multi" to determine which model to use
|
100 |
+
# """
|
101 |
+
# try:
|
102 |
+
# # Select model and parameters based on mode
|
103 |
+
# if mode == "multi":
|
104 |
+
# model = multi_animal_model
|
105 |
+
# imgsz = 1504
|
106 |
+
# max_det = 5
|
107 |
+
# else: # default to single
|
108 |
+
# model = single_animal_model
|
109 |
+
# imgsz = 1440
|
110 |
+
# max_det = 1
|
111 |
+
|
112 |
+
# # Convert PIL Image to numpy array
|
113 |
+
# if isinstance(image, Image.Image):
|
114 |
+
# image_np = np.array(image)
|
115 |
+
# image_cv2 = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)
|
116 |
+
# else:
|
117 |
+
# image_cv2 = image
|
118 |
+
|
119 |
+
# # Run inference with mode-specific parameters
|
120 |
+
# results = model.predict(
|
121 |
+
# source=image_cv2,
|
122 |
+
# conf=0.05,
|
123 |
+
# iou=0.7,
|
124 |
+
# max_det=max_det,
|
125 |
+
# imgsz=imgsz,
|
126 |
+
# device='cpu',
|
127 |
+
# verbose=False
|
128 |
+
# )
|
129 |
+
|
130 |
+
# keypoints_data = []
|
131 |
+
# if results and len(results) > 0:
|
132 |
+
# result = results[0]
|
133 |
+
# if result.keypoints is not None:
|
134 |
+
# kpts = result.keypoints.xy.cpu().numpy()
|
135 |
+
# conf = result.keypoints.conf.cpu().numpy()
|
136 |
+
|
137 |
+
# # Handle multiple detections (for multi-animal mode)
|
138 |
+
# for detection_idx in range(kpts.shape[0]):
|
139 |
+
# detection_keypoints = []
|
140 |
+
# for i in range(kpts.shape[1]):
|
141 |
+
# if i < len(kpts[detection_idx]):
|
142 |
+
# x, y = kpts[detection_idx][i]
|
143 |
+
# confidence = conf[detection_idx][i] if i < len(conf[detection_idx]) else 0.0
|
144 |
+
# detection_keypoints.append({
|
145 |
+
# "id": i,
|
146 |
+
# "x": float(x),
|
147 |
+
# "y": float(y),
|
148 |
+
# "confidence": float(confidence)
|
149 |
+
# })
|
150 |
+
|
151 |
+
# # For single animal mode, flatten the structure
|
152 |
+
# if mode == "single":
|
153 |
+
# keypoints_data = detection_keypoints
|
154 |
+
# break # Only take first detection
|
155 |
+
# else:
|
156 |
+
# # For multi-animal mode, keep detection structure
|
157 |
+
# keypoints_data.append({
|
158 |
+
# "detection_id": detection_idx,
|
159 |
+
# "keypoints": detection_keypoints
|
160 |
+
# })
|
161 |
+
|
162 |
+
# return {
|
163 |
+
# "success": True,
|
164 |
+
# "mode": mode,
|
165 |
+
# "keypoints": keypoints_data,
|
166 |
+
# "image_width": image_cv2.shape[1],
|
167 |
+
# "image_height": image_cv2.shape[0],
|
168 |
+
# "num_detections": len(keypoints_data) if mode == "multi" else (1 if keypoints_data else 0),
|
169 |
+
# "num_keypoints": len(keypoints_data) if mode == "single" else sum(len(det["keypoints"]) for det in keypoints_data) if mode == "multi" else 0
|
170 |
+
# }
|
171 |
+
|
172 |
+
# except Exception as e:
|
173 |
+
# return {"success": False, "error": str(e), "mode": mode}
|
174 |
+
|
175 |
+
# # Create Gradio interface with mode parameter
|
176 |
+
# iface = gr.Interface(
|
177 |
+
# fn=detect_keypoints,
|
178 |
+
# inputs=[
|
179 |
+
# gr.Image(type="pil"),
|
180 |
+
# gr.Dropdown(choices=["single", "multi"], value="single", label="Detection Mode")
|
181 |
+
# ],
|
182 |
+
# outputs=gr.JSON(),
|
183 |
+
# title="YOLO Keypoint Detection",
|
184 |
+
# description="Upload an image to detect keypoints using custom YOLO model. Choose single or multi-animal mode.",
|
185 |
+
# api_name="predict" # This enables API access at /api/predict
|
186 |
+
# )
|
187 |
+
|
188 |
+
# # Launch with API enabled
|
189 |
+
# if __name__ == "__main__":
|
190 |
+
# iface.launch(share=False)
|
191 |
+
|
192 |
import gradio as gr
|
193 |
import io
|
194 |
from ultralytics import YOLO
|
|
|
203 |
|
204 |
def detect_keypoints(image, mode="single"):
|
205 |
"""
|
206 |
+
Run YOLO inference and return keypoints and bounding boxes data
|
207 |
Args:
|
208 |
image: PIL Image
|
209 |
mode: "single" or "multi" to determine which model to use
|
|
|
237 |
verbose=False
|
238 |
)
|
239 |
|
240 |
+
detections_data = []
|
241 |
if results and len(results) > 0:
|
242 |
result = results[0]
|
243 |
+
|
244 |
+
# Extract bounding boxes
|
245 |
+
bboxes = []
|
246 |
+
if result.boxes is not None:
|
247 |
+
boxes_xyxy = result.boxes.xyxy.cpu().numpy() # [x1, y1, x2, y2]
|
248 |
+
boxes_conf = result.boxes.conf.cpu().numpy()
|
249 |
+
|
250 |
+
for i in range(len(boxes_xyxy)):
|
251 |
+
x1, y1, x2, y2 = boxes_xyxy[i]
|
252 |
+
confidence = float(boxes_conf[i])
|
253 |
+
|
254 |
+
bboxes.append({
|
255 |
+
"x1": float(x1),
|
256 |
+
"y1": float(y1),
|
257 |
+
"x2": float(x2),
|
258 |
+
"y2": float(y2),
|
259 |
+
"confidence": confidence
|
260 |
+
})
|
261 |
+
|
262 |
+
# Extract keypoints
|
263 |
+
keypoints_per_detection = []
|
264 |
if result.keypoints is not None:
|
265 |
kpts = result.keypoints.xy.cpu().numpy()
|
266 |
conf = result.keypoints.conf.cpu().numpy()
|
|
|
278 |
"y": float(y),
|
279 |
"confidence": float(confidence)
|
280 |
})
|
281 |
+
keypoints_per_detection.append(detection_keypoints)
|
282 |
+
|
283 |
+
# Combine keypoints and bboxes for each detection
|
284 |
+
max_detections = max(len(bboxes), len(keypoints_per_detection))
|
285 |
+
|
286 |
+
for detection_idx in range(max_detections):
|
287 |
+
detection_data = {
|
288 |
+
"detection_id": detection_idx
|
289 |
+
}
|
290 |
+
|
291 |
+
# Add keypoints if available for this detection
|
292 |
+
if detection_idx < len(keypoints_per_detection):
|
293 |
+
detection_data["keypoints"] = keypoints_per_detection[detection_idx]
|
294 |
+
else:
|
295 |
+
detection_data["keypoints"] = []
|
296 |
+
|
297 |
+
# Add bbox if available for this detection
|
298 |
+
if detection_idx < len(bboxes):
|
299 |
+
detection_data["bbox"] = bboxes[detection_idx]
|
300 |
+
else:
|
301 |
+
detection_data["bbox"] = None
|
302 |
+
|
303 |
+
detections_data.append(detection_data)
|
304 |
|
305 |
+
# Format response based on mode
|
306 |
+
if mode == "single":
|
307 |
+
# For single animal mode, flatten the structure (legacy compatibility)
|
308 |
+
if detections_data:
|
309 |
+
single_detection = detections_data[0]
|
310 |
+
return {
|
311 |
+
"success": True,
|
312 |
+
"mode": mode,
|
313 |
+
"keypoints": single_detection["keypoints"],
|
314 |
+
"bbox": single_detection["bbox"],
|
315 |
+
"image_width": image_cv2.shape[1],
|
316 |
+
"image_height": image_cv2.shape[0],
|
317 |
+
"num_detections": 1 if single_detection["keypoints"] or single_detection["bbox"] else 0,
|
318 |
+
"num_keypoints": len(single_detection["keypoints"])
|
319 |
+
}
|
320 |
+
else:
|
321 |
+
return {
|
322 |
+
"success": True,
|
323 |
+
"mode": mode,
|
324 |
+
"keypoints": [],
|
325 |
+
"bbox": None,
|
326 |
+
"image_width": image_cv2.shape[1],
|
327 |
+
"image_height": image_cv2.shape[0],
|
328 |
+
"num_detections": 0,
|
329 |
+
"num_keypoints": 0
|
330 |
+
}
|
331 |
+
else:
|
332 |
+
# For multi-animal mode, return all detections
|
333 |
+
return {
|
334 |
+
"success": True,
|
335 |
+
"mode": mode,
|
336 |
+
"detections": detections_data,
|
337 |
+
"image_width": image_cv2.shape[1],
|
338 |
+
"image_height": image_cv2.shape[0],
|
339 |
+
"num_detections": len(detections_data),
|
340 |
+
"num_keypoints": sum(len(det["keypoints"]) for det in detections_data)
|
341 |
+
}
|
342 |
|
343 |
except Exception as e:
|
344 |
return {"success": False, "error": str(e), "mode": mode}
|
|
|
352 |
],
|
353 |
outputs=gr.JSON(),
|
354 |
title="YOLO Keypoint Detection",
|
355 |
+
description="Upload an image to detect keypoints and bounding boxes using custom YOLO model. Choose single or multi-animal mode.",
|
356 |
api_name="predict" # This enables API access at /api/predict
|
357 |
)
|
358 |
|