-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Properly got script working with proper formatting. train/val tagging…
… as well as holes still needs to be implemented, but this can finally be read in by coco
- Loading branch information
Showing
1 changed file
with
325 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,325 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 1, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import os\n", | ||
"import json\n", | ||
"from pathlib import Path\n", | ||
"import datetime\n", | ||
"#from PIL import Image\n", | ||
"#from PIL.ExifTags import TAGS\n", | ||
"import numpy as np\n", | ||
"from skimage import draw\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 2, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"def polygon_area_calculation(x_inputs, y_inputs):\n", | ||
" '''\n", | ||
" Function generate a list of all coordinates that are found within the polygon object.\n", | ||
" Generates a list of x and y coordinates of the same length (they are pairs). In order to\n", | ||
" access the coordinates, step through each list (x_coordiantes, y_coordinates) at the same rate\n", | ||
" ie. one for loop with len(x_coordinates)\n", | ||
" :param x_inputs: list of x coordinates from the annotated json file\n", | ||
" :param y_inputs: list of y coordinates from the annotated json file\n", | ||
" :return: x_coordinates, y_coordinates which hold the x and y, respectively, coordinates of the polygon.\n", | ||
" '''\n", | ||
" r = np.array(x_inputs)\n", | ||
" c = np.array(y_inputs)\n", | ||
" x_coordinates, y_coordinates = draw.polygon(r, c)\n", | ||
" return x_coordinates, y_coordinates\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 3, | ||
"metadata": { | ||
"tags": [] | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"## Opening up meta.json file to figure out classes and class ids\n", | ||
"with open(\"config.json\") as json_file:\n", | ||
" content = json.load(json_file)\n", | ||
"classes = [stuff for stuff in content['class_title_to_idx'] if stuff != 'bg']\n", | ||
"\n", | ||
"## Class ids can be assigned in the order seen in classes. 'bg' will always be class id 0.\n", | ||
"## Indexes should be starting at 1\n", | ||
"mappedClasses = {c: i+1 for i, c in enumerate(classes)}" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 4, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"## JSON structure that will define the classes and ids to be used witin the file. This will be appended at the end\n", | ||
"catg_repr = [{\n", | ||
" \"id\": v,\n", | ||
" \"name\": k,\n", | ||
" \"supercategory\": \"type\"\n", | ||
" } for k,v in mappedClasses.items()]" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 5, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"## Directories to pull annotations and images from \n", | ||
"ann_directory = Path('ann')\n", | ||
"images_directory = Path('images')" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 7, | ||
"metadata": { | ||
"tags": [] | ||
}, | ||
"outputs": [ | ||
{ | ||
"output_type": "stream", | ||
"name": "stdout", | ||
"text": "Lenght filenames: 10 Length json_content: 10\n" | ||
} | ||
], | ||
"source": [ | ||
"## Loading up all the JSON filenames and their content into lists, this will get all File I/O initially\n", | ||
"filenames = []\n", | ||
"json_content = []\n", | ||
"for annotation_files in os.listdir(ann_directory):\n", | ||
" image_filename = annotation_files[:-5]\n", | ||
" with open(ann_directory / annotation_files) as fp:\n", | ||
" content = json.load(fp)\n", | ||
" filenames.append(image_filename)\n", | ||
" json_content.append(content)\n", | ||
"\n", | ||
"print(\"Lenght filenames: {} Length json_content: {}\".format(len(filenames), len(json_content)))\n", | ||
" " | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 8, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"## Dictionary holding general metadata about the project \n", | ||
"info = [{\n", | ||
" \"description\": \"Converting Supervisely JSON format polygons into COCO. (Work in progress)\",\n", | ||
" \"url\": \"null\",\n", | ||
" \"version\": \"1.0\",\n", | ||
" \"year\": datetime.datetime.now().year,\n", | ||
" \"contributor\": \"Original Script by Caio Marcellos, Modified by Sai Peri to work properly.\",\n", | ||
" \"date_created\": datetime.datetime.now().isoformat()\n", | ||
"}]" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 9, | ||
"metadata": { | ||
"tags": [] | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"## Dictionary holding general metadata about the project \n", | ||
"licenses = [{\n", | ||
" \"url\": \"null\",\n", | ||
" \"id\": 1,\n", | ||
" \"name\": \"Name of License\"\n", | ||
"}]" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 10, | ||
"metadata": { | ||
"tags": [] | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"images = []\n", | ||
"for i, files in enumerate(filenames):\n", | ||
" ## Generate absolute filepath for the image corresponding to the JSON file\n", | ||
" image_filepath = images_directory / files\n", | ||
" image_filepath = image_filepath.absolute()\n", | ||
" \n", | ||
" ## Open up image and get metadata about height, width, date_captured\n", | ||
" ## Unfortunately our dataset does not have proper metadata to extract this type of information\n", | ||
" #image = Image.open(image_filepath)\n", | ||
" #exif_data = image.getexif()\n", | ||
"\n", | ||
" images.append({\"license\": 1,\n", | ||
" \"file_name\": str(image_filepath),\n", | ||
" \"height\": 512,\n", | ||
" \"width\": 640,\n", | ||
" \"date_captured\": datetime.datetime.now().isoformat(),\n", | ||
" \"id\": i})" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 11, | ||
"metadata": { | ||
"tags": [] | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"## Generate annotations for each of the objects detected within supervisely JSON file\n", | ||
"## Currently only dumps coordinates from exterior into segmentation. \n", | ||
"## TODO: Incorperate holes, interior, and rebuild contour based on new coordiantes\n", | ||
"## TODO: Train/val tagging\n", | ||
"annotations = []\n", | ||
"annotation_id = 0\n", | ||
"for i, json_files in enumerate(json_content):\n", | ||
" objects = json_files['objects']\n", | ||
" for data in objects:\n", | ||
" classTitle = data['classTitle']\n", | ||
" class_id = mappedClasses.get(classTitle)\n", | ||
" #print(\"classTitle: {} | class_id: {}\".format(classTitle, class_id))\n", | ||
" exterior = data['points']['exterior']\n", | ||
" segmentation = []\n", | ||
" x = []\n", | ||
" y = []\n", | ||
" for poly_points in exterior:\n", | ||
" x.append(poly_points[1])\n", | ||
" y.append(poly_points[0])\n", | ||
" segmentation.append(poly_points[1])\n", | ||
" segmentation.append(poly_points[0])\n", | ||
" \n", | ||
" bbox_coordinates = [min(x), min(y), max(x), max(y)]\n", | ||
"\n", | ||
" ## Generating all coordinates within polygon shape to count area. Caio's implementation was not doing calculation\n", | ||
" ## based on each class but rather just kept appending\n", | ||
" x_coord, y_coord = polygon_area_calculation(x, y)\n", | ||
" #print(\"Filename: {} | Classname: {} | Area: {}\".format(filenames[i], classTitle, len(x_coord)))\n", | ||
" \n", | ||
" ## Appending annotation\n", | ||
" annotations.append({\n", | ||
" \"segmentation\": [segmentation],\n", | ||
" \"area\": len(x_coord),\n", | ||
" \"iscrowd\": 0,\n", | ||
" \"image_id\": i,\n", | ||
" \"bbox\": bbox_coordinates,\n", | ||
" \"category_id\": class_id,\n", | ||
" \"id\": annotation_id\n", | ||
" })\n", | ||
" annotation_id += 1\n", | ||
" #print(annotations)\n", | ||
"\n", | ||
" \n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 12, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"coco_fmt = {\n", | ||
" \"info\": info,\n", | ||
" \"images\": images,\n", | ||
" \"annotations\": annotations,\n", | ||
" \"licenses\": licenses,\n", | ||
" \"categories\": catg_repr\n", | ||
"}" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 13, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"class NpEncoder(json.JSONEncoder):\n", | ||
" def default(self, obj): #pylint: disable=method-hidden\n", | ||
" if isinstance(obj, np.integer):\n", | ||
" return int(obj)\n", | ||
" elif isinstance(obj, np.floating):\n", | ||
" return float(obj)\n", | ||
" elif isinstance(obj, np.ndarray):\n", | ||
" return obj.tolist()\n", | ||
" else:\n", | ||
" return super(NpEncoder, self).default(obj)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 16, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"with open(os.curdir + \"\\\\instances_test2014.json\", \"w\") as fp:\n", | ||
" json.dump(coco_fmt, fp, cls=NpEncoder)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [] | ||
} | ||
], | ||
"metadata": { | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.7.7-final" | ||
}, | ||
"orig_nbformat": 2, | ||
"kernelspec": { | ||
"name": "python_defaultSpec_1594844622175", | ||
"display_name": "Python 3.7.7 64-bit ('heatloss': conda)" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |