|
6 | 6 | "source": [ |
7 | 7 | "# Create training data using Labelbox\n", |
8 | 8 | "* Download images and animal annotations\n", |
9 | | - "* Upload them to labelbox using MAL\n", |
10 | | - "* Label to add any missing classes" |
| 9 | + "* Upload them to labelbox using MAL" |
11 | 10 | ] |
12 | 11 | }, |
13 | 12 | { |
14 | 13 | "cell_type": "code", |
15 | | - "execution_count": 1, |
| 14 | + "execution_count": null, |
16 | 15 | "metadata": {}, |
17 | 16 | "outputs": [], |
18 | 17 | "source": [ |
|
40 | 39 | }, |
41 | 40 | { |
42 | 41 | "cell_type": "code", |
43 | | - "execution_count": 2, |
| 42 | + "execution_count": null, |
44 | 43 | "metadata": {}, |
45 | 44 | "outputs": [], |
46 | 45 | "source": [ |
|
53 | 52 | }, |
54 | 53 | { |
55 | 54 | "cell_type": "code", |
56 | | - "execution_count": 3, |
| 55 | + "execution_count": null, |
57 | 56 | "metadata": {}, |
58 | 57 | "outputs": [], |
59 | 58 | "source": [ |
60 | 59 | "# Download the annotations\n", |
61 | | - "if not os.path.exists('eccv_18_annotation_files'):\n", |
62 | | - " !wget http://www.vision.caltech.edu/~sbeery/datasets/caltechcameratraps18/eccv_18_annotations.tar.gz\n", |
63 | | - " !tar -zxf eccv_18_annotations.tar.gz" |
| 60 | + "if not os.path.exists('eccv_18_all_annotations'):\n", |
| 61 | + " !wget http://www.vision.caltech.edu/~sbeery/datasets/caltechcameratraps18/eccv_18_all_annotations.tar.gz\n", |
| 62 | + " !tar -zxf eccv_18_all_annotations.tar.gz" |
64 | 63 | ] |
65 | 64 | }, |
66 | 65 | { |
67 | 66 | "cell_type": "markdown", |
68 | 67 | "metadata": {}, |
69 | 68 | "source": [ |
70 | 69 | "## Preprocess Data\n", |
| 70 | + "* Sample images from video sequences\n", |
71 | 71 | "* Select only day time images and a subset of possible animals\n", |
72 | | - "* Since the images are coming from video frames we split into train and eval datasets to account for this.\n", |
73 | 72 | "* Convert the data into a format that is compatible with labelbox" |
74 | 73 | ] |
75 | 74 | }, |
76 | 75 | { |
77 | 76 | "cell_type": "code", |
78 | | - "execution_count": 4, |
| 77 | + "execution_count": null, |
79 | 78 | "metadata": {}, |
80 | 79 | "outputs": [], |
81 | 80 | "source": [ |
82 | | - "data = json.load(open('eccv_18_annotation_files/train_annotations.json'))\n", |
| 81 | + "data = json.load(open('CaltechCameraTrapsECCV18.json'))\n", |
83 | 82 | "data['categories'] = {d['id'] : d for d in data['categories']}\n", |
84 | 83 | "annotations = defaultdict(lambda: [])" |
85 | 84 | ] |
86 | 85 | }, |
87 | 86 | { |
88 | 87 | "cell_type": "code", |
89 | | - "execution_count": 5, |
| 88 | + "execution_count": null, |
90 | 89 | "metadata": {}, |
91 | 90 | "outputs": [], |
92 | 91 | "source": [ |
93 | | - "#Unique sequence of frames so the that the same animal isn't in the train and eval set by chance\n", |
94 | | - "#We also want different seq_ids so that they are all from different sequences (not same animal)\n", |
| 92 | + "# One image per video sequence to reduce correlation between training/testing images.\n", |
95 | 93 | "\n", |
96 | 94 | "images = {}\n", |
97 | 95 | "ids = set()\n", |
|
113 | 111 | }, |
114 | 112 | { |
115 | 113 | "cell_type": "code", |
116 | | - "execution_count": 6, |
| 114 | + "execution_count": null, |
117 | 115 | "metadata": {}, |
118 | 116 | "outputs": [], |
119 | 117 | "source": [ |
| 118 | + "# These ids correspond to locations with a lot of people in the images that we can label\n", |
| 119 | + "target_locations = {0,125,120}\n", |
120 | 120 | "target_classes = {'dog', 'cat', 'deer', 'bobcat', 'fox'}\n", |
| 121 | + "min_border_distance = 50\n", |
121 | 122 | "\n", |
122 | 123 | "\n", |
123 | | - "def process_image(image, min_bbox_height_px = 50 , min_bbox_width_px = 50):\n", |
| 124 | + "def process_image(image):\n", |
124 | 125 | " date_time_obj = datetime.datetime.strptime(image['date_captured'], '%Y-%m-%d %H:%M:%S')\n", |
125 | 126 | " if (not ((18 > date_time_obj.hour > 7)) or (date_time_obj.hour == 12)):\n", |
126 | 127 | " #Only train on day time images\n", |
127 | 128 | " return\n", |
128 | 129 | " \n", |
| 130 | + " if image['location'] not in target_locations:\n", |
| 131 | + " return\n", |
| 132 | + " \n", |
129 | 133 | " annots = annotations[image['id']]\n", |
130 | 134 | " im = None \n", |
131 | 135 | " box_coords = []\n", |
|
138 | 142 | " bbox = annot.get('bbox')\n", |
139 | 143 | " assert bbox is not None\n", |
140 | 144 | " \n", |
141 | | - " if bbox[0] < min_bbox_width_px or bbox[1] < min_bbox_height_px:\n", |
142 | | - " #Ignore tiny bboxes\n", |
| 145 | + " # Don't train on images where the animal is on the edge of the image\n", |
| 146 | + " if bbox[0] < min_border_distance or bbox[1] < min_border_distance:\n", |
143 | 147 | " return\n", |
144 | 148 | " \n", |
145 | | - " if (w - (bbox[0] + bbox[2])) < min_bbox_width_px or (h - (bbox[1] + bbox[3])) < min_bbox_height_px:\n", |
| 149 | + " if (w - (bbox[0] + bbox[2])) < min_border_distance or (h - (bbox[1] + bbox[3])) < min_border_distance:\n", |
146 | 150 | " return \n", |
147 | 151 | " \n", |
148 | 152 | " if im is None:\n", |
|
158 | 162 | }, |
159 | 163 | { |
160 | 164 | "cell_type": "code", |
161 | | - "execution_count": 7, |
| 165 | + "execution_count": null, |
162 | 166 | "metadata": {}, |
163 | | - "outputs": [ |
164 | | - { |
165 | | - "name": "stdout", |
166 | | - "output_type": "stream", |
167 | | - "text": [ |
168 | | - "191\n" |
169 | | - ] |
170 | | - } |
171 | | - ], |
| 167 | + "outputs": [], |
172 | 168 | "source": [ |
173 | 169 | "examples = [process_image(ex) for ex in data['images'].values()]\n", |
174 | 170 | "examples = [ex for ex in examples if ex is not None]\n", |
|
184 | 180 | }, |
185 | 181 | { |
186 | 182 | "cell_type": "code", |
187 | | - "execution_count": 8, |
| 183 | + "execution_count": null, |
188 | 184 | "metadata": {}, |
189 | 185 | "outputs": [], |
190 | 186 | "source": [ |
|
195 | 191 | " os.mkdir(\"labels\")\n", |
196 | 192 | " \n", |
197 | 193 | "image_paths = []\n", |
| 194 | + "\n", |
198 | 195 | "for idx, example in enumerate(examples):\n", |
199 | 196 | " imm, coords, location = example\n", |
200 | 197 | " image_path = os.path.join(\"uploaded_images\", f\"{idx}.jpg\")\n", |
|
219 | 216 | }, |
220 | 217 | { |
221 | 218 | "cell_type": "code", |
222 | | - "execution_count": 9, |
| 219 | + "execution_count": null, |
223 | 220 | "metadata": {}, |
224 | 221 | "outputs": [], |
225 | 222 | "source": [ |
226 | | - "client = Client(api_key = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJja2s0cTF2Z3djMHZwMDcwNHhoeDdtNHZrIiwib3JnYW5pemF0aW9uSWQiOiJja2s0cTF2Z2Fwc2F1MDczMjRhd25zanEyIiwiYXBpS2V5SWQiOiJja2t6bjd5dG5pZHNjMDcwNjczazIyamF1IiwiaWF0IjoxNjEyOTc0MjQ3LCJleHAiOjIyNDQxMjYyNDd9.GrGjHbN1w1X5-qLzlzp9UKCnkSffKqTQWEWIRyegHGg\")" |
| 223 | + "client = Client()" |
227 | 224 | ] |
228 | 225 | }, |
229 | 226 | { |
230 | 227 | "cell_type": "code", |
231 | | - "execution_count": 10, |
| 228 | + "execution_count": null, |
232 | 229 | "metadata": {}, |
233 | | - "outputs": [ |
234 | | - { |
235 | | - "data": { |
236 | | - "text/plain": [ |
237 | | - "True" |
238 | | - ] |
239 | | - }, |
240 | | - "execution_count": 10, |
241 | | - "metadata": {}, |
242 | | - "output_type": "execute_result" |
243 | | - } |
244 | | - ], |
| 230 | + "outputs": [], |
245 | 231 | "source": [ |
246 | 232 | "project = client.create_project(name = \"animal_demo_proj\")\n", |
247 | 233 | "dataset = client.create_dataset(name = \"animal_demo_ds\")\n", |
|
252 | 238 | }, |
253 | 239 | { |
254 | 240 | "cell_type": "code", |
255 | | - "execution_count": 11, |
| 241 | + "execution_count": null, |
256 | 242 | "metadata": {}, |
257 | 243 | "outputs": [], |
258 | 244 | "source": [ |
|
273 | 259 | }, |
274 | 260 | { |
275 | 261 | "cell_type": "code", |
276 | | - "execution_count": 12, |
| 262 | + "execution_count": null, |
277 | 263 | "metadata": {}, |
278 | 264 | "outputs": [], |
279 | 265 | "source": [ |
|
286 | 272 | }, |
287 | 273 | { |
288 | 274 | "cell_type": "code", |
289 | | - "execution_count": 13, |
| 275 | + "execution_count": null, |
290 | 276 | "metadata": {}, |
291 | 277 | "outputs": [], |
292 | 278 | "source": [ |
|
295 | 281 | }, |
296 | 282 | { |
297 | 283 | "cell_type": "code", |
298 | | - "execution_count": 14, |
| 284 | + "execution_count": null, |
299 | 285 | "metadata": {}, |
300 | 286 | "outputs": [], |
301 | 287 | "source": [ |
|
319 | 305 | }, |
320 | 306 | { |
321 | 307 | "cell_type": "code", |
322 | | - "execution_count": 16, |
| 308 | + "execution_count": null, |
323 | 309 | "metadata": {}, |
324 | 310 | "outputs": [], |
325 | 311 | "source": [ |
|
331 | 317 | "cell_type": "markdown", |
332 | 318 | "metadata": {}, |
333 | 319 | "source": [ |
334 | | - "## Go to labelbox and label\n", |
335 | | - "* Most of the data is prelabeled so we just need to go through and make sure everything is correct\n", |
| 320 | + "## Go to Labelbox and Label\n", |
| 321 | + "* Most of the animal data is prelabeled we want to go through and make sure everything is correct\n", |
| 322 | + " * Make sure to use the hot keys to label quickly!\n", |
| 323 | + " * 'e' submits the image\n", |
| 324 | + " * '1' selects the person bounding box\n", |
| 325 | + " * '2' selects the animal bounding box\n", |
| 326 | + " * There are other helpful ones too! Check out the keyboard shortcuts panel in the top right of the editor.\n", |
336 | 327 | "* None of the people in the images have been labeled so we are also going to add those annotations" |
337 | 328 | ] |
338 | 329 | }, |
339 | 330 | { |
340 | 331 | "cell_type": "code", |
341 | | - "execution_count": 17, |
| 332 | + "execution_count": null, |
342 | 333 | "metadata": {}, |
343 | | - "outputs": [ |
344 | | - { |
345 | | - "name": "stdout", |
346 | | - "output_type": "stream", |
347 | | - "text": [ |
348 | | - "https://app.labelbox.com/projects/ckq6zvmwm8sko0ya4fevdgsbf/overview\n" |
349 | | - ] |
350 | | - } |
351 | | - ], |
| 334 | + "outputs": [], |
352 | 335 | "source": [ |
353 | 336 | "print(f\"https://app.labelbox.com/projects/{project.uid}/overview\")" |
354 | 337 | ] |
|
0 commit comments