Spaces:
Build error
Build error
vchiang001
commited on
Commit
β’
8d64a48
1
Parent(s):
47a9bd7
added font, font color, pose size,
Browse files
app.py
CHANGED
@@ -31,13 +31,61 @@ FONTS = {'amiko': "font/Amiko-Regular.ttf",
|
|
31 |
'zen': "font/ZEN.TTF"}
|
32 |
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
def draw_keypoints_on_image(image,
|
35 |
keypoints,
|
36 |
map_label_id_to_str,
|
37 |
-
color='red',
|
38 |
-
radius=2,
|
39 |
use_normalized_coordinates=True,
|
40 |
gr_pose_font_input='amiko',
|
|
|
|
|
|
|
41 |
):
|
42 |
"""Draws keypoints on an image.
|
43 |
Modified from:
|
@@ -64,21 +112,21 @@ def draw_keypoints_on_image(image,
|
|
64 |
keypoints_y = tuple([im_height * y for y in keypoints_y])
|
65 |
|
66 |
# draw ellipses around keypoints and add string labels
|
67 |
-
font = ImageFont.truetype(FONTS[gr_pose_font_input],
|
68 |
for i, (keypoint_x, keypoint_y) in enumerate(zip(keypoints_x, keypoints_y)):
|
69 |
-
draw.ellipse([(keypoint_x -
|
70 |
-
(keypoint_x +
|
71 |
-
outline=
|
72 |
|
73 |
# add string labels around keypoints
|
74 |
# draw.text((x, y),"Sample Text",(r,g,b))
|
75 |
-
draw.text((keypoint_x +
|
76 |
map_label_id_to_str[i],#"Sample Text",
|
77 |
(255,0,0), # rgb
|
78 |
font=font)
|
79 |
|
80 |
############################################
|
81 |
-
|
82 |
# Predict detections with MegaDetector v5a model
|
83 |
def predict_md(im, size=640):
|
84 |
# resize image
|
@@ -91,6 +139,7 @@ def predict_md(im, size=640):
|
|
91 |
|
92 |
return results #Image.fromarray(results.imgs[0]) ---return animals only?
|
93 |
|
|
|
94 |
def crop_animal_detections(yolo_results,
|
95 |
likelihood_th):
|
96 |
## crop if animal and return list of crops
|
@@ -140,6 +189,7 @@ def crop_animal_detections(yolo_results,
|
|
140 |
# if detections_dict["category"] == "1":
|
141 |
return list_np_animal_crops
|
142 |
|
|
|
143 |
def predict_dlc(list_np_crops,
|
144 |
kpts_likelihood_th,
|
145 |
DLCmodel,
|
@@ -162,13 +212,16 @@ def predict_dlc(list_np_crops,
|
|
162 |
return list_kpts_per_crop
|
163 |
|
164 |
|
165 |
-
|
166 |
def predict_pipeline(img_input,
|
167 |
model_input_str,
|
168 |
flag_dlc_only,
|
169 |
bbox_likelihood_th,
|
170 |
kpts_likelihood_th,
|
171 |
-
gr_pose_font_input,
|
|
|
|
|
|
|
172 |
):
|
173 |
|
174 |
############################################################
|
@@ -188,6 +241,7 @@ def predict_pipeline(img_input,
|
|
188 |
elif model_input_str == 'full_monkey':
|
189 |
path_to_DLCmodel = "model/DLC_monkey_resnet_50_iteration-0_shuffle-1"
|
190 |
pose_cfg_path = os.path.join(path_to_DLCmodel,'pose_cfg.yaml')
|
|
|
191 |
|
192 |
# read pose cfg as dict
|
193 |
with open(pose_cfg_path, "r") as stream:
|
@@ -219,10 +273,11 @@ def predict_pipeline(img_input,
|
|
219 |
draw_keypoints_on_image(img_input,
|
220 |
list_kpts_per_crop[0], # a numpy array with shape [num_keypoints, 2].
|
221 |
map_label_id_to_str,
|
222 |
-
color='red',
|
223 |
-
radius=2,
|
224 |
use_normalized_coordinates=False,
|
225 |
-
gr_pose_font_input=gr_pose_font_input
|
|
|
|
|
|
|
226 |
)
|
227 |
return img_input, #list_kpts_per_crop
|
228 |
|
@@ -243,10 +298,11 @@ def predict_pipeline(img_input,
|
|
243 |
draw_keypoints_on_image(img_crop,
|
244 |
kpts_crop, # a numpy array with shape [num_keypoints, 2].
|
245 |
map_label_id_to_str,
|
246 |
-
color='red',
|
247 |
-
radius=2,
|
248 |
use_normalized_coordinates=False, # if True, then I should use md_results.xyxyn
|
249 |
gr_pose_font_input=gr_pose_font_input,
|
|
|
|
|
|
|
250 |
)
|
251 |
|
252 |
## Paste crop in original image
|
@@ -258,53 +314,16 @@ def predict_pipeline(img_input,
|
|
258 |
|
259 |
|
260 |
##########################################################
|
|
|
261 |
# Get MegaDetector model
|
262 |
# TODO: Allow user selectable model?
|
263 |
# models = ["model_weights/md_v5a.0.0.pt","model_weights/md_v5b.0.0.pt"]
|
264 |
MD_model = torch.hub.load('ultralytics/yolov5', 'custom', "megadet_model/md_v5b.0.0.pt")
|
265 |
|
266 |
|
267 |
-
####################################################
|
268 |
-
# Create user interface and launch: all inputs
|
269 |
-
gr_image_input = gr.inputs.Image(type="pil", label="Input Image")
|
270 |
-
|
271 |
-
|
272 |
-
gr_dlc_model_input = gr.inputs.Dropdown(choices=['full_cat','full_dog', 'monkey_face', 'full_human', 'full_monkey'], # choices
|
273 |
-
default='full_cat', # default option
|
274 |
-
type='value', # Type of value to be returned by component. "value" returns the string of the choice selected, "index" returns the index of the choice selected.
|
275 |
-
label='Select DLC model')
|
276 |
-
gr_dlc_only_checkbox = gr.inputs.Checkbox(False,
|
277 |
-
label='Run DLClive only, directly on input image?')
|
278 |
-
|
279 |
-
gr_slider_conf_bboxes = gr.inputs.Slider(0,1,.05,0.8,
|
280 |
-
label='Set confidence threshold for animal detections')
|
281 |
-
gr_slider_conf_keypoints = gr.inputs.Slider(0,1,.05,0,
|
282 |
-
label='Set confidence threshold for keypoints')
|
283 |
-
|
284 |
-
gr_keypt_color = gr.ColorPicker(label="choose colour for pose")
|
285 |
-
|
286 |
-
gr_pose_font_input = gr.inputs.Dropdown(choices=['amiko', 'nature', 'painter', 'animals', 'zen'],
|
287 |
-
default='amiko',
|
288 |
-
type='value',
|
289 |
-
label='Select pose font')
|
290 |
-
gr_slider_font_size = gr.inputs.Slider(5,30,1,8,
|
291 |
-
label='Set pose font size')
|
292 |
-
|
293 |
-
inputs = [gr_image_input,
|
294 |
-
gr_dlc_model_input,
|
295 |
-
gr_dlc_only_checkbox,
|
296 |
-
gr_slider_conf_bboxes,
|
297 |
-
gr_slider_conf_keypoints,
|
298 |
-
#gr_keypt_color,
|
299 |
-
gr_pose_font_input,
|
300 |
-
#gr_slider_font_size,
|
301 |
-
]
|
302 |
-
|
303 |
-
#image = gr.inputs.Image(type="pil", label="Input Image")
|
304 |
-
#chosen_model = gr.inputs.Dropdown(choices = models, value = "model_weights/md_v5a.0.0.pt",type = "value", label="Model Weight")
|
305 |
-
#size = 640
|
306 |
|
307 |
####################################################
|
|
|
308 |
# Create user interface and launch: all outputs
|
309 |
gr_gallery_output = gr.Gallery(type="pil", label="Output Gallery")
|
310 |
gr_json_output = gr.JSON(label='megadetector json')
|
@@ -316,12 +335,15 @@ outputs = [gr_gallery_output, #gr_json_output,
|
|
316 |
#gr_pose_output,
|
317 |
]
|
318 |
|
319 |
-
gr_title = "MegaDetector v5 + DLClive"
|
320 |
gr_description = "Detect and estimate the pose of animals in camera trap images, using MegaDetector v5a + DeepLabCut-live. \
|
321 |
-
Builds up on work from <a href='https://huggingface.co/spaces/hlydecker/MegaDetector_v5'>hlydecker/MegaDetector_v5</a>
|
|
|
|
|
322 |
# article = "<p style='text-align: center'>This app makes predictions using a YOLOv5x6 model that was trained to detect animals, humans, and vehicles in camera trap images; find out more about the project on <a href='https://github.com/microsoft/CameraTraps'>GitHub</a>. This app was built by Henry Lydecker but really depends on code and models developed by <a href='http://ecologize.org/'>Ecologize</a> and <a href='http://aka.ms/aiforearth'>Microsoft AI for Earth</a>. Find out more about the YOLO model from the original creator, <a href='https://pjreddie.com/darknet/yolo/'>Joseph Redmon</a>. YOLOv5 is a family of compound-scaled object detection models trained on the COCO dataset and developed by Ultralytics, and includes simple functionality for Test Time Augmentation (TTA), model ensembling, hyperparameter evolution, and export to ONNX, CoreML and TFLite. <a href='https://github.com/ultralytics/yolov5'>Source code</a> | <a href='https://pytorch.org/hub/ultralytics_yolov5'>PyTorch Hub</a></p>"
|
323 |
# examples = [['data/Macropod.jpg'], ['data/koala2.jpg'],['data/cat.jpg'],['data/BrushtailPossum.jpg']]
|
324 |
|
|
|
325 |
demo = gr.Interface(predict_pipeline,
|
326 |
inputs=inputs,
|
327 |
outputs=outputs,
|
@@ -331,22 +353,5 @@ demo = gr.Interface(predict_pipeline,
|
|
331 |
#live=True
|
332 |
)
|
333 |
|
334 |
-
demo.launch(enable_queue=True)
|
335 |
-
|
336 |
-
# def dlclive_pose(model, crop_np, crop, fname, index,dlc_proc):
|
337 |
-
# dlc_live = DLCLive(model, processor=dlc_proc)
|
338 |
-
# dlc_live.init_inference(crop_np)
|
339 |
-
# keypts = dlc_live.get_pose(crop_np)
|
340 |
-
# savetxt(str(fname)+ '_' + str(index) + '.csv' , keypts, delimiter=',')
|
341 |
-
# xpose = []
|
342 |
-
# ypose = []
|
343 |
-
# for key in keypts[:,2]:
|
344 |
-
# # if key > 0.05: # which value do we need here?
|
345 |
-
# i = np.where(keypts[:,2]==key)
|
346 |
-
# xpose.append(keypts[i,0])
|
347 |
-
# ypose.append(keypts[i,1])
|
348 |
-
# plt.imshow(crop)
|
349 |
-
# plt.scatter(xpose[:], ypose[:], 40, color='cyan')
|
350 |
-
# plt.savefig(str(fname)+ '_' + str(index) + '.png')
|
351 |
-
# plt.show()
|
352 |
-
# plt.clf()
|
|
|
31 |
'zen': "font/ZEN.TTF"}
|
32 |
|
33 |
|
34 |
+
#############################################
|
35 |
+
# %%
|
36 |
+
# Create user interface and launch: all inputs
|
37 |
+
gr_image_input = gr.inputs.Image(type="pil", label="Input Image")
|
38 |
+
|
39 |
+
|
40 |
+
gr_dlc_model_input = gr.inputs.Dropdown(choices=['full_cat','full_dog', 'monkey_face', 'full_human', 'full_monkey'], # choices
|
41 |
+
default='full_cat', # default option
|
42 |
+
type='value', # Type of value to be returned by component. "value" returns the string of the choice selected, "index" returns the index of the choice selected.
|
43 |
+
label='Select DLC model')
|
44 |
+
gr_dlc_only_checkbox = gr.inputs.Checkbox(False,
|
45 |
+
label='Run DLClive only, directly on input image?')
|
46 |
+
|
47 |
+
gr_slider_conf_bboxes = gr.inputs.Slider(0,1,.05,0.8,
|
48 |
+
label='Set confidence threshold for animal detections')
|
49 |
+
gr_slider_conf_keypoints = gr.inputs.Slider(0,1,.05,0,
|
50 |
+
label='Set confidence threshold for keypoints')
|
51 |
+
|
52 |
+
gr_keypt_color = gr.ColorPicker(label="choose colour for pose")
|
53 |
+
|
54 |
+
gr_pose_font_input = gr.inputs.Dropdown(choices=['amiko', 'nature', 'painter', 'animals', 'zen'],
|
55 |
+
default='amiko',
|
56 |
+
type='value',
|
57 |
+
label='Select pose font')
|
58 |
+
gr_slider_font_size = gr.inputs.Slider(5,30,1,8,
|
59 |
+
label='Set pose font size')
|
60 |
+
|
61 |
+
gr_slider_pose_size = gr.inputs.Slider(1,20,1,2,
|
62 |
+
label='Set pose size')
|
63 |
+
|
64 |
+
inputs = [gr_image_input,
|
65 |
+
gr_dlc_model_input,
|
66 |
+
gr_dlc_only_checkbox,
|
67 |
+
gr_slider_conf_bboxes,
|
68 |
+
gr_slider_conf_keypoints,
|
69 |
+
gr_pose_font_input,
|
70 |
+
gr_slider_font_size,
|
71 |
+
gr_keypt_color,
|
72 |
+
gr_slider_pose_size,
|
73 |
+
]
|
74 |
+
|
75 |
+
#image = gr.inputs.Image(type="pil", label="Input Image")
|
76 |
+
#chosen_model = gr.inputs.Dropdown(choices = models, value = "model_weights/md_v5a.0.0.pt",type = "value", label="Model Weight")
|
77 |
+
#size = 640
|
78 |
+
|
79 |
+
#########################################
|
80 |
+
# %%
|
81 |
def draw_keypoints_on_image(image,
|
82 |
keypoints,
|
83 |
map_label_id_to_str,
|
|
|
|
|
84 |
use_normalized_coordinates=True,
|
85 |
gr_pose_font_input='amiko',
|
86 |
+
gr_slider_font_size=8,
|
87 |
+
gr_keypt_color="#ff0000",
|
88 |
+
gr_slider_pose_size='2'
|
89 |
):
|
90 |
"""Draws keypoints on an image.
|
91 |
Modified from:
|
|
|
112 |
keypoints_y = tuple([im_height * y for y in keypoints_y])
|
113 |
|
114 |
# draw ellipses around keypoints and add string labels
|
115 |
+
font = ImageFont.truetype(FONTS[gr_pose_font_input], gr_slider_font_size) # font = ImageFont.truetype(<font-file>, <font-size>)
|
116 |
for i, (keypoint_x, keypoint_y) in enumerate(zip(keypoints_x, keypoints_y)):
|
117 |
+
draw.ellipse([(keypoint_x - gr_slider_pose_size, keypoint_y - gr_slider_pose_size),
|
118 |
+
(keypoint_x + gr_slider_pose_size, keypoint_y + gr_slider_pose_size)],
|
119 |
+
outline=gr_keypt_color, fill=gr_keypt_color)
|
120 |
|
121 |
# add string labels around keypoints
|
122 |
# draw.text((x, y),"Sample Text",(r,g,b))
|
123 |
+
draw.text((keypoint_x + gr_slider_pose_size, keypoint_y + gr_slider_pose_size),#(0.5*im_width, 0.5*im_height), #-------
|
124 |
map_label_id_to_str[i],#"Sample Text",
|
125 |
(255,0,0), # rgb
|
126 |
font=font)
|
127 |
|
128 |
############################################
|
129 |
+
# %%
|
130 |
# Predict detections with MegaDetector v5a model
|
131 |
def predict_md(im, size=640):
|
132 |
# resize image
|
|
|
139 |
|
140 |
return results #Image.fromarray(results.imgs[0]) ---return animals only?
|
141 |
|
142 |
+
# %%
|
143 |
def crop_animal_detections(yolo_results,
|
144 |
likelihood_th):
|
145 |
## crop if animal and return list of crops
|
|
|
189 |
# if detections_dict["category"] == "1":
|
190 |
return list_np_animal_crops
|
191 |
|
192 |
+
# %%
|
193 |
def predict_dlc(list_np_crops,
|
194 |
kpts_likelihood_th,
|
195 |
DLCmodel,
|
|
|
212 |
return list_kpts_per_crop
|
213 |
|
214 |
|
215 |
+
# %%
|
216 |
def predict_pipeline(img_input,
|
217 |
model_input_str,
|
218 |
flag_dlc_only,
|
219 |
bbox_likelihood_th,
|
220 |
kpts_likelihood_th,
|
221 |
+
gr_pose_font_input=gr_pose_font_input,
|
222 |
+
gr_slider_font_size=gr_slider_font_size,
|
223 |
+
gr_keypt_color=gr_keypt_color,
|
224 |
+
gr_slider_pose_size=gr_slider_pose_size,
|
225 |
):
|
226 |
|
227 |
############################################################
|
|
|
241 |
elif model_input_str == 'full_monkey':
|
242 |
path_to_DLCmodel = "model/DLC_monkey_resnet_50_iteration-0_shuffle-1"
|
243 |
pose_cfg_path = os.path.join(path_to_DLCmodel,'pose_cfg.yaml')
|
244 |
+
|
245 |
|
246 |
# read pose cfg as dict
|
247 |
with open(pose_cfg_path, "r") as stream:
|
|
|
273 |
draw_keypoints_on_image(img_input,
|
274 |
list_kpts_per_crop[0], # a numpy array with shape [num_keypoints, 2].
|
275 |
map_label_id_to_str,
|
|
|
|
|
276 |
use_normalized_coordinates=False,
|
277 |
+
gr_pose_font_input=gr_pose_font_input,
|
278 |
+
gr_slider_font_size=gr_slider_font_size,
|
279 |
+
gr_keypt_color=gr_keypt_color,
|
280 |
+
gr_slider_pose_size=gr_slider_pose_size,
|
281 |
)
|
282 |
return img_input, #list_kpts_per_crop
|
283 |
|
|
|
298 |
draw_keypoints_on_image(img_crop,
|
299 |
kpts_crop, # a numpy array with shape [num_keypoints, 2].
|
300 |
map_label_id_to_str,
|
|
|
|
|
301 |
use_normalized_coordinates=False, # if True, then I should use md_results.xyxyn
|
302 |
gr_pose_font_input=gr_pose_font_input,
|
303 |
+
gr_slider_font_size=gr_slider_font_size,
|
304 |
+
gr_keypt_color=gr_keypt_color,
|
305 |
+
gr_slider_pose_size=gr_slider_pose_size,
|
306 |
)
|
307 |
|
308 |
## Paste crop in original image
|
|
|
314 |
|
315 |
|
316 |
##########################################################
|
317 |
+
# %%
|
318 |
# Get MegaDetector model
|
319 |
# TODO: Allow user selectable model?
|
320 |
# models = ["model_weights/md_v5a.0.0.pt","model_weights/md_v5b.0.0.pt"]
|
321 |
MD_model = torch.hub.load('ultralytics/yolov5', 'custom', "megadet_model/md_v5b.0.0.pt")
|
322 |
|
323 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
324 |
|
325 |
####################################################
|
326 |
+
# %%
|
327 |
# Create user interface and launch: all outputs
|
328 |
gr_gallery_output = gr.Gallery(type="pil", label="Output Gallery")
|
329 |
gr_json_output = gr.JSON(label='megadetector json')
|
|
|
335 |
#gr_pose_output,
|
336 |
]
|
337 |
|
338 |
+
gr_title = "MegaDetector v5 + DLClive by Sofi, Nesli, Nirel, Vic"
|
339 |
gr_description = "Detect and estimate the pose of animals in camera trap images, using MegaDetector v5a + DeepLabCut-live. \
|
340 |
+
Builds up on work from <a href='https://huggingface.co/spaces/hlydecker/MegaDetector_v5'>hlydecker/MegaDetector_v5</a> \
|
341 |
+
<a href='https://huggingface.co/spaces/sofmi/MegaDetector_DLClive</a> \
|
342 |
+
<a href='https://huggingface.co/spaces/Neslihan/megadetector_dlcmodels</a>"
|
343 |
# article = "<p style='text-align: center'>This app makes predictions using a YOLOv5x6 model that was trained to detect animals, humans, and vehicles in camera trap images; find out more about the project on <a href='https://github.com/microsoft/CameraTraps'>GitHub</a>. This app was built by Henry Lydecker but really depends on code and models developed by <a href='http://ecologize.org/'>Ecologize</a> and <a href='http://aka.ms/aiforearth'>Microsoft AI for Earth</a>. Find out more about the YOLO model from the original creator, <a href='https://pjreddie.com/darknet/yolo/'>Joseph Redmon</a>. YOLOv5 is a family of compound-scaled object detection models trained on the COCO dataset and developed by Ultralytics, and includes simple functionality for Test Time Augmentation (TTA), model ensembling, hyperparameter evolution, and export to ONNX, CoreML and TFLite. <a href='https://github.com/ultralytics/yolov5'>Source code</a> | <a href='https://pytorch.org/hub/ultralytics_yolov5'>PyTorch Hub</a></p>"
|
344 |
# examples = [['data/Macropod.jpg'], ['data/koala2.jpg'],['data/cat.jpg'],['data/BrushtailPossum.jpg']]
|
345 |
|
346 |
+
# %%
|
347 |
demo = gr.Interface(predict_pipeline,
|
348 |
inputs=inputs,
|
349 |
outputs=outputs,
|
|
|
353 |
#live=True
|
354 |
)
|
355 |
|
356 |
+
demo.launch(enable_queue=True, share=True)
|
357 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|