[Datumaro] Fix coco import conflict with labels (#1548)

main
zhiltsov-max 6 years ago committed by GitHub
parent 0934d772f8
commit 42990906b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -40,6 +40,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Task/Job buttons has no "Open in new tab" option (<https://github.com/opencv/cvat/pull/1419>) - Task/Job buttons has no "Open in new tab" option (<https://github.com/opencv/cvat/pull/1419>)
- Delete point context menu option has no shortcut hint (<https://github.com/opencv/cvat/pull/1416>) - Delete point context menu option has no shortcut hint (<https://github.com/opencv/cvat/pull/1416>)
- Fixed issue with unnecessary tag activation in cvat-canvas (<https://github.com/opencv/cvat/issues/1540>) - Fixed issue with unnecessary tag activation in cvat-canvas (<https://github.com/opencv/cvat/issues/1540>)
- Fixed full COCO dataset import error with conflicting labels in keypoints and detection (https://github.com/opencv/cvat/pull/1548)
- Fixed COCO keypoints skeleton parsing and saving (https://github.com/opencv/cvat/issues/1539)
### Security ### Security
- -

@ -481,7 +481,7 @@ class Bbox(_Shape):
return compute_iou(self.get_bbox(), other.get_bbox()) return compute_iou(self.get_bbox(), other.get_bbox())
class PointsCategories(Categories): class PointsCategories(Categories):
Category = namedtuple('Category', ['labels', 'adjacent']) Category = namedtuple('Category', ['labels', 'joints'])
def __init__(self, items=None, attributes=None): def __init__(self, items=None, attributes=None):
super().__init__(attributes=attributes) super().__init__(attributes=attributes)
@ -490,12 +490,13 @@ class PointsCategories(Categories):
items = {} items = {}
self.items = items self.items = items
def add(self, label_id, labels=None, adjacent=None): def add(self, label_id, labels=None, joints=None):
if labels is None: if labels is None:
labels = [] labels = []
if adjacent is None: if joints is None:
adjacent = [] joints = []
self.items[label_id] = self.Category(labels, set(adjacent)) joints = set(map(tuple, joints))
self.items[label_id] = self.Category(labels, joints)
def __eq__(self, other): def __eq__(self, other):
if not super().__eq__(other): if not super().__eq__(other):

@ -337,7 +337,7 @@ class _KeypointsConverter(_InstancesConverter):
if kp_cat is not None: if kp_cat is not None:
cat.update({ cat.update({
'keypoints': [str(l) for l in kp_cat.labels], 'keypoints': [str(l) for l in kp_cat.labels],
'skeleton': [int(i) for i in kp_cat.adjacent], 'skeleton': [list(map(int, j)) for j in kp_cat.joints],
}) })
self.categories.append(cat) self.categories.append(cat)
@ -464,8 +464,8 @@ class _Converter:
self._save_images = save_images self._save_images = save_images
assert segmentation_mode is None or \ assert segmentation_mode is None or \
segmentation_mode in SegmentationMode or \ isinstance(segmentation_mode, str) or \
isinstance(segmentation_mode, str) segmentation_mode in SegmentationMode
if segmentation_mode is None: if segmentation_mode is None:
segmentation_mode = SegmentationMode.guess segmentation_mode = SegmentationMode.guess
if isinstance(segmentation_mode, str): if isinstance(segmentation_mode, str):

@ -70,7 +70,9 @@ class _CocoExtractor(SourceExtractor):
self._categories = {} self._categories = {}
if self._task in [CocoTask.instances, CocoTask.labels, if self._task in [CocoTask.instances, CocoTask.labels,
CocoTask.person_keypoints, CocoTask.stuff, CocoTask.panoptic]: CocoTask.person_keypoints,
# TODO: Task.stuff, CocoTask.panoptic
]:
label_categories, label_map = self._load_label_categories(loader) label_categories, label_map = self._load_label_categories(loader)
self._categories[AnnotationType.label] = label_categories self._categories[AnnotationType.label] = label_categories
self._label_map = label_map self._label_map = label_map
@ -101,7 +103,8 @@ class _CocoExtractor(SourceExtractor):
for cat in cats: for cat in cats:
label_id = self._label_map[cat['id']] label_id = self._label_map[cat['id']]
categories.add(label_id=label_id, categories.add(label_id=label_id,
labels=cat['keypoints'], adjacent=cat['skeleton']) labels=cat['keypoints'], joints=cat['skeleton']
)
return categories return categories

@ -12,8 +12,8 @@ CocoTask = Enum('CocoTask', [
'captions', 'captions',
'labels', # extension, does not exist in the original COCO format 'labels', # extension, does not exist in the original COCO format
'image_info', 'image_info',
'panoptic', # 'panoptic',
'stuff', # 'stuff',
]) ])
class CocoPath: class CocoPath:

@ -37,8 +37,26 @@ class CocoImporter(Importer):
if len(subsets) == 0: if len(subsets) == 0:
raise Exception("Failed to find 'coco' dataset at '%s'" % path) raise Exception("Failed to find 'coco' dataset at '%s'" % path)
# TODO: should be removed when proper label merging is implemented
conflicting_types = {CocoTask.instances,
CocoTask.person_keypoints, CocoTask.labels}
ann_types = set(t for s in subsets.values() for t in s) \
& conflicting_types
if 1 <= len(ann_types):
selected_ann_type = sorted(ann_types, key=lambda x: x.name)[0]
if 1 < len(ann_types):
log.warning("Not implemented: "
"Found potentially conflicting source types with labels: %s. "
"Only one type will be used: %s" \
% (", ".join(t.name for t in ann_types), selected_ann_type.name))
for ann_files in subsets.values(): for ann_files in subsets.values():
for ann_type, ann_file in ann_files.items(): for ann_type, ann_file in ann_files.items():
if ann_type in conflicting_types:
if ann_type is not selected_ann_type:
log.warning("Not implemented: "
"conflicting source '%s' is skipped." % ann_file)
continue
log.info("Found a dataset at '%s'" % ann_file) log.info("Found a dataset at '%s'" % ann_file)
source_name = osp.splitext(osp.basename(ann_file))[0] source_name = osp.splitext(osp.basename(ann_file))[0]
@ -71,6 +89,7 @@ class CocoImporter(Importer):
"type '%s', the only known are: %s" % \ "type '%s', the only known are: %s" % \
(subset_path, ann_type, (subset_path, ann_type,
', '.join([e.name for e in CocoTask]))) ', '.join([e.name for e in CocoTask])))
continue
subset_name = name_parts[1] subset_name = name_parts[1]
subsets[subset_name][ann_type] = subset_path subsets[subset_name][ann_type] = subset_path
return dict(subsets) return dict(subsets)

@ -212,7 +212,7 @@ class _SubsetWriter:
converted['items'].append({ converted['items'].append({
'label_id': int(label_id), 'label_id': int(label_id),
'labels': [cast(label, str) for label in item.labels], 'labels': [cast(label, str) for label in item.labels],
'adjacent': [int(v) for v in item.adjacent], 'joints': [list(map(int, j)) for j in item.joints],
}) })
return converted return converted

@ -70,7 +70,7 @@ class DatumaroExtractor(SourceExtractor):
point_categories = PointsCategories() point_categories = PointsCategories()
for item in parsed_points_cat['items']: for item in parsed_points_cat['items']:
point_categories.add(int(item['label_id']), point_categories.add(int(item['label_id']),
item['labels'], adjacent=item['adjacent']) item['labels'], joints=item['joints'])
categories[AnnotationType.points] = point_categories categories[AnnotationType.points] = point_categories

@ -535,7 +535,7 @@ class CocoConverterTest(TestCase):
points_categories = PointsCategories() points_categories = PointsCategories()
for i in range(10): for i in range(10):
label_categories.add(str(i)) label_categories.add(str(i))
points_categories.add(i, []) points_categories.add(i, joints=[[0, 1], [1, 2]])
categories = { categories = {
AnnotationType.label: label_categories, AnnotationType.label: label_categories,
AnnotationType.points: points_categories, AnnotationType.points: points_categories,
@ -624,25 +624,12 @@ class CocoConverterTest(TestCase):
class TestExtractor(Extractor): class TestExtractor(Extractor):
def __iter__(self): def __iter__(self):
return iter([ return iter([
DatasetItem(id=1, annotations=[ DatasetItem(id=1),
Label(2, id=1, group=1), DatasetItem(id=2),
]),
DatasetItem(id=2, annotations=[
Label(3, id=2, group=2),
]),
]) ])
def categories(self): def categories(self):
label_cat = LabelCategories() return { AnnotationType.label: LabelCategories() }
point_cat = PointsCategories()
for label in range(10):
label_cat.add('label_' + str(label))
point_cat.add(label)
return {
AnnotationType.label: label_cat,
AnnotationType.points: point_cat,
}
with TestDir() as test_dir: with TestDir() as test_dir:
self._test_save_and_load(TestExtractor(), self._test_save_and_load(TestExtractor(),

@ -63,7 +63,7 @@ class DatumaroConverterTest(TestCase):
points_categories = PointsCategories() points_categories = PointsCategories()
for index, _ in enumerate(label_categories.items): for index, _ in enumerate(label_categories.items):
points_categories.add(index, ['cat1', 'cat2'], adjacent=[0, 1]) points_categories.add(index, ['cat1', 'cat2'], joints=[[0, 1]])
return { return {
AnnotationType.label: label_categories, AnnotationType.label: label_categories,

Loading…
Cancel
Save