diff --git a/datumaro/tests/test_coco_format.py b/datumaro/tests/test_coco_format.py index 19ae0805..8da66717 100644 --- a/datumaro/tests/test_coco_format.py +++ b/datumaro/tests/test_coco_format.py @@ -1,6 +1,4 @@ -import json import numpy as np -import os import os.path as osp from unittest import TestCase @@ -19,94 +17,13 @@ from datumaro.plugins.coco_format.converter import ( CocoLabelsConverter, ) from datumaro.plugins.coco_format.importer import CocoImporter -from datumaro.util.image import save_image, Image +from datumaro.util.image import Image from datumaro.util.test_utils import TestDir, compare_datasets -class CocoImporterTest(TestCase): - @staticmethod - def generate_annotation(): - annotation = { - 'licenses': [], - 'info': {}, - 'categories': [], - 'images': [], - 'annotations': [], - } - annotation['licenses'].append({ - 'name': '', - 'id': 0, - 'url': '', - }) - annotation['info'] = { - 'contributor': '', - 'date_created': '', - 'description': '', - 'url': '', - 'version': '', - 'year': '', - } - annotation['licenses'].append({ - 'name': '', - 'id': 0, - 'url': '', - }) - annotation['categories'].append({ - 'id': 1, - 'name': 'TEST', - 'supercategory': '', - }) - annotation['images'].append({ - "id": 1, - "width": 5, - "height": 10, - "file_name": '000000000001.jpg', - "license": 0, - "flickr_url": '', - "coco_url": '', - "date_captured": 0, - }) - annotation['annotations'].append({ - "id": 1, - "image_id": 1, - "category_id": 1, - "segmentation": [[0, 0, 1, 0, 1, 2, 0, 2]], - "area": 2, - "bbox": [0, 0, 1, 2], - "iscrowd": 0, - }) - annotation['annotations'].append({ - "id": 2, - "image_id": 1, - "category_id": 1, - "segmentation": { - "counts": [ - 0, 10, - 5, 5, - 5, 5, - 0, 10, - 10, 0], - "size": [10, 5]}, - "area": 30, - "bbox": [0, 0, 10, 4], - "iscrowd": 1, - }) - return annotation - - def COCO_dataset_generate(self, path): - img_dir = osp.join(path, 'images', 'val') - ann_dir = osp.join(path, 'annotations') - os.makedirs(img_dir) - os.makedirs(ann_dir) - - image = np.ones((10, 5, 3)) - save_image(osp.join(img_dir, '000000000001.jpg'), image) - - annotation = self.generate_annotation() - - with open(osp.join(ann_dir, 'instances_val.json'), 'w') as outfile: - json.dump(annotation, outfile) +DUMMY_DATASET_DIR = osp.join(osp.dirname(__file__), 'assets', 'coco_dataset') +class CocoImporterTest(TestCase): def test_can_import(self): class DstExtractor(Extractor): def __iter__(self): @@ -129,18 +46,13 @@ class CocoImporterTest(TestCase): label_cat.add('TEST') return { AnnotationType.label: label_cat } - with TestDir() as test_dir: - self.COCO_dataset_generate(test_dir) - - dataset = Project.import_from(test_dir, 'coco').make_dataset() + dataset = Project.import_from(DUMMY_DATASET_DIR, 'coco') \ + .make_dataset() - compare_datasets(self, DstExtractor(), dataset) + compare_datasets(self, DstExtractor(), dataset) def test_can_detect(self): - with TestDir() as test_dir: - self.COCO_dataset_generate(test_dir) - - self.assertTrue(CocoImporter.detect(test_dir)) + self.assertTrue(CocoImporter.detect(DUMMY_DATASET_DIR)) class CocoConverterTest(TestCase): def _test_save_and_load(self, source_dataset, converter, test_dir, @@ -282,7 +194,7 @@ class CocoConverterTest(TestCase): label_categories.add(str(i)) categories = { AnnotationType.label: label_categories } - class TestExtractor(Extractor): + class SrcExtractor(Extractor): def __iter__(self): return iter([ DatasetItem(id=1, image=np.zeros((6, 10, 3)), @@ -298,30 +210,35 @@ class CocoConverterTest(TestCase): def categories(self): return categories - class TargetExtractor(TestExtractor): + class DstExtractor(Extractor): def __iter__(self): - items = list(super().__iter__()) - items[0]._annotations = [ - Mask(np.array([ - [0, 1, 1, 1, 0, 1, 1, 1, 1, 0], - [0, 0, 1, 1, 0, 1, 1, 1, 0, 0], - [0, 0, 0, 1, 0, 1, 1, 0, 0, 0], - [0, 0, 0, 0, 0, 1, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], - # only internal fragment (without the border), - # but not everywhere... - ), - label=3, id=4, group=4, - attributes={ 'is_crowd': False }), - ] - return iter(items) + return iter([ + DatasetItem(id=1, image=np.zeros((6, 10, 3)), + annotations=[ + Mask(np.array([ + [0, 1, 1, 1, 0, 1, 1, 1, 1, 0], + [0, 0, 1, 1, 0, 1, 1, 1, 0, 0], + [0, 0, 0, 1, 0, 1, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], + # only internal fragment (without the border), + # but not everywhere... + ), + label=3, id=4, group=4, + attributes={ 'is_crowd': False }), + ] + ), + ]) + + def categories(self): + return categories with TestDir() as test_dir: - self._test_save_and_load(TestExtractor(), + self._test_save_and_load(SrcExtractor(), CocoInstancesConverter(), test_dir, importer_args={'merge_instance_polygons': True}, - target_dataset=TargetExtractor()) + target_dataset=DstExtractor()) def test_can_crop_covered_segments(self): label_categories = LabelCategories() @@ -435,7 +352,7 @@ class CocoConverterTest(TestCase): for i in range(10): label_categories.add(str(i)) - class SrcTestExtractor(Extractor): + class SrcExtractor(Extractor): def __iter__(self): return iter([ DatasetItem(id=1, image=np.zeros((5, 10, 3)), @@ -455,7 +372,7 @@ class CocoConverterTest(TestCase): def categories(self): return { AnnotationType.label: label_categories } - class DstTestExtractor(Extractor): + class DstExtractor(Extractor): def __iter__(self): return iter([ DatasetItem(id=1, image=np.zeros((5, 10, 3)), @@ -476,9 +393,9 @@ class CocoConverterTest(TestCase): return { AnnotationType.label: label_categories } with TestDir() as test_dir: - self._test_save_and_load(SrcTestExtractor(), + self._test_save_and_load(SrcExtractor(), CocoInstancesConverter(segmentation_mode='polygons'), test_dir, - target_dataset=DstTestExtractor()) + target_dataset=DstExtractor()) def test_can_save_and_load_images(self): class TestExtractor(Extractor): @@ -506,16 +423,8 @@ class CocoConverterTest(TestCase): annotations=[ Label(4, id=1, group=1), Label(9, id=2, group=2), - ]), - DatasetItem(id=2, subset='train', - annotations=[ - Label(4, id=4, group=4), - ]), - - DatasetItem(id=3, subset='val', - annotations=[ - Label(2, id=1, group=1), - ]), + ] + ), ]) def categories(self): @@ -555,21 +464,16 @@ class CocoConverterTest(TestCase): # Full instance annotations: bbox + keypoints Points([1, 2, 3, 4, 2, 3], group=2, id=2), Bbox(1, 2, 2, 2, group=2, id=2), - ]), - DatasetItem(id=2, subset='train', image=np.zeros((5, 4, 3)), - annotations=[ + # Solitary keypoints Points([1, 2, 0, 2, 4, 1], label=5, id=3), # Some other solitary annotations (bug #1387) Polygon([0, 0, 4, 0, 4, 4], label=3, id=4), - ]), - DatasetItem(id=3, subset='val', - annotations=[ # Solitary keypoints with no label - Points([0, 0, 1, 2, 3, 4], [0, 1, 2], id=3), - ]), + Points([0, 0, 1, 2, 3, 4], [0, 1, 2], id=5), + ]) ]) def categories(self): @@ -593,24 +497,19 @@ class CocoConverterTest(TestCase): Polygon([1, 2, 3, 2, 3, 4, 1, 4], group=2, id=2, attributes={'is_crowd': False}), - ]), - DatasetItem(id=2, subset='train', - annotations=[ + Points([1, 2, 0, 2, 4, 1], label=5, group=3, id=3, attributes={'is_crowd': False}), Polygon([0, 1, 4, 1, 4, 2, 0, 2], label=5, group=3, id=3, attributes={'is_crowd': False}), - ]), - DatasetItem(id=3, subset='val', - annotations=[ Points([0, 0, 1, 2, 3, 4], [0, 1, 2], - group=3, id=3, + group=5, id=5, attributes={'is_crowd': False}), Polygon([1, 2, 3, 2, 3, 4, 1, 4], - group=3, id=3, + group=5, id=5, attributes={'is_crowd': False}), ]), ])