sfmig commited on
Commit
fcf3dc1
·
1 Parent(s): 07d3c1e

pushing all but dlc models

Browse files
Files changed (5) hide show
  1. .gitignore +2 -0
  2. README.md +2 -1
  3. app.py +221 -0
  4. model_weights/md_v5a.0.0.pt +3 -0
  5. requirements.txt +7 -0
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ notebook_megadetector_crop.py
2
+ flagged/*
README.md CHANGED
@@ -9,4 +9,5 @@ app_file: app.py
9
  pinned: false
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
9
  pinned: false
10
  ---
11
 
12
+ Combining MegaDetector implementation from https://huggingface.co/spaces/hlydecker/MegaDetector_v5 with DLClive
13
+ # Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,221 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import gradio as gr
3
+ import torch
4
+ import torchvision
5
+ import numpy as np
6
+ from PIL import Image
7
+ import PIL.ImageDraw as ImageDraw
8
+ import math
9
+ import pdb
10
+
11
+ from dlclive import DLCLive, Processor
12
+
13
+ import matplotlib.pyplot as plt
14
+
15
+ #########################################
16
+ # https://www.programcreek.com/python/?code=fjchange%2Fobject_centric_VAD%2Fobject_centric_VAD-master%2Fobject_detection%2Futils%2Fvisualization_utils.py
17
+ def draw_keypoints_on_image(image,
18
+ keypoints,
19
+ color='red',
20
+ radius=2,
21
+ use_normalized_coordinates=True):
22
+ """Draws keypoints on an image.
23
+
24
+ Args:
25
+ image: a PIL.Image object.
26
+ keypoints: a numpy array with shape [num_keypoints, 2].
27
+ color: color to draw the keypoints with. Default is red.
28
+ radius: keypoint radius. Default value is 2.
29
+ use_normalized_coordinates: if True (default), treat keypoint values as
30
+ relative to the image. Otherwise treat them as absolute.
31
+ """
32
+ # get a drawing context
33
+ draw = ImageDraw.Draw(image)
34
+
35
+ im_width, im_height = image.size
36
+ keypoints_x = [k[1] for k in keypoints]
37
+ keypoints_y = [k[0] for k in keypoints]
38
+
39
+ # adjust keypoints coords if required
40
+ if use_normalized_coordinates:
41
+ keypoints_x = tuple([im_width * x for x in keypoints_x])
42
+ keypoints_y = tuple([im_height * y for y in keypoints_y])
43
+
44
+ # draw ellipses around keypoints
45
+ for keypoint_x, keypoint_y in zip(keypoints_x, keypoints_y):
46
+ draw.ellipse([(keypoint_x - radius, keypoint_y - radius),
47
+ (keypoint_x + radius, keypoint_y + radius)],
48
+ outline=color, fill=color)
49
+ ############################################
50
+
51
+ # Predict detections with MegaDetector v5a model
52
+ def predict_md(im, size=640):
53
+ # resize image
54
+ g = (size / max(im.size)) # gain
55
+ im = im.resize((int(x * g) for x in im.size), Image.ANTIALIAS) # resize
56
+
57
+ ## detect objects
58
+ results = MD_model(im) # inference # vars(results).keys()= dict_keys(['imgs', 'pred', 'names', 'files', 'times', 'xyxy', 'xywh', 'xyxyn', 'xywhn', 'n', 't', 's'])
59
+ results.render() # updates results.imgs with boxes and labels
60
+
61
+ return results #Image.fromarray(results.imgs[0]) ---return animals only?
62
+
63
+ def crop_animal_detections(yolo_results, likelihood_th):
64
+ ## crop if animal and return list of crops
65
+
66
+ list_labels_as_str = yolo_results.names #['animal', 'person', 'vehicle']
67
+ list_np_animal_crops = []
68
+
69
+ # for every image
70
+ for img, det_array in zip(yolo_results.imgs,
71
+ yolo_results.xyxy):
72
+
73
+ # for every detection
74
+ for j in range(det_array.shape[0]):
75
+
76
+ # compute coords around bbox rounded to the nearest integer (for pasting later)
77
+ xmin_rd = int(math.floor(det_array[j,0])) # int() should suffice?
78
+ ymin_rd = int(math.floor(det_array[j,1]))
79
+
80
+ xmax_rd = int(math.ceil(det_array[j,2]))
81
+ ymax_rd = int(math.ceil(det_array[j,3]))
82
+
83
+ pred_llk = det_array[j,4] #-----TODO: filter based on likelihood?
84
+ pred_label = det_array[j,5]
85
+
86
+ if (pred_label == list_labels_as_str.index('animal')) and \
87
+ (pred_llk >= likelihood_th):
88
+ area = (xmin_rd, ymin_rd, xmax_rd, ymax_rd)
89
+
90
+ crop = Image.fromarray(img).crop(area)
91
+ crop_np = np.asarray(crop)
92
+
93
+ # add to list
94
+ list_np_animal_crops.append(crop_np)
95
+
96
+ # for detections_dict in img_data["detections"]:
97
+ # index = img_data["detections"].index(detections_dict)
98
+ # if detections_dict["conf"] > 0.8:
99
+ # x1, y1,w_box, h_box = detections_dict["bbox"]
100
+ # ymin,xmin,ymax, xmax = y1, x1, y1 + h_box, x1 + w_box
101
+
102
+ # imageWidth=img.size[0]
103
+ # imageHeight= img.size[1]
104
+ # area = (xmin * imageWidth, ymin * imageHeight, xmax * imageWidth,
105
+ # ymax * imageHeight)
106
+ # crop = img.crop(area)
107
+ # crop_np = np.asarray(crop)
108
+ #
109
+ # if detections_dict["category"] == "1":
110
+ return list_np_animal_crops
111
+
112
+ def predict_dlc(list_np_crops,DLCmodel,dlc_proc):
113
+ # run dlc thru list of crops
114
+ dlc_live = DLCLive(DLCmodel, processor=dlc_proc)
115
+ dlc_live.init_inference(list_np_crops[0])
116
+
117
+ list_kpts_per_crop = []
118
+ for crop in list_np_crops:
119
+ keypts = dlc_live.get_pose(crop) # third column is llk!
120
+ list_kpts_per_crop.append(keypts)
121
+
122
+ return list_kpts_per_crop
123
+
124
+
125
+
126
+ def predict_pipeline(img_input):
127
+
128
+ # these eventually user inputs....
129
+ path_to_DLCmodel = "DLC_models/DLC_Cat_resnet_50_iteration-0_shuffle-0"
130
+ likelihood_th = 0.8
131
+
132
+ # Run Megadetector
133
+ md_results = predict_md(img_input) #Image.fromarray(results.imgs[0])
134
+
135
+ # Obtain animal crops with confidence above th
136
+ list_crops = crop_animal_detections(md_results,
137
+ likelihood_th)
138
+
139
+ # Run DLC
140
+ # TODO: add llk threshold for kpts too?
141
+ dlc_proc = Processor()
142
+ list_kpts_per_crop = predict_dlc(list_crops,
143
+ path_to_DLCmodel,
144
+ dlc_proc)
145
+
146
+
147
+ # # Produce final image
148
+ fig = plt.Figure(md_results.imgs[0].shape[:2]) #figsize=(10,10)) #md_results.imgs[0].shape)
149
+ for ic, (np_crop, kpts_crop) in enumerate(zip(list_crops,
150
+ list_kpts_per_crop)):
151
+
152
+ # Draw keypts on crop
153
+ img_crop = Image.fromarray(np_crop)
154
+ draw_keypoints_on_image(img_crop,
155
+ kpts_crop, # a numpy array with shape [num_keypoints, 2].
156
+ color='red',
157
+ radius=2,
158
+ use_normalized_coordinates=False) # if True, then I should use md_results.xyxyn
159
+
160
+ # Paste crop in original image
161
+ # https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.paste
162
+
163
+ img_input.paste(img_crop,
164
+ box = tuple([int(math.floor(t)) for t in md_results.xyxy[0][ic,:2]]))
165
+
166
+ # plt.imshow(np_crop)
167
+ # plt.scatter(kpts_crop[:,0], kpts_crop[:,1], 40,
168
+ # color='r')
169
+ # img_overlay = Image.frombytes('RGB',
170
+ # fig.canvas.get_width_height(),
171
+ # fig.canvas.tostring_rgb())
172
+ return img_input #Image.fromarray(list_crops[0]) #Image.fromarray(md_results.imgs[0]) #
173
+
174
+
175
+ ##########################################################
176
+ # Get MegaDetector model
177
+ # TODO: Allow user selectable model?
178
+ # models = ["model_weights/md_v5a.0.0.pt","model_weights/md_v5b.0.0.pt"]
179
+ MD_model = torch.hub.load('ultralytics/yolov5', 'custom', "model_weights/md_v5a.0.0.pt")
180
+
181
+
182
+
183
+ ####################################################
184
+ # Create user interface and launch
185
+ #inputs = [image, chosen_model, size]
186
+ inputs = gr.inputs.Image(type="pil", label="Input Image")
187
+ outputs = gr.outputs.Image(type="pil", label="Output Image")
188
+ #image = gr.inputs.Image(type="pil", label="Input Image")
189
+ #chosen_model = gr.inputs.Dropdown(choices = models, value = "model_weights/md_v5a.0.0.pt",type = "value", label="Model Weight")
190
+ #size = 640
191
+
192
+ title = "MegaDetector v5 + DLC live"
193
+ description = "Detect and estimate pose of animals camera trap images using MegaDetector v5a + DLClive"
194
+ # 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>"
195
+ # examples = [['data/Macropod.jpg'], ['data/koala2.jpg'],['data/cat.jpg'],['data/BrushtailPossum.jpg']]
196
+
197
+ gr.Interface(predict_pipeline,
198
+ inputs,
199
+ outputs,
200
+ title=title,
201
+ description=description,
202
+ theme="huggingface").launch(enable_queue=True)
203
+
204
+
205
+ # def dlclive_pose(model, crop_np, crop, fname, index,dlc_proc):
206
+ # dlc_live = DLCLive(model, processor=dlc_proc)
207
+ # dlc_live.init_inference(crop_np)
208
+ # keypts = dlc_live.get_pose(crop_np)
209
+ # savetxt(str(fname)+ '_' + str(index) + '.csv' , keypts, delimiter=',')
210
+ # xpose = []
211
+ # ypose = []
212
+ # for key in keypts[:,2]:
213
+ # # if key > 0.05: # which value do we need here?
214
+ # i = np.where(keypts[:,2]==key)
215
+ # xpose.append(keypts[i,0])
216
+ # ypose.append(keypts[i,1])
217
+ # plt.imshow(crop)
218
+ # plt.scatter(xpose[:], ypose[:], 40, color='cyan')
219
+ # plt.savefig(str(fname)+ '_' + str(index) + '.png')
220
+ # plt.show()
221
+ # plt.clf()
model_weights/md_v5a.0.0.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:94e88fe97c8050f2e3d0cc4cb4f64729d639d74312dcbe2f74f8eecd3b01b276
3
+ size 280766885
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ gradio
2
+ torch
3
+ torchvision
4
+ numpy
5
+ opencv-python
6
+ seaborn
7
+ dlclive