def _load_annotations(self, ann, image_info=None): parsed_annotations = [] ann_id = ann.get('id') attributes = {} if 'attributes' in ann: try: attributes.update(ann['attributes']) except Exception as e: log.debug("item #%s: failed to read annotation attributes: %s", image_info['id'], e) if 'score' in ann: attributes['score'] = ann['score'] group = ann_id # make sure all tasks' annotations are merged if self._task in [CocoTask.instances, CocoTask.person_keypoints]: x, y, w, h = ann['bbox'] label_id = self._get_label_id(ann) is_crowd = bool(ann['iscrowd']) attributes['is_crowd'] = is_crowd if self._task is CocoTask.person_keypoints: keypoints = ann['keypoints'] points = [p for i, p in enumerate(keypoints) if i % 3 != 2] visibility = keypoints[2::3] parsed_annotations.append( Points(points, visibility, label=label_id, id=ann_id, attributes=attributes, group=group)) segmentation = ann.get('segmentation') if segmentation and segmentation != [[]]: rle = None if isinstance(segmentation, list): if not self._merge_instance_polygons: # polygon - a single object can consist of multiple parts for polygon_points in segmentation: parsed_annotations.append( Polygon(points=polygon_points, label=label_id, id=ann_id, attributes=attributes, group=group)) else: # merge all parts into a single mask RLE img_h = image_info['height'] img_w = image_info['width'] rles = mask_utils.frPyObjects(segmentation, img_h, img_w) rle = mask_utils.merge(rles) elif isinstance(segmentation['counts'], list): # uncompressed RLE img_h = image_info['height'] img_w = image_info['width'] mask_h, mask_w = segmentation['size'] if img_h == mask_h and img_w == mask_w: rle = mask_utils.frPyObjects([segmentation], mask_h, mask_w)[0] else: log.warning( "item #%s: mask #%s " "does not match image size: %s vs. %s. " "Skipping this annotation.", image_info['id'], ann_id, (mask_h, mask_w), (img_h, img_w)) else: # compressed RLE rle = segmentation if rle is not None: parsed_annotations.append( RleMask(rle=rle, label=label_id, id=ann_id, attributes=attributes, group=group)) else: parsed_annotations.append( Bbox(x, y, w, h, label=label_id, id=ann_id, attributes=attributes, group=group)) elif self._task is CocoTask.labels: label_id = self._get_label_id(ann) parsed_annotations.append( Label(label=label_id, id=ann_id, attributes=attributes, group=group)) elif self._task is CocoTask.captions: caption = ann['caption'] parsed_annotations.append( Caption(caption, id=ann_id, attributes=attributes, group=group)) else: raise NotImplementedError() return parsed_annotations
def test_can_compare_projects(self): # just a smoke test label_categories1 = LabelCategories.from_iterable(['x', 'a', 'b', 'y']) mask_categories1 = MaskCategories.make_default(len(label_categories1)) point_categories1 = PointsCategories() for index, _ in enumerate(label_categories1.items): point_categories1.add(index, ['cat1', 'cat2'], joints=[[0, 1]]) dataset1 = Dataset.from_iterable( [ DatasetItem( id=100, subset='train', image=np.ones((10, 6, 3)), annotations=[ Caption('hello', id=1), Caption('world', id=2, group=5), Label(2, id=3, attributes={ 'x': 1, 'y': '2', }), Bbox(1, 2, 3, 4, label=0, id=4, z_order=1, attributes={ 'score': 1.0, }), Bbox(5, 6, 7, 8, id=5, group=5), Points([1, 2, 2, 0, 1, 1], label=0, id=5, z_order=4), Mask(label=3, id=5, z_order=2, image=np.ones((2, 3))), ]), DatasetItem(id=21, subset='train', annotations=[ Caption('test'), Label(2), Bbox(1, 2, 3, 4, label=2, id=42, group=42) ]), DatasetItem( id=2, subset='val', annotations=[ PolyLine([1, 2, 3, 4, 5, 6, 7, 8], id=11, z_order=1), Polygon([1, 2, 3, 4, 5, 6, 7, 8], id=12, z_order=4), ]), DatasetItem( id=42, subset='test', attributes={ 'a1': 5, 'a2': '42' }), DatasetItem(id=42), DatasetItem(id=43, image=Image(path='1/b/c.qq', size=(2, 4))), ], categories={ AnnotationType.label: label_categories1, AnnotationType.mask: mask_categories1, AnnotationType.points: point_categories1, }) label_categories2 = LabelCategories.from_iterable(['a', 'b', 'x', 'y']) mask_categories2 = MaskCategories.make_default(len(label_categories2)) point_categories2 = PointsCategories() for index, _ in enumerate(label_categories2.items): point_categories2.add(index, ['cat1', 'cat2'], joints=[[0, 1]]) dataset2 = Dataset.from_iterable( [ DatasetItem( id=100, subset='train', image=np.ones((10, 6, 3)), annotations=[ Caption('hello', id=1), Caption('world', id=2, group=5), Label(2, id=3, attributes={ 'x': 1, 'y': '2', }), Bbox(1, 2, 3, 4, label=1, id=4, z_order=1, attributes={ 'score': 1.0, }), Bbox(5, 6, 7, 8, id=5, group=5), Points([1, 2, 2, 0, 1, 1], label=0, id=5, z_order=4), Mask(label=3, id=5, z_order=2, image=np.ones((2, 3))), ]), DatasetItem(id=21, subset='train', annotations=[ Caption('test'), Label(2), Bbox(1, 2, 3, 4, label=3, id=42, group=42) ]), DatasetItem( id=2, subset='val', annotations=[ PolyLine([1, 2, 3, 4, 5, 6, 7, 8], id=11, z_order=1), Polygon([1, 2, 3, 4, 5, 6, 7, 8], id=12, z_order=4), ]), DatasetItem( id=42, subset='test', attributes={ 'a1': 5, 'a2': '42' }), DatasetItem(id=42), DatasetItem(id=43, image=Image(path='1/b/c.qq', size=(2, 4))), ], categories={ AnnotationType.label: label_categories2, AnnotationType.mask: mask_categories2, AnnotationType.points: point_categories2, }) with TestDir() as test_dir: with DatasetDiffVisualizer( save_dir=test_dir, comparator=DistanceComparator(iou_threshold=0.8), ) as visualizer: visualizer.save(dataset1, dataset2) self.assertNotEqual(0, os.listdir(osp.join(test_dir)))
def __iter__(self): for i in range(2): yield DatasetItem(id=i, image=np.ones([2, 2, 3]) * i, annotations=[Label(i)])
def _parse_annotations(raw_anns, item_id): return [Label(label_id) for label_id in raw_anns.get(item_id, [])]
def __iter__(self): yield DatasetItem(id=1, subset='train', annotations=[ Label(3, attributes={ 'x': 1 }), Label(4, id=4), ])
def __iter__(self): return iter([ DatasetItem(id=1, subset='val', annotations=[ Label(5), ]), ])
def test_can_merge_categories(self): source0 = Dataset.from_iterable( [ DatasetItem(1, annotations=[ Label(0), ]), ], categories={ AnnotationType.label: LabelCategories.from_iterable(['a', 'b']), AnnotationType.points: PointsCategories.from_iterable([ (0, ['l0', 'l1']), (1, ['l2', 'l3']), ]), AnnotationType.mask: MaskCategories({ 0: (0, 1, 2), 1: (1, 2, 3), }), }) source1 = Dataset.from_iterable( [ DatasetItem(1, annotations=[ Label(0), ]), ], categories={ AnnotationType.label: LabelCategories.from_iterable(['c', 'b']), AnnotationType.points: PointsCategories.from_iterable([ (0, []), (1, ['l2', 'l3']), ]), AnnotationType.mask: MaskCategories({ 0: (0, 2, 4), 1: (1, 2, 3), }), }) expected = Dataset.from_iterable( [ DatasetItem(1, annotations=[ Label(0), Label(2), ]), ], categories={ AnnotationType.label: LabelCategories.from_iterable(['a', 'b', 'c']), AnnotationType.points: PointsCategories.from_iterable([ (0, ['l0', 'l1']), (1, ['l2', 'l3']), (2, []), ]), AnnotationType.mask: MaskCategories({ 0: (0, 1, 2), 1: (1, 2, 3), 2: (0, 2, 4), }), }) merger = IntersectMerge() merged = merger([source0, source1]) compare_datasets(self, expected, merged, ignored_attrs={'score'})
def test_can_import(self): expected_dataset = Dataset.from_iterable( [ DatasetItem(id='0_Parade_image_01', subset='train', image=np.ones((10, 15, 3)), annotations=[ Bbox(1, 2, 2, 2, attributes={ 'blur': 0, 'expression': 0, 'illumination': 0, 'occluded': 0, 'pose': 0, 'invalid': 0 }), Label(0), ]), DatasetItem(id='1_Handshaking_image_02', subset='train', image=np.ones((10, 15, 3)), annotations=[ Bbox(1, 1, 2, 2, attributes={ 'blur': 0, 'expression': 0, 'illumination': 1, 'occluded': 0, 'pose': 0, 'invalid': 0 }), Bbox(5, 1, 2, 2, attributes={ 'blur': 0, 'expression': 0, 'illumination': 1, 'occluded': 0, 'pose': 0, 'invalid': 0 }), Label(1), ]), DatasetItem(id='0_Parade_image_03', subset='val', image=np.ones((10, 15, 3)), annotations=[ Bbox(0, 0, 1, 1, attributes={ 'blur': 2, 'expression': 0, 'illumination': 0, 'occluded': 0, 'pose': 2, 'invalid': 0 }), Bbox(3, 2, 1, 2, attributes={ 'blur': 0, 'expression': 0, 'illumination': 0, 'occluded': 1, 'pose': 0, 'invalid': 0 }), Bbox(5, 6, 1, 1, attributes={ 'blur': 2, 'expression': 0, 'illumination': 0, 'occluded': 0, 'pose': 2, 'invalid': 0 }), Label(0), ]), ], categories=['Parade', 'Handshaking']) dataset = Dataset.import_from(DUMMY_DATASET_DIR, 'wider_face') compare_datasets(self, expected_dataset, dataset)
def test_stats(self): dataset = Dataset.from_iterable( [ DatasetItem( id=1, image=np.ones((5, 5, 3)), annotations=[ Caption('hello'), Caption('world'), Label(2, attributes={ 'x': 1, 'y': '2', }), Bbox(1, 2, 2, 2, label=2, attributes={ 'score': 0.5, }), Bbox(5, 6, 2, 2, attributes={ 'x': 1, 'y': '3', 'occluded': True, }), Points([1, 2, 2, 0, 1, 1], label=0), Mask(label=3, image=np.array([ [0, 0, 1, 1, 1], [0, 0, 1, 1, 1], [0, 0, 1, 1, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], ])), ]), DatasetItem( id=2, image=np.ones((2, 4, 3)), annotations=[ Label(2, attributes={ 'x': 2, 'y': '2', }), Bbox(1, 2, 2, 2, label=3, attributes={ 'score': 0.5, }), Bbox(5, 6, 2, 2, attributes={ 'x': 2, 'y': '3', 'occluded': False, }), ]), DatasetItem(id=3), DatasetItem(id='2.2', image=np.ones((2, 4, 3))), ], categories=['label_%s' % i for i in range(4)]) expected = { 'images count': 4, 'unique images count': 3, 'repeated images count': 1, 'repeated images': [[('2', 'default'), ('2.2', 'default')]], 'annotations count': 10, 'unannotated images count': 2, 'unannotated images': ['3', '2.2'], 'annotations by type': { 'label': { 'count': 2, }, 'polygon': { 'count': 0, }, 'polyline': { 'count': 0, }, 'bbox': { 'count': 4, }, 'mask': { 'count': 1, }, 'points': { 'count': 1, }, 'caption': { 'count': 2, }, }, 'annotations': { 'labels': { 'count': 6, 'distribution': { 'label_0': [1, 1 / 6], 'label_1': [0, 0.0], 'label_2': [3, 3 / 6], 'label_3': [2, 2 / 6], }, 'attributes': { 'x': { 'count': 2, # annotations with no label are skipped 'values count': 2, 'values present': ['1', '2'], 'distribution': { '1': [1, 1 / 2], '2': [1, 1 / 2], }, }, 'y': { 'count': 2, # annotations with no label are skipped 'values count': 1, 'values present': ['2'], 'distribution': { '2': [2, 2 / 2], }, }, # must not include "special" attributes like "occluded" } }, 'segments': { 'avg. area': (4 * 2 + 9 * 1) / 3, 'area distribution': [ { 'min': 4.0, 'max': 4.5, 'count': 2, 'percent': 2 / 3 }, { 'min': 4.5, 'max': 5.0, 'count': 0, 'percent': 0.0 }, { 'min': 5.0, 'max': 5.5, 'count': 0, 'percent': 0.0 }, { 'min': 5.5, 'max': 6.0, 'count': 0, 'percent': 0.0 }, { 'min': 6.0, 'max': 6.5, 'count': 0, 'percent': 0.0 }, { 'min': 6.5, 'max': 7.0, 'count': 0, 'percent': 0.0 }, { 'min': 7.0, 'max': 7.5, 'count': 0, 'percent': 0.0 }, { 'min': 7.5, 'max': 8.0, 'count': 0, 'percent': 0.0 }, { 'min': 8.0, 'max': 8.5, 'count': 0, 'percent': 0.0 }, { 'min': 8.5, 'max': 9.0, 'count': 1, 'percent': 1 / 3 }, ], 'pixel distribution': { 'label_0': [0, 0.0], 'label_1': [0, 0.0], 'label_2': [4, 4 / 17], 'label_3': [13, 13 / 17], }, } }, } actual = compute_ann_statistics(dataset) self.assertEqual(expected, actual)
def test_attributes(self): source0 = Dataset.from_iterable([ DatasetItem(1, annotations=[ Label(2, attributes={ 'unique': 1, 'common_under_quorum': 2, 'common_over_quorum': 3, 'ignored': 'q', }), ]), ], categories=['a', 'b', 'c']) source1 = Dataset.from_iterable([ DatasetItem(1, annotations=[ Label(2, attributes={ 'common_under_quorum': 2, 'common_over_quorum': 3, 'ignored': 'q', }), ]), ], categories=['a', 'b', 'c']) source2 = Dataset.from_iterable([ DatasetItem(1, annotations=[ Label(2, attributes={ 'common_over_quorum': 3, 'ignored': 'q', }), ]), ], categories=['a', 'b', 'c']) expected = Dataset.from_iterable([ DatasetItem(1, annotations=[ Label(2, attributes={'common_over_quorum': 3}), ]), ], categories=['a', 'b', 'c']) merger = IntersectMerge(conf={ 'quorum': 3, 'ignored_attributes': {'ignored'} }) merged = merger([source0, source1, source2]) compare_datasets(self, expected, merged, ignored_attrs={'score'}) self.assertEqual( 2, len([ e for e in merger.errors if isinstance(e, FailedAttrVotingError) ]))
def test_can_match_items(self): # items 1 and 3 are unique, item 2 is common and should be merged source0 = Dataset.from_iterable([ DatasetItem(1, annotations=[ Label(0), ]), DatasetItem(2, annotations=[ Label(0), ]), ], categories=['a', 'b']) source1 = Dataset.from_iterable([ DatasetItem(2, annotations=[ Label(1), ]), DatasetItem(3, annotations=[ Label(0), ]), ], categories=['a', 'b']) source2 = Dataset.from_iterable([ DatasetItem(2, annotations=[Label(0), Bbox(1, 2, 3, 4)]), ], categories=['a', 'b']) expected = Dataset.from_iterable([ DatasetItem(1, annotations=[ Label(0, attributes={'score': 1 / 3}), ]), DatasetItem(2, annotations=[ Label(0, attributes={'score': 2 / 3}), Label(1, attributes={'score': 1 / 3}), Bbox(1, 2, 3, 4, attributes={'score': 1.0}), ]), DatasetItem(3, annotations=[ Label(0, attributes={'score': 1 / 3}), ]), ], categories=['a', 'b']) merger = IntersectMerge() merged = merger([source0, source1, source2]) compare_datasets(self, expected, merged) self.assertEqual( [ NoMatchingItemError(item_id=('1', DEFAULT_SUBSET_NAME), sources={1, 2}), NoMatchingItemError(item_id=('3', DEFAULT_SUBSET_NAME), sources={0, 2}), ], sorted( (e for e in merger.errors if isinstance(e, NoMatchingItemError)), key=lambda e: e.item_id)) self.assertEqual( [ NoMatchingAnnError(item_id=('2', DEFAULT_SUBSET_NAME), sources={0, 1}, ann=source2.get('2').annotations[1]), ], sorted( (e for e in merger.errors if isinstance(e, NoMatchingAnnError)), key=lambda e: e.item_id))
def _get_annotations(self, item_id): item_annotations = [] if self._task is VocTask.segmentation: class_mask = None segm_path = osp.join(self._path, VocPath.SEGMENTATION_DIR, item_id + VocPath.SEGM_EXT) if osp.isfile(segm_path): inverse_cls_colormap = \ self._categories[AnnotationType.mask].inverse_colormap class_mask = lazy_mask(segm_path, inverse_cls_colormap) instances_mask = None inst_path = osp.join(self._path, VocPath.INSTANCES_DIR, item_id + VocPath.SEGM_EXT) if osp.isfile(inst_path): instances_mask = lazy_mask(inst_path, _inverse_inst_colormap) if instances_mask is not None: compiled_mask = CompiledMask(class_mask, instances_mask) if class_mask is not None: label_cat = self._categories[AnnotationType.label] instance_labels = compiled_mask.get_instance_labels( class_count=len(label_cat.items)) else: instance_labels = { i: None for i in range(compiled_mask.instance_count) } for instance_id, label_id in instance_labels.items(): image = compiled_mask.lazy_extract(instance_id) attributes = dict() if label_id is not None: actions = { a: False for a in label_cat.items[label_id].attributes } attributes.update(actions) item_annotations.append( Mask(image=image, label=label_id, attributes=attributes, group=instance_id)) elif class_mask is not None: log.warn("item '%s': has only class segmentation, " "instance masks will not be available" % item_id) classes = class_mask.image.unique() for label_id in classes: image = self._lazy_extract_mask(class_mask, label_id) item_annotations.append(Mask(image=image, label=label_id)) cls_annotations = self._annotations.get(VocTask.classification) if cls_annotations is not None and \ self._task is VocTask.classification: item_labels = cls_annotations.get(item_id) if item_labels is not None: for label_id in item_labels: item_annotations.append(Label(label_id)) det_annotations = self._annotations.get(VocTask.detection) if det_annotations is not None: det_annotations = det_annotations.get(item_id) if det_annotations is not None: root_elem = ET.fromstring(det_annotations) for obj_id, object_elem in enumerate(root_elem.findall('object')): obj_id += 1 attributes = {} group = obj_id obj_label_id = None label_elem = object_elem.find('name') if label_elem is not None: obj_label_id = self._get_label_id(label_elem.text) obj_bbox = self._parse_bbox(object_elem) if obj_label_id is None or obj_bbox is None: continue difficult_elem = object_elem.find('difficult') attributes['difficult'] = difficult_elem is not None and \ difficult_elem.text == '1' truncated_elem = object_elem.find('truncated') attributes['truncated'] = truncated_elem is not None and \ truncated_elem.text == '1' occluded_elem = object_elem.find('occluded') attributes['occluded'] = occluded_elem is not None and \ occluded_elem.text == '1' pose_elem = object_elem.find('pose') if pose_elem is not None: attributes['pose'] = pose_elem.text point_elem = object_elem.find('point') if point_elem is not None: point_x = point_elem.find('x') point_y = point_elem.find('y') point = [float(point_x.text), float(point_y.text)] attributes['point'] = point actions_elem = object_elem.find('actions') actions = {a: False for a in self._categories[AnnotationType.label] \ .items[obj_label_id].attributes} if actions_elem is not None: for action_elem in actions_elem: actions[action_elem.tag] = (action_elem.text == '1') for action, present in actions.items(): attributes[action] = present has_parts = False for part_elem in object_elem.findall('part'): part = part_elem.find('name').text part_label_id = self._get_label_id(part) part_bbox = self._parse_bbox(part_elem) if self._task is not VocTask.person_layout: break if part_bbox is None: continue has_parts = True item_annotations.append( Bbox(*part_bbox, label=part_label_id, group=group)) if self._task is VocTask.person_layout and not has_parts: continue if self._task is VocTask.action_classification and not actions: continue item_annotations.append( Bbox(*obj_bbox, label=obj_label_id, attributes=attributes, id=obj_id, group=group)) return item_annotations
def _load_items(self, path): items = {} with open(path) as content: landmarks_table = list(csv.DictReader(content)) for row in landmarks_table: item_id = row['NAME_ID'] label = None if '/' in item_id: label_name = item_id.split('/')[0] if label_name != VggFace2Path.IMAGES_DIR_NO_LABEL: label = \ self._categories[AnnotationType.label].find(label_name)[0] item_id = item_id[len(label_name) + 1:] if item_id not in items: image_path = osp.join(self._dataset_dir, self._subset, row['NAME_ID'] + VggFace2Path.IMAGE_EXT) items[item_id] = DatasetItem(id=item_id, subset=self._subset, image=image_path) annotations = items[item_id].annotations if len([p for p in row if row[p] == '']) == 0 and len(row) == 11: annotations.append( Points([float(row[p]) for p in row if p != 'NAME_ID'], label=label, group=1)) elif label is not None: annotations.append(Label(label=label, group=1)) bboxes_path = osp.join( self._dataset_dir, VggFace2Path.ANNOTATION_DIR, VggFace2Path.BBOXES_FILE + self._subset + '.csv') if osp.isfile(bboxes_path): with open(bboxes_path) as content: bboxes_table = list(csv.DictReader(content)) for row in bboxes_table: item_id = row['NAME_ID'] label = None if '/' in item_id: label_name = item_id.split('/')[0] if label_name != VggFace2Path.IMAGES_DIR_NO_LABEL: label = \ self._categories[AnnotationType.label].find(label_name)[0] item_id = item_id[len(label_name) + 1:] if item_id not in items: image_path = osp.join( self._dataset_dir, self._subset, row['NAME_ID'] + VggFace2Path.IMAGE_EXT) items[item_id] = DatasetItem(id=item_id, subset=self._subset, image=image_path) annotations = items[item_id].annotations if len([p for p in row if row[p] == '']) == 0 and len(row) == 5: annotations.append( Bbox(float(row['X']), float(row['Y']), float(row['W']), float(row['H']), label=label, group=1)) return items
def __iter__(self): return iter([ DatasetItem(id=0, subset='s1', image=np.zeros((5, 10, 3)), annotations=[ Polygon([0, 0, 4, 0, 4, 4], label=1, group=4, attributes={ 'z_order': 0, 'occluded': True }), Polygon([5, 0, 9, 0, 5, 5], label=2, group=4, attributes={ 'z_order': 0, 'occluded': False }), Points( [1, 1, 3, 2, 2, 3], label=2, attributes={ 'z_order': 0, 'occluded': False, 'a1': 'x', 'a2': 42 }), Label(1), Label(2, attributes={ 'a1': 'y', 'a2': 44 }), ]), DatasetItem(id=1, subset='s1', annotations=[ PolyLine([0, 0, 4, 0, 4, 4], label=3, group=4, attributes={ 'z_order': 0, 'occluded': False }), Bbox(5, 0, 1, 9, label=3, group=4, attributes={ 'z_order': 0, 'occluded': False }), ]), DatasetItem(id=2, subset='s2', image=np.ones((5, 10, 3)), annotations=[ Polygon([0, 0, 4, 0, 4, 4], label=3, group=4, attributes={ 'z_order': 1, 'occluded': False }), ]), DatasetItem(id=3, subset='s3', image=Image(path='3.jpg', size=(2, 4))), ])
def _load_items(self, path): items = {} with open(path, 'r', encoding='utf-8') as f: lines = f.readlines() line_ids = [line_idx for line_idx, line in enumerate(lines) if ('/' in line or '\\' in line) and '.' in line] \ # a heuristic for paths for line_idx in line_ids: image_path = lines[line_idx].strip() item_id = osp.splitext(image_path)[0] image_path = osp.join(self._dataset_dir, WiderFacePath.SUBSET_DIR + self._subset, WiderFacePath.IMAGES_DIR, image_path) annotations = [] if '/' in item_id: label_name = item_id.split('/')[0] if '--' in label_name: label_name = label_name.split('--')[1] if label_name != WiderFacePath.IMAGES_DIR_NO_LABEL: label = \ self._categories[AnnotationType.label].find(label_name)[0] annotations.append(Label(label=label)) item_id = item_id[len(item_id.split('/')[0]) + 1:] items[item_id] = DatasetItem(id=item_id, subset=self._subset, image=image_path, annotations=annotations) try: bbox_count = int(lines[line_idx + 1]) # can be the next image except ValueError: continue bbox_lines = lines[line_idx + 2:line_idx + bbox_count + 2] for bbox in bbox_lines: bbox_list = bbox.split() if 4 <= len(bbox_list): attributes = {} label = None if len(bbox_list) == 5 or len(bbox_list) == 11: if len(bbox_list) == 5: label_name = bbox_list[4] else: label_name = bbox_list[10] label = \ self._categories[AnnotationType.label].find(label_name)[0] if 10 <= len(bbox_list): i = 4 for attr in WiderFacePath.BBOX_ATTRIBUTES: if bbox_list[i] != '-': attributes[attr] = bbox_list[i] i += 1 annotations.append( Bbox(float(bbox_list[0]), float(bbox_list[1]), float(bbox_list[2]), float(bbox_list[3]), attributes=attributes, label=label)) return items
def test_can_save_and_load(self): source_dataset = Dataset.from_iterable( [ DatasetItem(id='1', subset='train', image=np.ones((8, 8, 3)), annotations=[ Bbox(0, 2, 4, 2), Bbox(0, 1, 2, 3, attributes={ 'blur': 2, 'expression': 0, 'illumination': 0, 'occluded': 0, 'pose': 2, 'invalid': 0 }), Label(0), ]), DatasetItem(id='2', subset='train', image=np.ones((10, 10, 3)), annotations=[ Bbox(0, 2, 4, 2, attributes={ 'blur': 2, 'expression': 0, 'illumination': 1, 'occluded': 0, 'pose': 1, 'invalid': 0 }), Bbox(3, 3, 2, 3, attributes={ 'blur': 0, 'expression': 1, 'illumination': 0, 'occluded': 0, 'pose': 2, 'invalid': 0 }), Bbox(2, 1, 2, 3, attributes={ 'blur': 2, 'expression': 0, 'illumination': 0, 'occluded': 0, 'pose': 0, 'invalid': 1 }), Label(1), ]), DatasetItem(id='3', subset='val', image=np.ones((8, 8, 3)), annotations=[ Bbox(0, 1, 5, 2, attributes={ 'blur': 2, 'expression': 1, 'illumination': 0, 'occluded': 0, 'pose': 1, 'invalid': 0 }), Bbox(0, 2, 3, 2), Bbox(0, 2, 4, 2), Bbox(0, 7, 3, 2, attributes={ 'blur': 2, 'expression': 1, 'illumination': 0, 'occluded': 0, 'pose': 1, 'invalid': 0 }), ]), DatasetItem(id='4', subset='val', image=np.ones((8, 8, 3))), ], categories={ AnnotationType.label: LabelCategories.from_iterable('label_' + str(i) for i in range(3)), }) with TestDir() as test_dir: WiderFaceConverter.convert(source_dataset, test_dir, save_images=True) parsed_dataset = Dataset.import_from(test_dir, 'wider_face') compare_datasets(self, source_dataset, parsed_dataset)
def transform_item(self, item): annotations = item.annotations if item.attributes: annotations.append(Label(self._label, attributes=item.attributes)) item.attributes = {} return item.wrap(annotations=annotations)
def __iter__(self): for path in self.items: with open(path, 'r') as f: index = osp.splitext(osp.basename(path))[0] label = int(f.readline().strip()) yield DatasetItem(id=index, annotations=[Label(label)])
def _parse_tag_ann(cls, ann, categories): label = ann.get('label') label_id = categories[AnnotationType.label].find(label)[0] group = ann.get('group') attributes = ann.get('attributes') return Label(label_id, attributes=attributes, group=group)
def __iter__(self): return iter([ DatasetItem(id=2, annotations=[ Label(2), ]), ])
def test_can_save_and_load(self): label_categories = LabelCategories() for i in range(10): label_categories.add(str(i)) label_categories.items[2].attributes.update(['a1', 'a2', 'empty']) label_categories.attributes.update(['occluded']) source_dataset = Dataset.from_iterable( [ DatasetItem(id=0, subset='s1', image=np.zeros((5, 10, 3)), annotations=[ Polygon([0, 0, 4, 0, 4, 4], label=1, group=4, attributes={'occluded': True}), Points( [1, 1, 3, 2, 2, 3], label=2, attributes={ 'a1': 'x', 'a2': 42, 'empty': '', 'unknown': 'bar' }), Label(1), Label(2, attributes={ 'a1': 'y', 'a2': 44 }), ]), DatasetItem( id=1, subset='s1', annotations=[ PolyLine([0, 0, 4, 0, 4, 4], label=3, id=4, group=4), Bbox(5, 0, 1, 9, label=3, id=4, group=4), ]), DatasetItem( id=2, subset='s2', image=np.ones((5, 10, 3)), annotations=[ Polygon([0, 0, 4, 0, 4, 4], z_order=1, label=3, group=4, attributes={'occluded': False}), PolyLine([5, 0, 9, 0, 5, 5 ]), # will be skipped as no label ]), DatasetItem( id=3, subset='s3', image=Image(path='3.jpg', size=(2, 4))), ], categories={ AnnotationType.label: label_categories, }) target_dataset = Dataset.from_iterable([ DatasetItem(id=0, subset='s1', image=np.zeros((5, 10, 3)), annotations=[ Polygon([0, 0, 4, 0, 4, 4], label=1, group=4, attributes={'occluded': True}), Points( [1, 1, 3, 2, 2, 3], label=2, attributes={ 'occluded': False, 'empty': '', 'a1': 'x', 'a2': 42 }), Label(1), Label(2, attributes={ 'a1': 'y', 'a2': 44 }), ], attributes={'frame': 0}), DatasetItem(id=1, subset='s1', annotations=[ PolyLine([0, 0, 4, 0, 4, 4], label=3, group=4, attributes={'occluded': False}), Bbox(5, 0, 1, 9, label=3, group=4, attributes={'occluded': False}), ], attributes={'frame': 1}), DatasetItem(id=2, subset='s2', image=np.ones((5, 10, 3)), annotations=[ Polygon([0, 0, 4, 0, 4, 4], z_order=1, label=3, group=4, attributes={'occluded': False}), ], attributes={'frame': 0}), DatasetItem(id=3, subset='s3', image=Image(path='3.jpg', size=(2, 4)), attributes={'frame': 0}), ], categories={ AnnotationType.label: label_categories, }) with TestDir() as test_dir: self._test_save_and_load(source_dataset, partial(CvatConverter.convert, save_images=True), test_dir, target_dataset=target_dataset)
def launch(self, inputs): for i, inp in enumerate(inputs): yield [Label(0, attributes={'idx': i, 'data': inp.item()})]
def _load_annotations(self, item): parsed = item['annotations'] loaded = [] for ann in parsed: ann_id = ann.get('id') ann_type = AnnotationType[ann['type']] attributes = ann.get('attributes') group = ann.get('group') if ann_type == AnnotationType.label: label_id = ann.get('label_id') loaded.append( Label(label=label_id, id=ann_id, attributes=attributes, group=group)) elif ann_type == AnnotationType.mask: label_id = ann.get('label_id') rle = ann['rle'] rle['counts'] = rle['counts'].encode('ascii') loaded.append( RleMask(rle=rle, label=label_id, id=ann_id, attributes=attributes, group=group)) elif ann_type == AnnotationType.polyline: label_id = ann.get('label_id') points = ann.get('points') loaded.append( PolyLine(points, label=label_id, id=ann_id, attributes=attributes, group=group)) elif ann_type == AnnotationType.polygon: label_id = ann.get('label_id') points = ann.get('points') loaded.append( Polygon(points, label=label_id, id=ann_id, attributes=attributes, group=group)) elif ann_type == AnnotationType.bbox: label_id = ann.get('label_id') x, y, w, h = ann.get('bbox') loaded.append( Bbox(x, y, w, h, label=label_id, id=ann_id, attributes=attributes, group=group)) elif ann_type == AnnotationType.points: label_id = ann.get('label_id') points = ann.get('points') loaded.append( Points(points, label=label_id, id=ann_id, attributes=attributes, group=group)) elif ann_type == AnnotationType.caption: caption = ann.get('caption') loaded.append( Caption(caption, id=ann_id, attributes=attributes, group=group)) else: raise NotImplementedError() return loaded
def launch(self, inputs): for inp in inputs: yield [Label(inp[0, 0, 0])]
def test_dataset(self): label_categories = LabelCategories() for i in range(5): label_categories.add('cat' + str(i)) mask_categories = MaskCategories( generate_colormap(len(label_categories.items))) points_categories = PointsCategories() for index, _ in enumerate(label_categories.items): points_categories.add(index, ['cat1', 'cat2'], joints=[[0, 1]]) return Dataset.from_iterable( [ DatasetItem( id=100, subset='train', image=np.ones((10, 6, 3)), annotations=[ Caption('hello', id=1), Caption('world', id=2, group=5), Label(2, id=3, attributes={ 'x': 1, 'y': '2', }), Bbox(1, 2, 3, 4, label=4, id=4, z_order=1, attributes={ 'score': 1.0, }), Bbox(5, 6, 7, 8, id=5, group=5), Points([1, 2, 2, 0, 1, 1], label=0, id=5, z_order=4), Mask(label=3, id=5, z_order=2, image=np.ones((2, 3))), ]), DatasetItem(id=21, subset='train', annotations=[ Caption('test'), Label(2), Bbox(1, 2, 3, 4, label=5, id=42, group=42) ]), DatasetItem( id=2, subset='val', annotations=[ PolyLine([1, 2, 3, 4, 5, 6, 7, 8], id=11, z_order=1), Polygon([1, 2, 3, 4, 5, 6, 7, 8], id=12, z_order=4), ]), DatasetItem( id=42, subset='test', attributes={ 'a1': 5, 'a2': '42' }), DatasetItem(id=42), DatasetItem(id=43, image=Image(path='1/b/c.qq', size=(2, 4))), ], categories={ AnnotationType.label: label_categories, AnnotationType.mask: mask_categories, AnnotationType.points: points_categories, })