├── COCO_Image_Viewer.ipynb
├── Detectron2_COCO_DataSegmentation_from_Marine_checkpoints.ipynb
├── Detectron2_COCO_DataSegmentation_from_Marine_checkpoints.py
├── Detectron2_custom_coco_data_instance_segmentation_marine_ver5_TRAIN_Colab.ipynb
├── LICENSE
├── README.md
├── _config.yml
├── composite.png
├── data_val
├── images-10.jpeg
├── images-11.jpeg
├── images-12.jpeg
├── images-13.jpeg
├── images-14.jpeg
├── images-15.jpeg
├── images-16.jpeg
├── images-17.jpeg
├── images-18.jpeg
├── images-19.jpeg
├── images-2.jpeg
├── images-20.jpeg
├── images-21.jpeg
├── images-22.jpeg
├── images-23.jpeg
├── images-24.jpeg
├── images-25.jpeg
├── images-26.jpeg
├── images-27.jpeg
├── images-28.jpeg
├── images-29.jpeg
├── images-3.jpeg
├── images-4.jpeg
├── images-5.jpeg
├── images-6.jpeg
├── images-7.jpeg
├── images-8.jpeg
└── images-9.jpeg
├── googlea2f7fa877a9207e5.html
├── googlee5a896f21eabcd63.html
├── labelme.png
├── labelme2coco.py
└── results.png
/COCO_Image_Viewer.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# COCO Image Viewer\n",
8 | "This notebook will allow you to view details about a COCO dataset and preview segmentations on annotated images.\n",
9 | "Learn more about it at: http://cocodataset.org/"
10 | ]
11 | },
12 | {
13 | "cell_type": "code",
14 | "execution_count": 2,
15 | "metadata": {
16 | "ExecuteTime": {
17 | "end_time": "2019-07-27T08:58:05.441736Z",
18 | "start_time": "2019-07-27T08:58:05.075740Z"
19 | }
20 | },
21 | "outputs": [],
22 | "source": [
23 | "import IPython\n",
24 | "import os\n",
25 | "import json\n",
26 | "import random\n",
27 | "import numpy as np\n",
28 | "import requests\n",
29 | "from io import BytesIO\n",
30 | "from math import trunc\n",
31 | "from PIL import Image as PILImage\n",
32 | "from PIL import ImageDraw as PILImageDraw"
33 | ]
34 | },
35 | {
36 | "cell_type": "code",
37 | "execution_count": 3,
38 | "metadata": {
39 | "ExecuteTime": {
40 | "end_time": "2019-07-27T08:58:05.486614Z",
41 | "start_time": "2019-07-27T08:58:05.443733Z"
42 | }
43 | },
44 | "outputs": [],
45 | "source": [
46 | "# Load the dataset json\n",
47 | "class CocoDataset():\n",
48 | " def __init__(self, annotation_path, image_dir):\n",
49 | " self.annotation_path = annotation_path\n",
50 | " self.image_dir = image_dir\n",
51 | " self.colors = ['blue', 'purple', 'red', 'green', 'orange', 'salmon', 'pink', 'gold',\n",
52 | " 'orchid', 'slateblue', 'limegreen', 'seagreen', 'darkgreen', 'olive',\n",
53 | " 'teal', 'aquamarine', 'steelblue', 'powderblue', 'dodgerblue', 'navy',\n",
54 | " 'magenta', 'sienna', 'maroon']\n",
55 | "\n",
56 | " json_file = open(self.annotation_path)\n",
57 | " self.coco = json.load(json_file)\n",
58 | " json_file.close()\n",
59 | "\n",
60 | " self.process_info()\n",
61 | " self.process_licenses()\n",
62 | " self.process_categories()\n",
63 | " self.process_images()\n",
64 | " self.process_segmentations()\n",
65 | "\n",
66 | " def display_info(self):\n",
67 | " print('Dataset Info:')\n",
68 | " print('=============')\n",
69 | " if self.info is None:\n",
70 | " return\n",
71 | " for key, item in self.info.items():\n",
72 | " print(' {}: {}'.format(key, item))\n",
73 | "\n",
74 | " requirements = [['description', str],\n",
75 | " ['url', str],\n",
76 | " ['version', str],\n",
77 | " ['year', int],\n",
78 | " ['contributor', str],\n",
79 | " ['date_created', str]]\n",
80 | " for req, req_type in requirements:\n",
81 | " if req not in self.info:\n",
82 | " print('ERROR: {} is missing'.format(req))\n",
83 | " elif type(self.info[req]) != req_type:\n",
84 | " print('ERROR: {} should be type {}'.format(req, str(req_type)))\n",
85 | " print('')\n",
86 | "\n",
87 | " def display_licenses(self):\n",
88 | " print('Licenses:')\n",
89 | " print('=========')\n",
90 | "\n",
91 | " if self.licenses is None:\n",
92 | " return\n",
93 | " requirements = [['id', int],\n",
94 | " ['url', str],\n",
95 | " ['name', str]]\n",
96 | " for license in self.licenses:\n",
97 | " for key, item in license.items():\n",
98 | " print(' {}: {}'.format(key, item))\n",
99 | " for req, req_type in requirements:\n",
100 | " if req not in license:\n",
101 | " print('ERROR: {} is missing'.format(req))\n",
102 | " elif type(license[req]) != req_type:\n",
103 | " print('ERROR: {} should be type {}'.format(\n",
104 | " req, str(req_type)))\n",
105 | " print('')\n",
106 | " print('')\n",
107 | "\n",
108 | " def display_categories(self):\n",
109 | " print('Categories:')\n",
110 | " print('=========')\n",
111 | " for sc_key, sc_val in self.super_categories.items():\n",
112 | " print(' super_category: {}'.format(sc_key))\n",
113 | " for cat_id in sc_val:\n",
114 | " print(' id {}: {}'.format(\n",
115 | " cat_id, self.categories[cat_id]['name']))\n",
116 | " print('')\n",
117 | "\n",
118 | " def display_image(self, image_id, show_polys=True, show_bbox=True, show_crowds=True, use_url=False):\n",
119 | " print('Image:')\n",
120 | " print('======')\n",
121 | " if image_id == 'random':\n",
122 | " image_id = random.choice(list(self.images.keys()))\n",
123 | "\n",
124 | " # Print the image info\n",
125 | " image = self.images[image_id]\n",
126 | " for key, val in image.items():\n",
127 | " print(' {}: {}'.format(key, val))\n",
128 | "\n",
129 | " # Open the image\n",
130 | " if use_url:\n",
131 | " image_path = image['coco_url']\n",
132 | " response = requests.get(image_path)\n",
133 | " image = PILImage.open(BytesIO(response.content))\n",
134 | "\n",
135 | " else:\n",
136 | " # image_path = os.path.join(self.image_dir, image['file_name'])\n",
137 | " image_path = \"{}/{}\".format(self.image_dir, image['file_name'])\n",
138 | " image = PILImage.open(image_path)\n",
139 | "\n",
140 | " # Calculate the size and adjusted display size\n",
141 | " max_width = 600\n",
142 | " image_width, image_height = image.size\n",
143 | " adjusted_width = min(image_width, max_width)\n",
144 | " adjusted_ratio = adjusted_width / image_width\n",
145 | " adjusted_height = adjusted_ratio * image_height\n",
146 | "\n",
147 | " # Create list of polygons to be drawn\n",
148 | " polygons = {}\n",
149 | " bbox_polygons = {}\n",
150 | " rle_regions = {}\n",
151 | " poly_colors = {}\n",
152 | " bbox_categories = {}\n",
153 | " print(' segmentations ({}):'.format(\n",
154 | " len(self.segmentations[image_id])))\n",
155 | " for i, segm in enumerate(self.segmentations[image_id]):\n",
156 | " polygons_list = []\n",
157 | " if segm['iscrowd'] != 0:\n",
158 | " # Gotta decode the RLE\n",
159 | " px = 0\n",
160 | " x, y = 0, 0\n",
161 | " rle_list = []\n",
162 | " for j, counts in enumerate(segm['segmentation']['counts']):\n",
163 | " if j % 2 == 0:\n",
164 | " # Empty pixels\n",
165 | " px += counts\n",
166 | " else:\n",
167 | " # Need to draw on these pixels, since we are drawing in vector form,\n",
168 | " # we need to draw horizontal lines on the image\n",
169 | " x_start = trunc(\n",
170 | " trunc(px / image_height) * adjusted_ratio)\n",
171 | " y_start = trunc(px % image_height * adjusted_ratio)\n",
172 | " px += counts\n",
173 | " x_end = trunc(trunc(px / image_height)\n",
174 | " * adjusted_ratio)\n",
175 | " y_end = trunc(px % image_height * adjusted_ratio)\n",
176 | " if x_end == x_start:\n",
177 | " # This is only on one line\n",
178 | " rle_list.append(\n",
179 | " {'x': x_start, 'y': y_start, 'width': 1, 'height': (y_end - y_start)})\n",
180 | " if x_end > x_start:\n",
181 | " # This spans more than one line\n",
182 | " # Insert top line first\n",
183 | " rle_list.append(\n",
184 | " {'x': x_start, 'y': y_start, 'width': 1, 'height': (image_height - y_start)})\n",
185 | "\n",
186 | " # Insert middle lines if needed\n",
187 | " lines_spanned = x_end - x_start + 1 # total number of lines spanned\n",
188 | " full_lines_to_insert = lines_spanned - 2\n",
189 | " if full_lines_to_insert > 0:\n",
190 | " full_lines_to_insert = trunc(\n",
191 | " full_lines_to_insert * adjusted_ratio)\n",
192 | " rle_list.append(\n",
193 | " {'x': (x_start + 1), 'y': 0, 'width': full_lines_to_insert, 'height': image_height})\n",
194 | "\n",
195 | " # Insert bottom line\n",
196 | " rle_list.append(\n",
197 | " {'x': x_end, 'y': 0, 'width': 1, 'height': y_end})\n",
198 | " if len(rle_list) > 0:\n",
199 | " rle_regions[segm['id']] = rle_list\n",
200 | " else:\n",
201 | " # Add the polygon segmentation\n",
202 | " for segmentation_points in segm['segmentation']:\n",
203 | " segmentation_points = np.multiply(\n",
204 | " segmentation_points, adjusted_ratio).astype(int)\n",
205 | " polygons_list.append(\n",
206 | " str(segmentation_points).lstrip('[').rstrip(']'))\n",
207 | " polygons[segm['id']] = polygons_list\n",
208 | " if i < len(self.colors):\n",
209 | " poly_colors[segm['id']] = self.colors[i]\n",
210 | " else:\n",
211 | " poly_colors[segm['id']] = 'white'\n",
212 | "\n",
213 | " bbox = segm['bbox']\n",
214 | " bbox_points = [bbox[0], bbox[1], bbox[0] + bbox[2], bbox[1],\n",
215 | " bbox[0] + bbox[2], bbox[1] +\n",
216 | " bbox[3], bbox[0], bbox[1] + bbox[3],\n",
217 | " bbox[0], bbox[1]]\n",
218 | " bbox_points = np.multiply(bbox_points, adjusted_ratio).astype(int)\n",
219 | " bbox_polygons[segm['id']] = str(\n",
220 | " bbox_points).lstrip('[').rstrip(']')\n",
221 | " bbox_categories[segm['id']] = self.categories[segm['category_id']]\n",
222 | " # Print details\n",
223 | " print(' {}:{}:{}'.format(\n",
224 | " segm['id'], poly_colors[segm['id']], self.categories[segm['category_id']]))\n",
225 | "\n",
226 | " # Draw segmentation polygons on image\n",
227 | " html = '
'\n",
228 | " html += '

'.format(\n",
229 | " image_path, adjusted_width)\n",
230 | " html += '
'\n",
262 | " html += '
'\n",
263 | " html += ''\n",
266 | " return html\n",
267 | "\n",
268 | " def process_info(self):\n",
269 | " self.info = self.coco.get('info')\n",
270 | "\n",
271 | " def process_licenses(self):\n",
272 | " self.licenses = self.coco.get('licenses')\n",
273 | "\n",
274 | " def process_categories(self):\n",
275 | " self.categories = {}\n",
276 | " self.super_categories = {}\n",
277 | " for category in self.coco['categories']:\n",
278 | " cat_id = category['id']\n",
279 | " super_category = category['supercategory']\n",
280 | "\n",
281 | " # Add category to the categories dict\n",
282 | " if cat_id not in self.categories:\n",
283 | " self.categories[cat_id] = category\n",
284 | " else:\n",
285 | " print(\"ERROR: Skipping duplicate category id: {}\".format(category))\n",
286 | "\n",
287 | " # Add category to super_categories dict\n",
288 | " if super_category not in self.super_categories:\n",
289 | " # Create a new set with the category id\n",
290 | " self.super_categories[super_category] = {cat_id}\n",
291 | " else:\n",
292 | " self.super_categories[super_category] |= {\n",
293 | " cat_id} # Add category id to the set\n",
294 | "\n",
295 | " def process_images(self):\n",
296 | " self.images = {}\n",
297 | " for image in self.coco['images']:\n",
298 | " image_id = image['id']\n",
299 | " if image_id in self.images:\n",
300 | " print(\"ERROR: Skipping duplicate image id: {}\".format(image))\n",
301 | " else:\n",
302 | " self.images[image_id] = image\n",
303 | "\n",
304 | " def process_segmentations(self):\n",
305 | " self.segmentations = {}\n",
306 | " for segmentation in self.coco['annotations']:\n",
307 | " image_id = segmentation['image_id']\n",
308 | " if image_id not in self.segmentations:\n",
309 | " self.segmentations[image_id] = []\n",
310 | " self.segmentations[image_id].append(segmentation)"
311 | ]
312 | },
313 | {
314 | "cell_type": "code",
315 | "execution_count": 4,
316 | "metadata": {
317 | "ExecuteTime": {
318 | "end_time": "2019-07-27T08:58:05.510585Z",
319 | "start_time": "2019-07-27T08:58:05.489608Z"
320 | }
321 | },
322 | "outputs": [
323 | {
324 | "name": "stdout",
325 | "output_type": "stream",
326 | "text": [
327 | "Dataset Info:\n",
328 | "=============\n",
329 | "Licenses:\n",
330 | "=========\n",
331 | "Categories:\n",
332 | "=========\n",
333 | " super_category: buoy\n",
334 | " id 0: buoy\n",
335 | "\n",
336 | " super_category: land\n",
337 | " id 1: land\n",
338 | "\n",
339 | " super_category: ship\n",
340 | " id 2: ship\n",
341 | "\n"
342 | ]
343 | }
344 | ],
345 | "source": [
346 | "annotation_path = \"./data_plus_boats/trainval.json\"\n",
347 | "image_dir = \"./data_plus_boats/images\"\n",
348 | "\n",
349 | "coco_dataset = CocoDataset(annotation_path, image_dir)\n",
350 | "coco_dataset.display_info()\n",
351 | "coco_dataset.display_licenses()\n",
352 | "coco_dataset.display_categories()"
353 | ]
354 | },
355 | {
356 | "cell_type": "code",
357 | "execution_count": 5,
358 | "metadata": {
359 | "ExecuteTime": {
360 | "end_time": "2019-07-27T08:58:05.520552Z",
361 | "start_time": "2019-07-27T08:58:05.512547Z"
362 | },
363 | "scrolled": false
364 | },
365 | "outputs": [
366 | {
367 | "name": "stdout",
368 | "output_type": "stream",
369 | "text": [
370 | "0 {'height': 3264, 'width': 4928, 'id': 0, 'file_name': 'DSC_4513.JPG'}\n",
371 | "1 {'height': 3264, 'width': 4928, 'id': 1, 'file_name': 'DSC_4682.JPG'}\n",
372 | "2 {'height': 3264, 'width': 4928, 'id': 2, 'file_name': 'DSC_4505.JPG'}\n",
373 | "3 {'height': 3264, 'width': 4928, 'id': 3, 'file_name': 'DSC_4591.JPG'}\n",
374 | "4 {'height': 3264, 'width': 4928, 'id': 4, 'file_name': 'DSC_4657.JPG'}\n",
375 | "5 {'height': 225, 'width': 225, 'id': 5, 'file_name': '20.jpg'}\n",
376 | "6 {'height': 978, 'width': 1835, 'id': 6, 'file_name': 'DSC_5007.JPG'}\n",
377 | "7 {'height': 135, 'width': 372, 'id': 7, 'file_name': '16.jpg'}\n",
378 | "8 {'height': 3264, 'width': 4928, 'id': 8, 'file_name': 'DSC_4620.JPG'}\n",
379 | "9 {'height': 3264, 'width': 4928, 'id': 9, 'file_name': 'DSC_4437.JPG'}\n",
380 | "10 {'height': 3264, 'width': 4928, 'id': 10, 'file_name': 'DSC_4525.JPG'}\n",
381 | "11 {'height': 2160, 'width': 3840, 'id': 11, 'file_name': 'DSC_0136.JPG'}\n",
382 | "12 {'height': 194, 'width': 259, 'id': 12, 'file_name': '6.jpg'}\n",
383 | "13 {'height': 3264, 'width': 4928, 'id': 13, 'file_name': 'DSC_4499.JPG'}\n",
384 | "14 {'height': 3264, 'width': 4928, 'id': 14, 'file_name': 'DSC_4421.JPG'}\n",
385 | "15 {'height': 168, 'width': 299, 'id': 15, 'file_name': '7.jpg'}\n",
386 | "16 {'height': 3264, 'width': 4928, 'id': 16, 'file_name': 'DSC_4621.JPG'}\n",
387 | "17 {'height': 3264, 'width': 4928, 'id': 17, 'file_name': 'DSC_4676.JPG'}\n",
388 | "18 {'height': 182, 'width': 278, 'id': 18, 'file_name': '17.jpg'}\n",
389 | "19 {'height': 3264, 'width': 4928, 'id': 19, 'file_name': 'DSC_4586.JPG'}\n",
390 | "20 {'height': 3264, 'width': 4928, 'id': 20, 'file_name': 'DSC_4656.JPG'}\n",
391 | "21 {'height': 194, 'width': 259, 'id': 21, 'file_name': '21.jpg'}\n",
392 | "22 {'height': 3264, 'width': 4928, 'id': 22, 'file_name': 'DSC_4441.JPG'}\n",
393 | "23 {'height': 3264, 'width': 4928, 'id': 23, 'file_name': 'DSC_4416.JPG'}\n",
394 | "24 {'height': 3264, 'width': 4928, 'id': 24, 'file_name': 'DSC_4683.JPG'}\n",
395 | "25 {'height': 3264, 'width': 4928, 'id': 25, 'file_name': 'DSC_4519.JPG'}\n",
396 | "26 {'height': 225, 'width': 225, 'id': 26, 'file_name': '10.jpg'}\n",
397 | "27 {'height': 3264, 'width': 4928, 'id': 27, 'file_name': 'DSC_4626.JPG'}\n",
398 | "28 {'height': 2160, 'width': 3840, 'id': 28, 'file_name': 'DSC_0130.JPG'}\n",
399 | "29 {'height': 3264, 'width': 4928, 'id': 29, 'file_name': 'DSC_4535.JPG'}\n",
400 | "30 {'height': 3264, 'width': 4928, 'id': 30, 'file_name': 'DSC_4427.JPG'}\n",
401 | "31 {'height': 3264, 'width': 4928, 'id': 31, 'file_name': 'DSC_4684.JPG'}\n",
402 | "32 {'height': 3264, 'width': 4928, 'id': 32, 'file_name': 'DSC_4503.JPG'}\n",
403 | "33 {'height': 3264, 'width': 4928, 'id': 33, 'file_name': 'DSC_4597.JPG'}\n",
404 | "34 {'height': 3264, 'width': 4928, 'id': 34, 'file_name': 'DSC_4606.JPG'}\n",
405 | "35 {'height': 976, 'width': 1829, 'id': 35, 'file_name': 'DSC_5017.JPG'}\n",
406 | "36 {'height': 3264, 'width': 4928, 'id': 36, 'file_name': 'DSC_4580.JPG'}\n",
407 | "37 {'height': 1049, 'width': 1851, 'id': 37, 'file_name': 'DSC_5000.JPG'}\n",
408 | "38 {'height': 3264, 'width': 4928, 'id': 38, 'file_name': 'DSC_4538.JPG'}\n",
409 | "39 {'height': 3264, 'width': 4928, 'id': 39, 'file_name': 'DSC_4579.JPG'}\n",
410 | "40 {'height': 3264, 'width': 4928, 'id': 40, 'file_name': 'DSC_4685.JPG'}\n",
411 | "41 {'height': 3264, 'width': 4928, 'id': 41, 'file_name': 'DSC_4514.JPG'}\n",
412 | "42 {'height': 158, 'width': 319, 'id': 42, 'file_name': '1.jpg'}\n",
413 | "43 {'height': 3264, 'width': 4928, 'id': 43, 'file_name': 'DSC_4488.JPG'}\n",
414 | "44 {'height': 3264, 'width': 4928, 'id': 44, 'file_name': 'DSC_4430.JPG'}\n",
415 | "45 {'height': 3264, 'width': 4928, 'id': 45, 'file_name': 'DSC_4627.JPG'}\n",
416 | "46 {'height': 177, 'width': 284, 'id': 46, 'file_name': '2.jpg'}\n",
417 | "47 {'height': 2160, 'width': 3840, 'id': 47, 'file_name': 'DSC_0132.JPG'}\n",
418 | "48 {'height': 188, 'width': 268, 'id': 48, 'file_name': '12.jpg'}\n",
419 | "49 {'height': 3264, 'width': 4928, 'id': 49, 'file_name': 'DSC_4583.JPG'}\n",
420 | "50 {'height': 2160, 'width': 3840, 'id': 50, 'file_name': 'DSC_0128.JPG'}\n",
421 | "51 {'height': 3264, 'width': 4928, 'id': 51, 'file_name': 'DSC_4595.JPG'}\n",
422 | "52 {'height': 3264, 'width': 4928, 'id': 52, 'file_name': 'DSC_4413.JPG'}\n",
423 | "53 {'height': 3264, 'width': 4928, 'id': 53, 'file_name': 'DSC_4452.JPG'}\n",
424 | "54 {'height': 3264, 'width': 4928, 'id': 54, 'file_name': 'DSC_4412.JPG'}\n",
425 | "55 {'height': 3264, 'width': 4928, 'id': 55, 'file_name': 'DSC_4594.JPG'}\n",
426 | "56 {'height': 3264, 'width': 4928, 'id': 56, 'file_name': 'DSC_4486.JPG'}\n",
427 | "57 {'height': 975, 'width': 1827, 'id': 57, 'file_name': 'DSC_5014.JPG'}\n",
428 | "58 {'height': 3264, 'width': 4928, 'id': 58, 'file_name': 'DSC_4428.JPG'}\n",
429 | "59 {'height': 275, 'width': 183, 'id': 59, 'file_name': '13.jpg'}\n",
430 | "60 {'height': 2160, 'width': 3840, 'id': 60, 'file_name': 'DSC_0133.JPG'}\n",
431 | "61 {'height': 145, 'width': 348, 'id': 61, 'file_name': '3.jpg'}\n",
432 | "62 {'height': 3264, 'width': 4928, 'id': 62, 'file_name': 'DSC_4585.JPG'}\n",
433 | "63 {'height': 980, 'width': 1836, 'id': 63, 'file_name': 'DSC_5005.JPG'}\n",
434 | "64 {'height': 3264, 'width': 4928, 'id': 64, 'file_name': 'DSC_4614.JPG'}\n",
435 | "65 {'height': 190, 'width': 266, 'id': 65, 'file_name': '8.jpg'}\n",
436 | "66 {'height': 3264, 'width': 4928, 'id': 66, 'file_name': 'DSC_4602.JPG'}\n",
437 | "67 {'height': 3264, 'width': 4928, 'id': 67, 'file_name': 'DSC_4593.JPG'}\n",
438 | "68 {'height': 3264, 'width': 4928, 'id': 68, 'file_name': 'DSC_4679.JPG'}\n",
439 | "69 {'height': 3264, 'width': 4928, 'id': 69, 'file_name': 'DSC_4680.JPG'}\n",
440 | "70 {'height': 3264, 'width': 4928, 'id': 70, 'file_name': 'DSC_4511.JPG'}\n",
441 | "71 {'height': 3264, 'width': 4928, 'id': 71, 'file_name': 'DSC_4531.JPG'}\n",
442 | "72 {'height': 168, 'width': 300, 'id': 72, 'file_name': '4.jpg'}\n",
443 | "73 {'height': 2160, 'width': 3840, 'id': 73, 'file_name': 'DSC_0134.JPG'}\n",
444 | "74 {'height': 3264, 'width': 4928, 'id': 74, 'file_name': 'DSC_4419.JPG'}\n",
445 | "75 {'height': 168, 'width': 300, 'id': 75, 'file_name': '14.jpg'}\n",
446 | "76 {'height': 176, 'width': 286, 'id': 76, 'file_name': '15.jpg'}\n",
447 | "77 {'height': 3264, 'width': 4928, 'id': 77, 'file_name': 'DSC_4658.JPG'}\n",
448 | "78 {'height': 2160, 'width': 3840, 'id': 78, 'file_name': 'DSC_0135.JPG'}\n",
449 | "79 {'height': 168, 'width': 300, 'id': 79, 'file_name': '5.jpg'}\n",
450 | "80 {'height': 967, 'width': 1836, 'id': 80, 'file_name': 'DSC_5008.JPG'}\n",
451 | "81 {'height': 3264, 'width': 4928, 'id': 81, 'file_name': 'DSC_4530.JPG'}\n",
452 | "82 {'height': 3264, 'width': 4928, 'id': 82, 'file_name': 'DSC_4475.JPG'}\n",
453 | "83 {'height': 3264, 'width': 4928, 'id': 83, 'file_name': 'DSC_4422.JPG'}\n",
454 | "84 {'height': 3264, 'width': 4928, 'id': 84, 'file_name': 'DSC_4588.JPG'}\n",
455 | "85 {'height': 3264, 'width': 4928, 'id': 85, 'file_name': 'DSC_4681.JPG'}\n",
456 | "86 {'height': 142, 'width': 356, 'id': 86, 'file_name': '19.jpg'}\n",
457 | "87 {'height': 3264, 'width': 4928, 'id': 87, 'file_name': 'DSC_4414.JPG'}\n",
458 | "88 {'height': 3264, 'width': 4928, 'id': 88, 'file_name': 'DSC_4678.JPG'}\n",
459 | "89 {'height': 3264, 'width': 4928, 'id': 89, 'file_name': 'DSC_4506.JPG'}\n",
460 | "90 {'height': 692, 'width': 924, 'id': 90, 'file_name': '23.jpg'}\n",
461 | "91 {'height': 982, 'width': 1843, 'id': 91, 'file_name': 'DSC_5012.JPG'}\n",
462 | "92 {'height': 168, 'width': 300, 'id': 92, 'file_name': '9.jpg'}\n",
463 | "93 {'height': 3264, 'width': 4928, 'id': 93, 'file_name': 'DSC_4584.JPG'}\n"
464 | ]
465 | }
466 | ],
467 | "source": [
468 | "for k, v in coco_dataset.images.items():\n",
469 | " print(k, v)"
470 | ]
471 | },
472 | {
473 | "cell_type": "code",
474 | "execution_count": 6,
475 | "metadata": {
476 | "ExecuteTime": {
477 | "end_time": "2019-07-27T08:58:05.587373Z",
478 | "start_time": "2019-07-27T08:58:05.574383Z"
479 | }
480 | },
481 | "outputs": [
482 | {
483 | "name": "stdout",
484 | "output_type": "stream",
485 | "text": [
486 | "Image:\n",
487 | "======\n",
488 | " height: 3264\n",
489 | " width: 4928\n",
490 | " id: 1\n",
491 | " file_name: DSC_4682.JPG\n",
492 | " segmentations (3):\n",
493 | " 5:blue:{'supercategory': 'land', 'id': 1, 'name': 'land'}\n",
494 | " 6:purple:{'supercategory': 'ship', 'id': 2, 'name': 'ship'}\n",
495 | " 7:red:{'supercategory': 'buoy', 'id': 0, 'name': 'buoy'}\n"
496 | ]
497 | },
498 | {
499 | "data": {
500 | "text/html": [
501 | "
"
505 | ],
506 | "text/plain": [
507 | ""
508 | ]
509 | },
510 | "execution_count": 6,
511 | "metadata": {},
512 | "output_type": "execute_result"
513 | }
514 | ],
515 | "source": [
516 | "html = coco_dataset.display_image(1, use_url=False)\n",
517 | "IPython.display.HTML(html)"
518 | ]
519 | },
520 | {
521 | "cell_type": "code",
522 | "execution_count": 7,
523 | "metadata": {},
524 | "outputs": [
525 | {
526 | "name": "stdout",
527 | "output_type": "stream",
528 | "text": [
529 | "Image:\n",
530 | "======\n",
531 | " height: 3264\n",
532 | " width: 4928\n",
533 | " id: 2\n",
534 | " file_name: DSC_4505.JPG\n",
535 | " segmentations (4):\n",
536 | " 8:blue:{'supercategory': 'land', 'id': 1, 'name': 'land'}\n",
537 | " 9:purple:{'supercategory': 'buoy', 'id': 0, 'name': 'buoy'}\n",
538 | " 10:red:{'supercategory': 'buoy', 'id': 0, 'name': 'buoy'}\n",
539 | " 11:green:{'supercategory': 'buoy', 'id': 0, 'name': 'buoy'}\n"
540 | ]
541 | },
542 | {
543 | "data": {
544 | "text/html": [
545 | "
"
549 | ],
550 | "text/plain": [
551 | ""
552 | ]
553 | },
554 | "execution_count": 7,
555 | "metadata": {},
556 | "output_type": "execute_result"
557 | }
558 | ],
559 | "source": [
560 | "html = coco_dataset.display_image(2, use_url=False)\n",
561 | "IPython.display.HTML(html)"
562 | ]
563 | },
564 | {
565 | "cell_type": "code",
566 | "execution_count": 8,
567 | "metadata": {},
568 | "outputs": [
569 | {
570 | "name": "stdout",
571 | "output_type": "stream",
572 | "text": [
573 | "Image:\n",
574 | "======\n",
575 | " height: 3264\n",
576 | " width: 4928\n",
577 | " id: 3\n",
578 | " file_name: DSC_4591.JPG\n",
579 | " segmentations (3):\n",
580 | " 12:blue:{'supercategory': 'land', 'id': 1, 'name': 'land'}\n",
581 | " 13:purple:{'supercategory': 'land', 'id': 1, 'name': 'land'}\n",
582 | " 14:red:{'supercategory': 'buoy', 'id': 0, 'name': 'buoy'}\n"
583 | ]
584 | },
585 | {
586 | "data": {
587 | "text/html": [
588 | "
"
589 | ],
590 | "text/plain": [
591 | ""
592 | ]
593 | },
594 | "execution_count": 8,
595 | "metadata": {},
596 | "output_type": "execute_result"
597 | }
598 | ],
599 | "source": [
600 | "html = coco_dataset.display_image(3, use_url=False)\n",
601 | "IPython.display.HTML(html)"
602 | ]
603 | },
604 | {
605 | "cell_type": "code",
606 | "execution_count": 9,
607 | "metadata": {},
608 | "outputs": [
609 | {
610 | "name": "stdout",
611 | "output_type": "stream",
612 | "text": [
613 | "Image:\n",
614 | "======\n",
615 | " height: 3264\n",
616 | " width: 4928\n",
617 | " id: 4\n",
618 | " file_name: DSC_4657.JPG\n",
619 | " segmentations (7):\n",
620 | " 15:blue:{'supercategory': 'ship', 'id': 2, 'name': 'ship'}\n",
621 | " 16:purple:{'supercategory': 'ship', 'id': 2, 'name': 'ship'}\n",
622 | " 17:red:{'supercategory': 'ship', 'id': 2, 'name': 'ship'}\n",
623 | " 18:green:{'supercategory': 'buoy', 'id': 0, 'name': 'buoy'}\n",
624 | " 19:orange:{'supercategory': 'land', 'id': 1, 'name': 'land'}\n",
625 | " 20:salmon:{'supercategory': 'land', 'id': 1, 'name': 'land'}\n",
626 | " 21:pink:{'supercategory': 'land', 'id': 1, 'name': 'land'}\n"
627 | ]
628 | },
629 | {
630 | "data": {
631 | "text/html": [
632 | "
"
634 | ],
635 | "text/plain": [
636 | ""
637 | ]
638 | },
639 | "execution_count": 9,
640 | "metadata": {},
641 | "output_type": "execute_result"
642 | }
643 | ],
644 | "source": [
645 | "html = coco_dataset.display_image(4, use_url=False)\n",
646 | "IPython.display.HTML(html)"
647 | ]
648 | },
649 | {
650 | "cell_type": "code",
651 | "execution_count": 10,
652 | "metadata": {},
653 | "outputs": [
654 | {
655 | "name": "stdout",
656 | "output_type": "stream",
657 | "text": [
658 | "Image:\n",
659 | "======\n",
660 | " height: 3264\n",
661 | " width: 4928\n",
662 | " id: 19\n",
663 | " file_name: DSC_4586.JPG\n",
664 | " segmentations (1):\n",
665 | " 52:blue:{'supercategory': 'land', 'id': 1, 'name': 'land'}\n",
666 | "Image:\n",
667 | "======\n",
668 | " height: 3264\n",
669 | " width: 4928\n",
670 | " id: 1\n",
671 | " file_name: DSC_4682.JPG\n",
672 | " segmentations (3):\n",
673 | " 5:blue:{'supercategory': 'land', 'id': 1, 'name': 'land'}\n",
674 | " 6:purple:{'supercategory': 'ship', 'id': 2, 'name': 'ship'}\n",
675 | " 7:red:{'supercategory': 'buoy', 'id': 0, 'name': 'buoy'}\n"
676 | ]
677 | },
678 | {
679 | "data": {
680 | "text/html": [
681 | "
"
685 | ],
686 | "text/plain": [
687 | ""
688 | ]
689 | },
690 | "execution_count": 10,
691 | "metadata": {},
692 | "output_type": "execute_result"
693 | }
694 | ],
695 | "source": [
696 | "for i in 19,1:\n",
697 | " html = coco_dataset.display_image(i, use_url=False)\n",
698 | " \n",
699 | "IPython.display.HTML(html)"
700 | ]
701 | },
702 | {
703 | "cell_type": "code",
704 | "execution_count": null,
705 | "metadata": {},
706 | "outputs": [],
707 | "source": []
708 | },
709 | {
710 | "cell_type": "code",
711 | "execution_count": null,
712 | "metadata": {},
713 | "outputs": [],
714 | "source": []
715 | },
716 | {
717 | "cell_type": "code",
718 | "execution_count": null,
719 | "metadata": {},
720 | "outputs": [],
721 | "source": []
722 | }
723 | ],
724 | "metadata": {
725 | "kernelspec": {
726 | "display_name": "Python 3",
727 | "language": "python",
728 | "name": "python3"
729 | },
730 | "language_info": {
731 | "codemirror_mode": {
732 | "name": "ipython",
733 | "version": 3
734 | },
735 | "file_extension": ".py",
736 | "mimetype": "text/x-python",
737 | "name": "python",
738 | "nbconvert_exporter": "python",
739 | "pygments_lexer": "ipython3",
740 | "version": "3.7.7"
741 | },
742 | "toc": {
743 | "base_numbering": 1,
744 | "nav_menu": {},
745 | "number_sections": true,
746 | "sideBar": true,
747 | "skip_h1_title": false,
748 | "title_cell": "Table of Contents",
749 | "title_sidebar": "Contents",
750 | "toc_cell": false,
751 | "toc_position": {},
752 | "toc_section_display": true,
753 | "toc_window_display": false
754 | }
755 | },
756 | "nbformat": 4,
757 | "nbformat_minor": 2
758 | }
759 |
--------------------------------------------------------------------------------
/Detectron2_COCO_DataSegmentation_from_Marine_checkpoints.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Spyder Editor
4 |
5 | This is a temporary script file.
6 |
7 | First, Import all variables
8 | """
9 | import detectron2
10 | from detectron2.data import DatasetCatalog, MetadataCatalog
11 |
12 | import matplotlib.pyplot as plt
13 | import random
14 | import os
15 | import cv2
16 |
17 |
18 | #from detectron2.engine import DefaultTrainer
19 | from detectron2.utils.visualizer import Visualizer
20 | from detectron2.config import get_cfg
21 | from detectron2 import model_zoo
22 | from detectron2.engine import DefaultPredictor
23 | from detectron2.utils.visualizer import ColorMode
24 |
25 | '''
26 | # download, decompress the data in Colab where much faster
27 | !wget https://cbpetro.s3.us-east-2.amazonaws.com/api/download/data.zip
28 | !unzip data.zip > /dev/null
29 | '''
30 |
31 | import wget
32 |
33 | '''
34 | Download the data.zip file only once and then comment out the following 7 lines
35 | '''
36 | # url = 'https://cbpetro.s3.us-east-2.amazonaws.com/api/download/data.zip'
37 | # wget.download(url, './data.zip')
38 |
39 | # from zipfile import ZipFile
40 | # zf = ZipFile('./data.zip', 'r')
41 | # zf.extractall('./')
42 | # zf.close()
43 |
44 |
45 |
46 |
47 | '''
48 | Register coco instance
49 | '''
50 | from detectron2.data.datasets import register_coco_instances
51 | register_coco_instances("nautical_ecp", {}, "./data/trainval.json", "./data/images")
52 |
53 | nautical_metadata = MetadataCatalog.get("nautical_ecp")
54 | dataset_dicts = DatasetCatalog.get("nautical_ecp")
55 |
56 |
57 | '''
58 | Get ready to read models
59 | '''
60 | cfg = get_cfg()
61 | cfg.MODEL.DEVICE = "cpu"
62 | cfg.merge_from_file(model_zoo.get_config_file("COCO-Detection/faster_rcnn_R_50_FPN_1x.yaml"))
63 | #cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml")
64 | cfg.DATASETS.TRAIN = ("nautical_ecp",)
65 |
66 | cfg.MODEL.ROI_HEADS.NUM_CLASSES = 5
67 |
68 |
69 | '''
70 | Load Weights
71 | '''
72 | cfg.OUTPUT_DIR = "./output"
73 | cfg.MODEL.WEIGHTS = os.path.join(cfg.OUTPUT_DIR, "model_final.pth")
74 | cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.7 # set the testing threshold for this model
75 | cfg.DATASETS.TEST = ("nautical_ecp", )
76 | predictor = DefaultPredictor(cfg)
77 |
78 |
79 |
80 | '''
81 | Random images from training set
82 | '''
83 | for d in random.sample(dataset_dicts, 1):
84 | im = cv2.imread(d["file_name"])
85 | outputs = predictor(im)
86 | v = Visualizer(im[:, :, ::-1],
87 | metadata=nautical_metadata,
88 | scale=0.8,
89 | #instance_mode=ColorMode.IMAGE_BW # remove the colors of unsegmented pixels
90 | )
91 | v = v.draw_instance_predictions(outputs["instances"].to("cpu"))
92 | plt.imshow(v.get_image()[:, :, ::-1])
93 | plt.show()
94 |
95 |
96 |
97 | '''
98 | Random images from boats set not used in training
99 | '''
100 | for i in range(2,29,1):
101 | nautical_img_no = str(i)
102 | img = os.path.join("./data_val/images-" +nautical_img_no + ".jpeg") #1-24 in boats
103 | print(img)
104 | im = cv2.imread(img)
105 | outputs = predictor(im)
106 | v = Visualizer(im[:, :, ::-1],
107 | metadata=nautical_metadata,
108 | scale=0.8,
109 | #instance_mode=ColorMode.IMAGE_BW # remove the colors of unsegmented pixels
110 | )
111 | v = v.draw_instance_predictions(outputs["instances"].to("cpu"))
112 | #cv2_imshow(v.get_image()[:, :, ::-1])
113 | plt.imshow(v.get_image()[:, :, ::-1])
114 | plt.show()
115 |
116 |
117 |
118 |
119 |
120 | '''
121 | This is how you load and predict discrete images
122 | '''
123 | im = cv2.imread("./data_val/images-28.jpeg")
124 | outputs = predictor(im)
125 | v = Visualizer(im[:, :, ::-1],
126 | metadata=nautical_metadata,
127 | scale=0.8,
128 | )
129 | v = v.draw_instance_predictions(outputs["instances"].to("cpu"))
130 | plt.imshow(v.get_image()[:, :, ::-1])
131 | plt.show()
132 |
133 |
134 |
--------------------------------------------------------------------------------
/Detectron2_custom_coco_data_instance_segmentation_marine_ver5_TRAIN_Colab.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "Detectron2_custom_coco_data_instance_segmentation_marine_ver5_TRAIN.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "toc_visible": true
10 | },
11 | "kernelspec": {
12 | "name": "python3",
13 | "display_name": "Python 3"
14 | },
15 | "accelerator": "GPU"
16 | },
17 | "cells": [
18 | {
19 | "cell_type": "markdown",
20 | "metadata": {
21 | "id": "QHnVupBBn9eR",
22 | "colab_type": "text"
23 | },
24 | "source": [
25 | "# [How to train Detectron2 with Custom COCO Datasets](https://www.dlology.com/blog/how-to-train-detectron2-with-custom-coco-datasets/) | DLology\n",
26 | "\n",
27 | "
\n",
28 | "\n",
29 | "This notebook will help you get started with this framwork by training a instance segmentation model with your custom COCO datasets."
30 | ]
31 | },
32 | {
33 | "cell_type": "markdown",
34 | "metadata": {
35 | "id": "vM54r6jlKTII",
36 | "colab_type": "text"
37 | },
38 | "source": [
39 | "# Install detectron2"
40 | ]
41 | },
42 | {
43 | "cell_type": "code",
44 | "metadata": {
45 | "id": "9_FzH13EjseR",
46 | "colab_type": "code",
47 | "colab": {}
48 | },
49 | "source": [
50 | "#!pip install -U torch torchvision\n",
51 | "!pip install git+https://github.com/facebookresearch/fvcore.git\n",
52 | "import torch, torchvision\n",
53 | "torch.__version__"
54 | ],
55 | "execution_count": 0,
56 | "outputs": []
57 | },
58 | {
59 | "cell_type": "code",
60 | "metadata": {
61 | "id": "b-i4hmGYk1dL",
62 | "colab_type": "code",
63 | "colab": {}
64 | },
65 | "source": [
66 | "#!git clone https://github.com/facebookresearch/detectron2 detectron2_repo\n",
67 | "#!pip install -e detectron2_repo\n",
68 | "#!pip install detectron2 -f https://github.com/facebookresearch/detectron2\n",
69 | "# install detectron2:\n",
70 | "!pip install detectron2 -f https://dl.fbaipublicfiles.com/detectron2/wheels/cu100/index.html"
71 | ],
72 | "execution_count": 0,
73 | "outputs": []
74 | },
75 | {
76 | "cell_type": "code",
77 | "metadata": {
78 | "id": "ZyAvNCJMmvFF",
79 | "colab_type": "code",
80 | "colab": {}
81 | },
82 | "source": [
83 | "# You may need to restart your runtime prior to this, to let your installation take effect\n",
84 | "# Some basic setup\n",
85 | "# Setup detectron2 logger\n",
86 | "import detectron2\n",
87 | "from detectron2.utils.logger import setup_logger\n",
88 | "setup_logger()\n",
89 | "\n",
90 | "# import some common libraries\n",
91 | "import matplotlib.pyplot as plt\n",
92 | "import numpy as np\n",
93 | "import cv2\n",
94 | "from google.colab.patches import cv2_imshow\n",
95 | "\n",
96 | "# import some common detectron2 utilities\n",
97 | "from detectron2.engine import DefaultPredictor\n",
98 | "from detectron2.config import get_cfg\n",
99 | "from detectron2.utils.visualizer import Visualizer\n",
100 | "from detectron2.data import MetadataCatalog, DatasetCatalog"
101 | ],
102 | "execution_count": 0,
103 | "outputs": []
104 | },
105 | {
106 | "cell_type": "markdown",
107 | "metadata": {
108 | "id": "b2bjrfb2LDeo",
109 | "colab_type": "text"
110 | },
111 | "source": [
112 | "# Train on a custom COCO dataset"
113 | ]
114 | },
115 | {
116 | "cell_type": "markdown",
117 | "metadata": {
118 | "id": "tjbUIhSxUdm_",
119 | "colab_type": "text"
120 | },
121 | "source": [
122 | "In this section, we show how to train an existing detectron2 model on a custom dataset in a new format.\n",
123 | "\n",
124 | "We use [the marine segmentation dataset](https://github.com/Allopart/Maritme_Mask_RCNN)\n",
125 | "which only has 5 classes: data, buoy, land, sea, ship and sky.\n",
126 | "We'll train a segmentation model from an existing model pre-trained on the COCO dataset, available in detectron2's model zoo.\n",
127 | "\n",
128 | "Note that the COCO dataset does not have the \"data\", \"buoy\" and \"sea\" categories."
129 | ]
130 | },
131 | {
132 | "cell_type": "code",
133 | "metadata": {
134 | "id": "4Qg7zSVOulkb",
135 | "colab_type": "code",
136 | "colab": {}
137 | },
138 | "source": [
139 | "# download, decompress the data\n",
140 | "!wget https://cbpetro.s3.us-east-2.amazonaws.com/api/download/data.zip\n",
141 | "!unzip data.zip > /dev/null"
142 | ],
143 | "execution_count": 0,
144 | "outputs": []
145 | },
146 | {
147 | "cell_type": "markdown",
148 | "metadata": {
149 | "id": "tVJoOm6LVJwW",
150 | "colab_type": "text"
151 | },
152 | "source": [
153 | "Register the fruits_nuts dataset to detectron2, following the [detectron2 custom dataset tutorial](https://detectron2.readthedocs.io/tutorials/datasets.html).\n"
154 | ]
155 | },
156 | {
157 | "cell_type": "code",
158 | "metadata": {
159 | "id": "Lnkg1PByUjGQ",
160 | "colab_type": "code",
161 | "colab": {}
162 | },
163 | "source": [
164 | "from detectron2.data.datasets import register_coco_instances\n",
165 | "register_coco_instances(\"nautical_ecp\", {}, \"./data/trainval.json\", \"./data/images\")"
166 | ],
167 | "execution_count": 0,
168 | "outputs": []
169 | },
170 | {
171 | "cell_type": "code",
172 | "metadata": {
173 | "id": "MWknKqWTWIw9",
174 | "colab_type": "code",
175 | "colab": {}
176 | },
177 | "source": [
178 | "nautical_metadata = MetadataCatalog.get(\"nautical_ecp\")\n",
179 | "dataset_dicts = DatasetCatalog.get(\"nautical_ecp\")"
180 | ],
181 | "execution_count": 0,
182 | "outputs": []
183 | },
184 | {
185 | "cell_type": "markdown",
186 | "metadata": {
187 | "id": "6ljbWTX0Wi8E",
188 | "colab_type": "text"
189 | },
190 | "source": [
191 | "To verify the data loading is correct, let's visualize the annotations of randomly selected samples in the training set:\n",
192 | "\n"
193 | ]
194 | },
195 | {
196 | "cell_type": "code",
197 | "metadata": {
198 | "id": "UkNbUzUOLYf0",
199 | "colab_type": "code",
200 | "colab": {}
201 | },
202 | "source": [
203 | "import random\n",
204 | "\n",
205 | "for d in random.sample(dataset_dicts, 1):\n",
206 | " img = cv2.imread(d[\"file_name\"])\n",
207 | " visualizer = Visualizer(img[:, :, ::-1], metadata=nautical_metadata, scale=0.5)\n",
208 | " vis = visualizer.draw_dataset_dict(d)\n",
209 | " cv2_imshow(vis.get_image()[:, :, ::-1])"
210 | ],
211 | "execution_count": 0,
212 | "outputs": []
213 | },
214 | {
215 | "cell_type": "markdown",
216 | "metadata": {
217 | "id": "wlqXIXXhW8dA",
218 | "colab_type": "text"
219 | },
220 | "source": [
221 | "Now, let's fine-tune a coco-pretrained R50-FPN Mask R-CNN model on the Nautical dataset. It takes ~6 minutes to train 300 iterations on Colab's K80 GPU.\n"
222 | ]
223 | },
224 | {
225 | "cell_type": "code",
226 | "metadata": {
227 | "id": "7unkuuiqLdqd",
228 | "colab_type": "code",
229 | "colab": {}
230 | },
231 | "source": [
232 | "from detectron2.engine import DefaultTrainer\n",
233 | "from detectron2.config import get_cfg\n",
234 | "from detectron2 import model_zoo\n",
235 | "import os\n",
236 | "\n",
237 | "cfg = get_cfg()\n",
238 | "cfg.merge_from_file(model_zoo.get_config_file(\"COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml\"))\n",
239 | "cfg.DATASETS.TRAIN = (\"nautical_ecp\",)\n",
240 | "cfg.DATASETS.TEST = () # no metrics implemented for this dataset\n",
241 | "cfg.DATALOADER.NUM_WORKERS = 2\n",
242 | "cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url(\"COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml\") # Let training initialize from model zoo\n",
243 | "cfg.SOLVER.IMS_PER_BATCH = 2\n",
244 | "cfg.SOLVER.BASE_LR = 0.002\n",
245 | "cfg.SOLVER.MAX_ITER = 300 # 300 iterations seems good enough, but you can certainly train longer\n",
246 | "cfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = 128 # faster, and good enough for this toy dataset\n",
247 | "cfg.MODEL.ROI_HEADS.NUM_CLASSES = 3 # 3 classes (buoy, land, ship)\n",
248 | "\n",
249 | "#os.makedirs(cfg.OUTPUT_DIR, exist_ok=True)\n",
250 | "os.makedirs(cfg.OUTPUT_DIR, exist_ok=True)\n",
251 | "trainer = DefaultTrainer(cfg)\n",
252 | "trainer.resume_or_load(resume=False)\n",
253 | "trainer.train()"
254 | ],
255 | "execution_count": 0,
256 | "outputs": []
257 | },
258 | {
259 | "cell_type": "code",
260 | "metadata": {
261 | "id": "JY67ava3nsnh",
262 | "colab_type": "code",
263 | "colab": {}
264 | },
265 | "source": [
266 | "# Look at training curves in tensorboard:\n",
267 | "%load_ext tensorboard\n",
268 | "%tensorboard --logdir output"
269 | ],
270 | "execution_count": 0,
271 | "outputs": []
272 | },
273 | {
274 | "cell_type": "markdown",
275 | "metadata": {
276 | "id": "0e4vdDIOXyxF",
277 | "colab_type": "text"
278 | },
279 | "source": [
280 | "Now, we perform inference with the trained model on the nautical dataset. First, let's create a predictor using the model we just trained:\n",
281 | "\n"
282 | ]
283 | },
284 | {
285 | "cell_type": "code",
286 | "metadata": {
287 | "id": "Ya5nEuMELeq8",
288 | "colab_type": "code",
289 | "colab": {}
290 | },
291 | "source": [
292 | "# Directory where output files are written\n",
293 | "cfg.OUTPUT_DIR = \"./output\"\n",
294 | "\n",
295 | "cfg.MODEL.WEIGHTS = os.path.join(cfg.OUTPUT_DIR, \"model_final.pth\")\n",
296 | "cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.7 # set the testing threshold for this model\n",
297 | "cfg.DATASETS.TEST = (\"nautical_ecp\", )\n",
298 | "predictor = DefaultPredictor(cfg)"
299 | ],
300 | "execution_count": 0,
301 | "outputs": []
302 | },
303 | {
304 | "cell_type": "markdown",
305 | "metadata": {
306 | "id": "qWq1XHfDWiXO",
307 | "colab_type": "text"
308 | },
309 | "source": [
310 | "Then, we randomly select several samples to visualize the prediction results."
311 | ]
312 | },
313 | {
314 | "cell_type": "code",
315 | "metadata": {
316 | "id": "U5LhISJqWXgM",
317 | "colab_type": "code",
318 | "colab": {}
319 | },
320 | "source": [
321 | "from detectron2.utils.visualizer import ColorMode\n",
322 | "\n",
323 | "for d in random.sample(dataset_dicts, 1): \n",
324 | " im = cv2.imread(d[\"file_name\"])\n",
325 | " outputs = predictor(im)\n",
326 | " v = Visualizer(im[:, :, ::-1],\n",
327 | " metadata=nautical_metadata, \n",
328 | " scale=0.8, \n",
329 | " instance_mode=ColorMode.IMAGE_BW # remove the colors of unsegmented pixels\n",
330 | " )\n",
331 | " v = v.draw_instance_predictions(outputs[\"instances\"].to(\"cpu\"))\n",
332 | " cv2_imshow(v.get_image()[:, :, ::-1])\n",
333 | "\n"
334 | ],
335 | "execution_count": 0,
336 | "outputs": []
337 | },
338 | {
339 | "cell_type": "code",
340 | "metadata": {
341 | "id": "t_bo0cypwllj",
342 | "colab_type": "code",
343 | "colab": {}
344 | },
345 | "source": [
346 | "nautical_metadata"
347 | ],
348 | "execution_count": 0,
349 | "outputs": []
350 | },
351 | {
352 | "cell_type": "markdown",
353 | "metadata": {
354 | "id": "wZ6lYrCqLLLW",
355 | "colab_type": "text"
356 | },
357 | "source": [
358 | "## Benchmark inference speed"
359 | ]
360 | },
361 | {
362 | "cell_type": "code",
363 | "metadata": {
364 | "id": "PxRHYcAC_Z0f",
365 | "colab_type": "code",
366 | "colab": {}
367 | },
368 | "source": [
369 | "import time\n",
370 | "times = []\n",
371 | "for i in range(20):\n",
372 | " start_time = time.time()\n",
373 | " outputs = predictor(im)\n",
374 | " delta = time.time() - start_time\n",
375 | " times.append(delta)\n",
376 | "mean_delta = np.array(times).mean()\n",
377 | "fps = 1 / mean_delta\n",
378 | "print(\"Average(sec):{:.2f},fps:{:.2f}\".format(mean_delta, fps))"
379 | ],
380 | "execution_count": 0,
381 | "outputs": []
382 | },
383 | {
384 | "cell_type": "code",
385 | "metadata": {
386 | "id": "WFMOqBbWEh5v",
387 | "colab_type": "code",
388 | "colab": {}
389 | },
390 | "source": [
391 | "# Download the results\n",
392 | "#from google.colab import files\n",
393 | "#files.download('./output/metrics.json')\n",
394 | "#files.download('./output/model_final.pth')\n",
395 | "#files.download('./output/last_checkpoint')"
396 | ],
397 | "execution_count": 0,
398 | "outputs": []
399 | }
400 | ]
401 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Craig Phillips
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Marine Object Image Segmentation using FAIR's Detectron2
2 | This repository was inspired by the following Detectron2 tutorial:
3 |
4 | https://colab.research.google.com/drive/16jcaJoc6bCFAQ96jDe2HwtXj7BMD_-m5
5 |
6 | This tutorial is what led to this repository.
7 |
8 | According to Facebook AI Research (FAIR), "Detectron2 is Facebook AI Research's next generation software system that implements state-of-the-art object detection algorithms".
9 |
10 | https://github.com/facebookresearch/detectron2
11 |
12 | ## Objectives
13 | The objective of this project is to recognize nautical objects like buoys, ships or land forms while at sea using a video camera for real-time warnings. We plan on installing a low power drain Jetson Xavier on a boat with a video camera(s) to detect these nautical objects. This project is actually a follow up to Adrian Llopart Maurin's GitHub repository where he used Mask RCNN to train and predict Marine objects typically encountered at sea. Adrian labeled his images (using labelme?) to detect ships, buoys, land, sea and sky. This is agreat objective, but we have decided only to predict ships, buoys and land forms in this repository.
14 |
15 | https://github.com/Allopart/Maritme_Mask_RCNN
16 |
17 | We used Adrian's Marine image dataset as our training set, which also included all of his the labelme .json file labels. Adrian used a Panoptic Segmentation approach were he labeled the entire image for ships, buoys, land, sea and sky. For this repository; however, we edited Adrian's nautical images and labels in labelme and eliminated sea and sky. For our next panoptic segmentation project coming up next if we can figure out how to train for this (errors now in Colab training), we will go back to Arian's comprehensive labeling approach.
18 |
19 |
20 | ## Marine Labels
21 | The following image is an example of an buoy being labeled in labelme to be used in training.
22 |
23 | >
24 |
25 | Adrian's training dataset was composed of images and separate .json for each image. We used Chengwei Zhang's GitHub repository (see link below) to combine all the individual .json files obtained on each image. Labelme creates these individual json files from each image. With Chengwei's program we created the single trainval.json file used in training by Detectron2. We ran Chengwei's program using the following command line:
26 |
27 | python labelme2coco.py .data/images
28 |
29 | https://github.com/Tony607/labelme2coco
30 |
31 | Chengwei also included a notebook that was created to evaluate and scan the individual image results as a qc check before starting the training in Colab. This notebook is called COCO_Image_Viewer.ipynb, and it too is included in this repository with thanks to Chengwei.
32 |
33 | ## Data used for Training
34 | A subset to Adrian's images ca be accessed from the following AWS source:
35 |
36 | https://cbpetro.s3.us-east-2.amazonaws.com/api/download/data.zip
37 |
38 | This creates a folder called data and within this folder is the single trainval.json file and a folder called "images". We did observe that in the training, Detectron2 did not accept images in the portrait mode. Images in the portrait mode were eliminated from the training set. We used the following Colab notebook to train this nautical dataset on Colab:
39 |
40 | Detectron2_custom_coco_data_instance_segmentation_marine_ver5_TRAIN_Colab.ipynb
41 |
42 | Colab generates a weights file that are are stored in the Colab "/output/model_final.pth" directory. After performing the training, this file can be accessed in Colab by tapping on the folder icon to the very far left in the area of the Table of Contents in Colab and downloading the file. The weights are downloaded to your Download directory and can be placed in your Detectron2 project directory as "./output/model_fina.pth".
43 |
44 | Our nautical training weights can be downloaded from the following AWS link. Just click on it.
45 |
46 | https://cbpetro.s3.us-east-2.amazonaws.com/api/download/output.zip
47 |
48 |
49 | ## Predict Nautical Objects
50 | We used the following notebook to then predict our nautical objects like buoys, ships and land features from a validation image set downloaded from the web discussed below:
51 |
52 | Detectron2_COCO_DataSegmentation_from_Marine_checkpoints.ipynb
53 |
54 | or you can use the following python code in Spyder:
55 |
56 | Detectron2_COCO_DataSegmentation_from_Marine_checkpoints.py
57 |
58 | >
59 |
60 | We provide a data_val subdirectory with this GitHub repository. This folder has numerous images of nautical objects, all of which were not used in training process. These images are being used as validation of our model. The instance segmentation process appears to be working rather well as can be observed in the images below.
61 |
62 | >
63 |
64 | At this time we are a bit unclear as to how to employ a validation set in the actual Detectron2 training process. This will be added at a later date if found to add value, which it should.
65 |
66 | Tools being employed:
67 |
68 | - Colab for Detectron2 training and weights
69 | - NVIDIA's Jetson Xavier Development kit running Ubuntu 18.04 for low current draw on boat
70 | - Video Camera to be determined
71 | -------------------------------------------------------------------------------------------------------
72 | - Using OpenCPN on Xavier for Navigation aid other that just the chart plotters
73 | - Can send iPad GPS location data to OpenCPN using GPS2ZIP if necessary
74 | - On land using Boat Beacon with AIS targets being captured on iPad. OpenCPN is networked into Boat Beacon.
75 | - Can use python VDRplayer to stream from nmea .txt file to OpenCPN for display
76 | - iCom M506 AIS Receiver/VHF on nmea 2k network
77 | - NMEA2k Network needs to exploit this further and add wifi to boat NMEA 2k
78 |
79 |
80 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/composite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/composite.png
--------------------------------------------------------------------------------
/data_val/images-10.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-10.jpeg
--------------------------------------------------------------------------------
/data_val/images-11.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-11.jpeg
--------------------------------------------------------------------------------
/data_val/images-12.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-12.jpeg
--------------------------------------------------------------------------------
/data_val/images-13.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-13.jpeg
--------------------------------------------------------------------------------
/data_val/images-14.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-14.jpeg
--------------------------------------------------------------------------------
/data_val/images-15.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-15.jpeg
--------------------------------------------------------------------------------
/data_val/images-16.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-16.jpeg
--------------------------------------------------------------------------------
/data_val/images-17.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-17.jpeg
--------------------------------------------------------------------------------
/data_val/images-18.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-18.jpeg
--------------------------------------------------------------------------------
/data_val/images-19.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-19.jpeg
--------------------------------------------------------------------------------
/data_val/images-2.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-2.jpeg
--------------------------------------------------------------------------------
/data_val/images-20.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-20.jpeg
--------------------------------------------------------------------------------
/data_val/images-21.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-21.jpeg
--------------------------------------------------------------------------------
/data_val/images-22.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-22.jpeg
--------------------------------------------------------------------------------
/data_val/images-23.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-23.jpeg
--------------------------------------------------------------------------------
/data_val/images-24.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-24.jpeg
--------------------------------------------------------------------------------
/data_val/images-25.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-25.jpeg
--------------------------------------------------------------------------------
/data_val/images-26.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-26.jpeg
--------------------------------------------------------------------------------
/data_val/images-27.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-27.jpeg
--------------------------------------------------------------------------------
/data_val/images-28.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-28.jpeg
--------------------------------------------------------------------------------
/data_val/images-29.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-29.jpeg
--------------------------------------------------------------------------------
/data_val/images-3.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-3.jpeg
--------------------------------------------------------------------------------
/data_val/images-4.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-4.jpeg
--------------------------------------------------------------------------------
/data_val/images-5.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-5.jpeg
--------------------------------------------------------------------------------
/data_val/images-6.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-6.jpeg
--------------------------------------------------------------------------------
/data_val/images-7.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-7.jpeg
--------------------------------------------------------------------------------
/data_val/images-8.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-8.jpeg
--------------------------------------------------------------------------------
/data_val/images-9.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/data_val/images-9.jpeg
--------------------------------------------------------------------------------
/googlea2f7fa877a9207e5.html:
--------------------------------------------------------------------------------
1 | google-site-verification: googlea2f7fa877a9207e5.html
--------------------------------------------------------------------------------
/googlee5a896f21eabcd63.html:
--------------------------------------------------------------------------------
1 | google-site-verification: googlee5a896f21eabcd63.html
--------------------------------------------------------------------------------
/labelme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/labelme.png
--------------------------------------------------------------------------------
/labelme2coco.py:
--------------------------------------------------------------------------------
1 | import os
2 | import argparse
3 | import json
4 |
5 | from labelme import utils
6 | import numpy as np
7 | import glob
8 | import PIL.Image
9 |
10 |
11 | class labelme2coco(object):
12 | def __init__(self, labelme_json=[], save_json_path="./coco.json"):
13 | """
14 | :param labelme_json: the list of all labelme json file paths
15 | :param save_json_path: the path to save new json
16 | """
17 | self.labelme_json = labelme_json
18 | self.save_json_path = save_json_path
19 | self.images = []
20 | self.categories = []
21 | self.annotations = []
22 | self.label = []
23 | self.annID = 1
24 | self.height = 0
25 | self.width = 0
26 |
27 | self.save_json()
28 |
29 | def data_transfer(self):
30 | for num, json_file in enumerate(self.labelme_json):
31 | with open(json_file, "r") as fp:
32 | data = json.load(fp)
33 | self.images.append(self.image(data, num))
34 | for shapes in data["shapes"]:
35 | label = shapes["label"].split("_")
36 | if label not in self.label:
37 | self.label.append(label)
38 | points = shapes["points"]
39 | self.annotations.append(self.annotation(points, label, num))
40 | self.annID += 1
41 |
42 | # Sort all text labels so they are in the same order across data splits.
43 | self.label.sort()
44 | for label in self.label:
45 | self.categories.append(self.category(label))
46 | for annotation in self.annotations:
47 | annotation["category_id"] = self.getcatid(annotation["category_id"])
48 |
49 | def image(self, data, num):
50 | image = {}
51 | img = utils.img_b64_to_arr(data["imageData"])
52 | height, width = img.shape[:2]
53 | img = None
54 | image["height"] = height
55 | image["width"] = width
56 | image["id"] = num
57 | image["file_name"] = data["imagePath"].split("/")[-1]
58 |
59 | self.height = height
60 | self.width = width
61 |
62 | return image
63 |
64 | def category(self, label):
65 | category = {}
66 | category["supercategory"] = label[0]
67 | category["id"] = len(self.categories)
68 | category["name"] = label[0]
69 | return category
70 |
71 | def annotation(self, points, label, num):
72 | annotation = {}
73 | contour = np.array(points)
74 | x = contour[:, 0]
75 | y = contour[:, 1]
76 | area = 0.5 * np.abs(np.dot(x, np.roll(y, 1)) - np.dot(y, np.roll(x, 1)))
77 | annotation["segmentation"] = [list(np.asarray(points).flatten())]
78 | annotation["iscrowd"] = 0
79 | annotation["area"] = area
80 | annotation["image_id"] = num
81 |
82 | annotation["bbox"] = list(map(float, self.getbbox(points)))
83 |
84 | annotation["category_id"] = label[0] # self.getcatid(label)
85 | annotation["id"] = self.annID
86 | return annotation
87 |
88 | def getcatid(self, label):
89 | for category in self.categories:
90 | if label == category["name"]:
91 | return category["id"]
92 | print("label: {} not in categories: {}.".format(label, self.categories))
93 | exit()
94 | return -1
95 |
96 | def getbbox(self, points):
97 | polygons = points
98 | mask = self.polygons_to_mask([self.height, self.width], polygons)
99 | return self.mask2box(mask)
100 |
101 | def mask2box(self, mask):
102 |
103 | index = np.argwhere(mask == 1)
104 | rows = index[:, 0]
105 | clos = index[:, 1]
106 |
107 | left_top_r = np.min(rows) # y
108 | left_top_c = np.min(clos) # x
109 |
110 | right_bottom_r = np.max(rows)
111 | right_bottom_c = np.max(clos)
112 |
113 | return [
114 | left_top_c,
115 | left_top_r,
116 | right_bottom_c - left_top_c,
117 | right_bottom_r - left_top_r,
118 | ]
119 |
120 | def polygons_to_mask(self, img_shape, polygons):
121 | mask = np.zeros(img_shape, dtype=np.uint8)
122 | mask = PIL.Image.fromarray(mask)
123 | xy = list(map(tuple, polygons))
124 | PIL.ImageDraw.Draw(mask).polygon(xy=xy, outline=1, fill=1)
125 | mask = np.array(mask, dtype=bool)
126 | return mask
127 |
128 | def data2coco(self):
129 | data_coco = {}
130 | data_coco["images"] = self.images
131 | data_coco["categories"] = self.categories
132 | data_coco["annotations"] = self.annotations
133 | return data_coco
134 |
135 | def save_json(self):
136 | print("save coco json")
137 | self.data_transfer()
138 | self.data_coco = self.data2coco()
139 |
140 | print(self.save_json_path)
141 | os.makedirs(
142 | os.path.dirname(os.path.abspath(self.save_json_path)), exist_ok=True
143 | )
144 | json.dump(self.data_coco, open(self.save_json_path, "w"), indent=4)
145 |
146 |
147 | if __name__ == "__main__":
148 | import argparse
149 |
150 | parser = argparse.ArgumentParser(
151 | description="labelme annotation to coco data json file."
152 | )
153 | parser.add_argument(
154 | "labelme_images",
155 | help="Directory to labelme images and annotation json files.",
156 | type=str,
157 | )
158 | parser.add_argument(
159 | "--output", help="Output json file path.", default="trainval.json"
160 | )
161 | args = parser.parse_args()
162 | labelme_json = glob.glob(os.path.join(args.labelme_images, "*.json"))
163 | labelme2coco(labelme_json, args.output)
164 |
--------------------------------------------------------------------------------
/results.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Philliec459/Marine-ObjectDetection-and-InstanceSegmentation-using-Detectron2-developing-our-own-Training-Weights/f1ee9041502a60cf735e638b3d426521f2c5c7bb/results.png
--------------------------------------------------------------------------------