diff --git a/.github/coco.png b/.github/coco.png deleted file mode 100644 index 93a36fd..0000000 Binary files a/.github/coco.png and /dev/null differ diff --git a/README.md b/README.md index 8d88fcc..6923414 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ![CircleCI](https://circleci.com/gh/ashnair1/COCO-Assistant/tree/master.svg?style=shield&circle-token=553c83e37198fe02a71743d42ee427c292336743) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/5299d18c95da4991b4f3a6ae6e8a0b7a)](https://www.codacy.com/manual/ashnair1/COCO-Assistant?utm_source=github.com&utm_medium=referral&utm_content=ashnair1/COCO-Assistant&utm_campaign=Badge_Grade) [![PyPI version](https://badge.fury.io/py/coco-assistant.svg)](https://badge.fury.io/py/coco-assistant) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -Helper for dealing with MS-COCO annotations. +Helper for dealing with MS-COCO annotations. ## Overview The MS COCO annotation format along with the pycocotools library is quite popular among the computer vision community. Yet I for one found it difficult to play around with the annotations. Deleting a specific category, combining multiple mini datasets to generate a larger dataset, viewing distribution of classes in the annotation file are things I would like to do without writing a separate script for each. The COCO Assistant is designed (or being designed) to assist with this problem. **Please note that currently, the Assistant can only help out with object detection datasets**. Any contributions and/or suggestions are welcome. @@ -10,7 +10,7 @@ The MS COCO annotation format along with the pycocotools library is quite popula ### Requirements Your data directory should look as follows: -```shell script +```markdown Example: . ├── images @@ -32,7 +32,7 @@ Example: `pip install coco-assistant` ### 2. Installation: From Source -```shell script +```markdown # Clone the repository git clone https://github.com/ashnair1/COCO-Assistant.git # Build and install the library @@ -43,7 +43,7 @@ make Usage is similar to how you would use `pycocotools` -```shell script +```markdown from coco_assistant import COCO_Assistant # Specify image and annotation directories @@ -59,7 +59,7 @@ cas = COCO_Assistant(img_dir, ann_dir) The `merge` function allows you to merge multiple datasets. -```shell script +```markdown In[1]: cas = COCO_Assistant(img_dir, ann_dir) loading annotations into memory... Done (t=0.09s) @@ -83,7 +83,7 @@ The merged dataset (images and annotation) can be found in `./results/combinatio Removes a specific category from an annotation file. -```shell script +```markdown In[1]: cas = COCO_Assistant(img_dir, ann_dir) loading annotations into memory... Done (t=0.09s) @@ -125,7 +125,7 @@ The modified annotation can be found in `./results/removal` Couldn't `pycocotools` visualise annotations (via [showAnns](https://github.com/cocodataset/cocoapi/blob/636becdc73d54283b3aac6d4ec363cffbb6f9b20/PythonAPI/pycocotools/coco.py#L233)) as well? Sure it could, but I required a way to freely view all the annotations of a particular dataset so here we are. -```shell script +```markdown In[1]: cas.visualise() Choose directory: ['tiny', 'tiny2'] @@ -142,6 +142,3 @@ The `cas.get_segmasks()` function allows you to create segmentation masks from y | **SpaceNet** | SpaceNet | SpaceNet_mask | | **iSAID** | iSAID | iSAID_mask | -### Todo -1. Converter for converting COCO annotations to YOLO format. -2. Write tests for untested functions :) diff --git a/coco_assistant/VERSION b/coco_assistant/VERSION index 0c62199..0d91a54 100644 --- a/coco_assistant/VERSION +++ b/coco_assistant/VERSION @@ -1 +1 @@ -0.2.1 +0.3.0 diff --git a/coco_assistant/coco_assistant.py b/coco_assistant/coco_assistant.py index b3fae78..b588d16 100755 --- a/coco_assistant/coco_assistant.py +++ b/coco_assistant/coco_assistant.py @@ -8,11 +8,9 @@ from tqdm import tqdm -from . import coco_converters as converter from . import coco_stats as stats from . import coco_visualiser as cocovis -from coco_assistant.utils import anchors -from coco_assistant.utils import det2seg +from coco_assistant.utils import anchors, det2seg logging.basicConfig(level=logging.ERROR) logging.getLogger().setLevel(logging.WARNING) @@ -292,25 +290,6 @@ def get_segmasks(self): output_dir = os.path.join(self.res_dir, 'segmasks', name) det2seg.det2seg(ann, output_dir) - def converter(self, to="TFRecord"): - """ - Function for converting annotations to other formats - - :param to: Format to which annotations are to be converted - """ - print("Choose directory:") - print(self.imgfolders) - - dir_choice = input() - - if dir_choice.lower() not in [item.lower() for item in self.imgfolders]: - raise AssertionError("Choice not in images folder") - ind = self.imgfolders.index(dir_choice.lower()) - ann = self.annfiles[ind] - img_dir = os.path.join(self.img_dir, dir_choice) - - converter.convert(ann, img_dir, _format=to) - def visualise(self): """ Function for visualising annotations. diff --git a/coco_assistant/coco_converters.py b/coco_assistant/coco_converters.py deleted file mode 100755 index 342d722..0000000 --- a/coco_assistant/coco_converters.py +++ /dev/null @@ -1,138 +0,0 @@ -import logging -import os -from random import shuffle - -from PIL import Image - -from pycocotools.coco import COCO - -import tensorflow as tf - -from .utils import dataset_util - -logging.basicConfig(level=logging.WARNING) - -# flags = tf.app.flags -# flags.DEFINE_string('data_dir', '', 'Root directory to raw Microsoft COCO dataset.') -# flags.DEFINE_string('set', 'train', 'Convert training set or validation set') -# flags.DEFINE_string('output_filepath', '', 'Path to output TFRecord') -# flags.DEFINE_bool('shuffle_imgs',True,'whether to shuffle images of coco') -# FLAGS = flags.FLAGS - - -def load_coco_detection_dataset(imgs_dir, annotations, shuffle_img=True): - """Load data from dataset by pycocotools. This tools can be download from "http://mscoco.org/dataset/#download" - Args: - imgs_dir: directories of coco images - annotations_filepath: file path of coco annotations file - shuffle_img: wheter to shuffle images order - Return: - coco_data: list of dictionary format information of each image - """ - coco = annotations - img_ids = coco.getImgIds() # totally 82783 images - cat_ids = coco.getCatIds() #totally 90 catagories, however, the number of categories is not continuous, \ - # [0,12,26,29,30,45,66,68,69,71,83] are missing, this is the problem of coco dataset. - - if shuffle_img: - shuffle(img_ids) - - coco_data = [] - - nb_imgs = len(img_ids) - for index, img_id in enumerate(img_ids): - if index % 100 == 0: - print("Readling images: %d / %d " % (index, nb_imgs)) - img_info = {} - bboxes = [] - labels = [] - - img_detail = coco.loadImgs(img_id)[0] - try: - pic_height = img_detail['height'] - pic_width = img_detail['width'] - except KeyError: - logging.warning("Image dimension is missing from the image field." - " Proceeding to read it manually") - im = Image.open(os.path.join(imgs_dir, img_detail['file_name'])) - pic_height = im.size[1] - pic_width = im.size[0] - - ann_ids = coco.getAnnIds(imgIds=img_id, catIds=cat_ids) - anns = coco.loadAnns(ann_ids) - for ann in anns: - bboxes_data = ann['bbox'] - # the format of coco bounding boxes are [Xmin, Ymin, width, height] - bboxes_data = [bboxes_data[0] / float(pic_width), bboxes_data[1] / float(pic_height), - bboxes_data[2] / float(pic_width), bboxes_data[3] / float(pic_height)] - bboxes.append(bboxes_data) - labels.append(ann['category_id']) - - img_path = os.path.join(imgs_dir, img_detail['file_name']) - img_bytes = tf.gfile.GFile(img_path, 'rb').read() - - img_info['pixel_data'] = img_bytes - img_info['height'] = pic_height - img_info['width'] = pic_width - img_info['bboxes'] = bboxes - img_info['labels'] = labels - - coco_data.append(img_info) - - return coco_data - - -def dict_to_coco_example(img_data): - """Convert python dictionary formath data of one image to tf.Example proto. - Args: - img_data: infomation of one image, inclue bounding box, labels of bounding box,\ - height, width, encoded pixel data. - Returns: - example: The converted tf.Example - """ - bboxes = img_data['bboxes'] - xmin, xmax, ymin, ymax = [], [], [], [] - for bbox in bboxes: - xmin.append(bbox[0]) - xmax.append(bbox[0] + bbox[2]) - ymin.append(bbox[1]) - ymax.append(bbox[1] + bbox[3]) - - example = tf.train.Example(features=tf.train.Features(feature={ - 'image/height': dataset_util.int64_feature(img_data['height']), - 'image/width': dataset_util.int64_feature(img_data['width']), - 'image/object/bbox/xmin': dataset_util.float_list_feature(xmin), - 'image/object/bbox/xmax': dataset_util.float_list_feature(xmax), - 'image/object/bbox/ymin': dataset_util.float_list_feature(ymin), - 'image/object/bbox/ymax': dataset_util.float_list_feature(ymax), - 'image/object/class/label': dataset_util.int64_list_feature(img_data['labels']), - 'image/encoded': dataset_util.bytes_feature(img_data['pixel_data']), - 'image/format': dataset_util.bytes_feature('jpeg'.encode('utf-8')), - })) - return example - - -def convert(ann, img_dir, _format): - - dst = os.path.join(os.path.dirname(os.path.dirname(img_dir)), - 'annotations', - os.path.basename(img_dir) + ".tfrecord") - - if _format == "TFRecord": - # load total coco data - coco_data = load_coco_detection_dataset(img_dir, ann, shuffle_img=True) - total_imgs = len(coco_data) - # write coco data to tf record - with tf.python_io.TFRecordWriter(dst) as tfrecord_writer: - for index, img_data in enumerate(coco_data): - if index % 100 == 0: - print("Converting images: %d / %d" % (index, total_imgs)) - example = dict_to_coco_example(img_data) - tfrecord_writer.write(example.SerializeToString()) - - -if __name__ == "__main__": - _format = "TFRecord" - ann = COCO("/home/ashwin/COCO-Assistant/data/annotations/coco.json") - img_dir = "/home/ashwin/COCO-Assistant/data/images/coco" - convert(ann, img_dir, _format) diff --git a/requirements.txt b/requirements.txt index 3c21069..ee0164e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,7 +7,6 @@ Pillow>=6.2.2 git+https://github.com/ashnair1/cocoapi.git#egg=pycocotools&subdirectory=PythonAPI seaborn scikit-image -tensorflow==1.12.0 tqdm # packaging