Skip to content

Commit

Permalink
Properly got script working with proper formatting. train/val tagging…
Browse files Browse the repository at this point in the history
… as well as holes still needs to be implemented, but this can finally be read in by coco
  • Loading branch information
speri203 committed Jul 15, 2020
1 parent 5bca079 commit 7baf5ec
Showing 1 changed file with 325 additions and 0 deletions.
325 changes: 325 additions & 0 deletions convert.ipynb
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
}

0 comments on commit 7baf5ec

Please sign in to comment.