|
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