diff --git a/README.md b/README.md
index dd8b68c6b56..6a65a2ea06b 100644
--- a/README.md
+++ b/README.md
@@ -62,6 +62,7 @@ For more information about supported formats look at the
| [LabelMe 3.0](http://labelme.csail.mit.edu/Release3.0) | X | X |
| [ImageNet](http://www.image-net.org) | X | X |
| [CamVid](http://mi.eng.cam.ac.uk/research/projects/VideoRec/CamVid/) | X | X |
+| [VGGFace2](https://github.com/ox-vgg/vgg_face2) | X | X |
## Deep learning serverless functions for automatic labeling
diff --git a/cvat/apps/dataset_manager/formats/README.md b/cvat/apps/dataset_manager/formats/README.md
index 38ff0676217..8e61fdbbb2d 100644
--- a/cvat/apps/dataset_manager/formats/README.md
+++ b/cvat/apps/dataset_manager/formats/README.md
@@ -20,6 +20,7 @@
- [TF detection API](#tfrecord)
- [ImageNet](#imagenet)
- [CamVid](#camvid)
+ - [VGGFace2](#vggface2)
## How to add a new annotation format support
@@ -874,3 +875,34 @@ has own color which corresponds to a label.
Uploaded file: a zip archive of the structure above
- supported annotations: Polygons
+
+### [VGGFace2](https://github.com/ox-vgg/vgg_face2)
+
+#### VGGFace2 Dumper
+
+Downloaded file: a zip archive of the following structure:
+
+```bash
+taskname.zip/
+├── labels.txt # optional
+├── /
+| ├── label0/
+| | └── image1.jpg
+| └── label1/
+| └── image2.jpg
+└── bb_landmark/
+ ├── loose_bb_.csv
+ └── loose_landmark_.csv
+# labels.txt
+# n000001 car
+label0
+label1
+```
+
+- supported annotations: Rectangles, Points (landmarks - groups of 5 points)
+
+#### VGGFace2 Loader
+
+Uploaded file: a zip archive of the structure above
+
+- supported annotations: Rectangles, Points (landmarks - groups of 5 points)
diff --git a/cvat/apps/dataset_manager/formats/registry.py b/cvat/apps/dataset_manager/formats/registry.py
index 46039f25fcd..5218ff28413 100644
--- a/cvat/apps/dataset_manager/formats/registry.py
+++ b/cvat/apps/dataset_manager/formats/registry.py
@@ -95,3 +95,4 @@ def make_exporter(name):
import cvat.apps.dataset_manager.formats.yolo
import cvat.apps.dataset_manager.formats.imagenet
import cvat.apps.dataset_manager.formats.camvid
+import cvat.apps.dataset_manager.formats.vggface2
diff --git a/cvat/apps/dataset_manager/formats/vggface2.py b/cvat/apps/dataset_manager/formats/vggface2.py
new file mode 100644
index 00000000000..528f52c76d7
--- /dev/null
+++ b/cvat/apps/dataset_manager/formats/vggface2.py
@@ -0,0 +1,32 @@
+# Copyright (C) 2021 Intel Corporation
+#
+# SPDX-License-Identifier: MIT
+
+import zipfile
+from tempfile import TemporaryDirectory
+
+from datumaro.components.dataset import Dataset
+
+from cvat.apps.dataset_manager.bindings import CvatTaskDataExtractor, \
+ import_dm_annotations
+from cvat.apps.dataset_manager.util import make_zip_archive
+
+from .registry import dm_env, exporter, importer
+
+
+@exporter(name='VGGFace2', ext='ZIP', version='1.0')
+def _export(dst_file, task_data, save_images=False):
+ dataset = Dataset.from_extractors(CvatTaskDataExtractor(
+ task_data, include_images=save_images), env=dm_env)
+ with TemporaryDirectory() as temp_dir:
+ dataset.export(temp_dir, 'vgg_face2', save_images=save_images)
+
+ make_zip_archive(temp_dir, dst_file)
+
+@importer(name='VGGFace2', ext='ZIP', version='1.0')
+def _import(src_file, task_data):
+ with TemporaryDirectory() as tmp_dir:
+ zipfile.ZipFile(src_file).extractall(tmp_dir)
+
+ dataset = Dataset.import_from(tmp_dir, 'vgg_face2', env=dm_env)
+ import_dm_annotations(dataset, task_data)
diff --git a/cvat/apps/dataset_manager/tests/test_formats.py b/cvat/apps/dataset_manager/tests/test_formats.py
index 5103da65ba3..f9b39b57436 100644
--- a/cvat/apps/dataset_manager/tests/test_formats.py
+++ b/cvat/apps/dataset_manager/tests/test_formats.py
@@ -282,6 +282,7 @@ def test_export_formats_query(self):
'YOLO 1.1',
'ImageNet 1.0',
'CamVid 1.0',
+ 'VGGFace2 1.0',
})
def test_import_formats_query(self):
@@ -300,6 +301,7 @@ def test_import_formats_query(self):
'YOLO 1.1',
'ImageNet 1.0',
'CamVid 1.0',
+ 'VGGFace2 1.0',
})
def test_exports(self):
@@ -312,6 +314,9 @@ def check(file_path):
self.skipTest("Format is disabled")
format_name = f.DISPLAY_NAME
+ if format_name == "VGGFace2 1.0":
+ self.skipTest("Format does not support multiple shapes for one item")
+
for save_images in { True, False }:
images = self._generate_task_images(3)
task = self._generate_task(images)
@@ -337,6 +342,7 @@ def test_empty_images_are_exported(self):
('YOLO 1.1', 'yolo'),
('ImageNet 1.0', 'imagenet_txt'),
('CamVid 1.0', 'camvid'),
+ ('VGGFace2 1.0', 'vgg_face2'),
]:
with self.subTest(format=format_name):
if not dm.formats.registry.EXPORT_FORMATS[format_name].ENABLED:
diff --git a/cvat/apps/engine/tests/test_rest_api.py b/cvat/apps/engine/tests/test_rest_api.py
index d9d2c182a8e..9d37e6a71c1 100644
--- a/cvat/apps/engine/tests/test_rest_api.py
+++ b/cvat/apps/engine/tests/test_rest_api.py
@@ -16,8 +16,6 @@
from glob import glob
from io import BytesIO
from unittest import mock
-import open3d as o3d
-import struct
import av
import numpy as np
@@ -739,7 +737,7 @@ def _run_api_v1_users(self, user):
return response
- def _check_response(self, user, response, is_full):
+ def _check_response(self, user, response, is_full=True):
self.assertEqual(response.status_code, status.HTTP_200_OK)
for user_info in response.data['results']:
db_user = getattr(self, user_info['username'])
@@ -3770,6 +3768,17 @@ def _get_initial_annotation(annotation_format):
"occluded": False,
}]
+ points_wo_attrs = [{
+ "frame": 1,
+ "label_id": task["labels"][1]["id"],
+ "group": 0,
+ "source": "manual",
+ "attributes": [],
+ "points": [20.0, 0.1, 10, 3.22, 4, 7, 10, 30, 1, 2],
+ "type": "points",
+ "occluded": False,
+ }]
+
tags_wo_attrs = [{
"frame": 2,
"label_id": task["labels"][1]["id"],
@@ -3855,6 +3864,11 @@ def _get_initial_annotation(annotation_format):
annotations["shapes"] = rectangle_shapes_wo_attrs \
+ polygon_shapes_wo_attrs
+ elif annotation_format == "VGGFace2 1.0":
+ annotations["tags"] = tags_wo_attrs
+ annotations["shapes"] = points_wo_attrs \
+ + rectangle_shapes_wo_attrs
+
else:
raise Exception("Unknown format {}".format(annotation_format))