Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

YOLOv8 classification format #8475

Merged
merged 13 commits into from
Oct 7, 2024
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,10 @@ For more information about the supported formats, see:
| [LFW](http://vis-www.cs.umass.edu/lfw/) | ✔️ | ✔️ |
| [Supervisely Point Cloud Format](https://docs.supervise.ly/data-organization/00_ann_format_navi) | ✔️ | ✔️ |
| [YOLOv8 Detection](https://docs.ultralytics.com/datasets/detect/) | ✔️ | ✔️ |
| [YOLOv8 Oriented Bounding Boxes](https://docs.ultralytics.com/datasets/obb/) | ✔️ | ✔️ |
| [YOLOv8 Segmentation](https://docs.ultralytics.com/datasets/segment/) | ✔️ | ✔️ |
| [YOLOv8 Pose](https://docs.ultralytics.com/datasets/pose/) | ✔️ | ✔️ |
| [YOLOv8 Oriented Bounding Boxes](https://docs.ultralytics.com/datasets/obb/) | ✔️ | ✔️ |
| [YOLOv8 Segmentation](https://docs.ultralytics.com/datasets/segment/) | ✔️ | ✔️ |
| [YOLOv8 Pose](https://docs.ultralytics.com/datasets/pose/) | ✔️ | ✔️ |
| [YOLOv8 Classification](https://docs.ultralytics.com/datasets/classify/) | ✔️ | ✔️ |

<!--lint enable maximum-line-length-->

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### Added

- Support for YOLOv8 Classification format
(<https://github.com/cvat-ai/cvat/pull/8475>)
10 changes: 10 additions & 0 deletions cvat/apps/dataset_manager/formats/yolo.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ def _export_yolov8_pose(*args, **kwargs):
_export_common(*args, format_name='yolov8_pose', **kwargs)


@exporter(name='YOLOv8 Classification', ext='ZIP', version='1.0')
def _export_yolov8_classification(*args, **kwargs):
_export_common(*args, format_name='yolov8_classification', **kwargs)


@importer(name='YOLOv8 Detection', ext="ZIP", version="1.0")
def _import_yolov8_detection(*args, **kwargs):
_import_common(*args, format_name="yolov8_detection", **kwargs)
Expand Down Expand Up @@ -134,3 +139,8 @@ def _import_yolov8_pose(src_file, temp_dir, instance_data, **kwargs):
import_kwargs=dict(skeleton_sub_labels=true_skeleton_point_labels),
**kwargs
)


@importer(name='YOLOv8 Classification', ext="ZIP", version="1.0")
def _import_yolov8_classification(*args, **kwargs):
_import_common(*args, format_name="yolov8_classification", **kwargs)
14 changes: 14 additions & 0 deletions cvat/apps/dataset_manager/tests/assets/annotations.json
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,20 @@
],
"tracks": []
},
"YOLOv8 Classification 1.0": {
"version": 0,
"tags": [
{
"frame": 0,
"label_id": null,
"group": 0,
"source": "manual",
"attributes": []
}
],
"shapes": [],
"tracks": []
},
"YOLOv8 Detection 1.0": {
"version": 0,
"tags": [],
Expand Down
3 changes: 3 additions & 0 deletions cvat/apps/dataset_manager/tests/test_formats.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ def test_export_formats_query(self):
'LFW 1.0',
'Cityscapes 1.0',
'Open Images V6 1.0',
'YOLOv8 Classification 1.0',
'YOLOv8 Oriented Bounding Boxes 1.0',
'YOLOv8 Detection 1.0',
'YOLOv8 Pose 1.0',
Expand Down Expand Up @@ -326,6 +327,7 @@ def test_import_formats_query(self):
'Open Images V6 1.0',
'Datumaro 1.0',
'Datumaro 3D 1.0',
'YOLOv8 Classification 1.0',
'YOLOv8 Oriented Bounding Boxes 1.0',
'YOLOv8 Detection 1.0',
'YOLOv8 Pose 1.0',
Expand Down Expand Up @@ -379,6 +381,7 @@ def test_empty_images_are_exported(self):
# ('KITTI 1.0', 'kitti') format does not support empty annotations
('LFW 1.0', 'lfw'),
# ('Cityscapes 1.0', 'cityscapes'), does not support, empty annotations
('YOLOv8 Classification 1.0', 'yolov8_classification'),
('YOLOv8 Oriented Bounding Boxes 1.0', 'yolov8_oriented_boxes'),
('YOLOv8 Detection 1.0', 'yolov8_detection'),
('YOLOv8 Pose 1.0', 'yolov8_pose'),
Expand Down
60 changes: 25 additions & 35 deletions cvat/apps/dataset_manager/tests/test_rest_api_formats.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,22 @@
with open(annotation_path) as file:
annotations = json.load(file)

DEFAULT_ATTRIBUTES_FORMATS = [
"VGGFace2 1.0",
"WiderFace 1.0",
"YOLOv8 Classification 1.0",
"YOLO 1.1",
"YOLOv8 Detection 1.0",
"YOLOv8 Segmentation 1.0",
"YOLOv8 Oriented Bounding Boxes 1.0",
"YOLOv8 Pose 1.0",
"PASCAL VOC 1.1",
"Segmentation mask 1.1",
"ImageNet 1.0",
"Cityscapes 1.0",
"MOTS PNG 1.0",
]


def generate_image_file(filename, size=(100, 50)):
f = BytesIO()
Expand Down Expand Up @@ -401,14 +417,8 @@ def test_api_v2_dump_and_upload_annotations_with_objects_type_is_shape(self):
else:
task = self._create_task(tasks["main"], images)
task_id = task["id"]
if dump_format_name in [
"Cityscapes 1.0", "Datumaro 1.0",
"ImageNet 1.0", "MOTS PNG 1.0",
"PASCAL VOC 1.1", "Segmentation mask 1.1",
"VGGFace2 1.0",
"WiderFace 1.0", "YOLO 1.1",
"YOLOv8 Detection 1.0", "YOLOv8 Segmentation 1.0",
"YOLOv8 Oriented Bounding Boxes 1.0", "YOLOv8 Pose 1.0",
if dump_format_name in DEFAULT_ATTRIBUTES_FORMATS + [
"Datumaro 1.0",
]:
self._create_annotations(task, dump_format_name, "default")
else:
Expand Down Expand Up @@ -510,14 +520,7 @@ def test_api_v2_dump_annotations_with_objects_type_is_track(self):
task = self._create_task(tasks["main"], video)
task_id = task["id"]

if dump_format_name in [
"Cityscapes 1.0", "ImageNet 1.0",
"MOTS PNG 1.0", "PASCAL VOC 1.1",
"Segmentation mask 1.1",
"VGGFace2 1.0", "WiderFace 1.0", "YOLO 1.1",
"YOLOv8 Detection 1.0", "YOLOv8 Segmentation 1.0",
"YOLOv8 Oriented Bounding Boxes 1.0", "YOLOv8 Pose 1.0",
]:
if dump_format_name in DEFAULT_ATTRIBUTES_FORMATS:
self._create_annotations(task, dump_format_name, "default")
else:
self._create_annotations(task, dump_format_name, "random")
Expand Down Expand Up @@ -951,13 +954,8 @@ def test_api_v2_rewriting_annotations(self):
task = self._create_task(tasks["main"], images)
task_id = task["id"]

if dump_format_name in [
"MOT 1.1", "PASCAL VOC 1.1", "Segmentation mask 1.1",
"YOLO 1.1", "ImageNet 1.0",
"WiderFace 1.0", "VGGFace2 1.0",
"Datumaro 1.0", "Open Images V6 1.0", "KITTI 1.0",
"YOLOv8 Detection 1.0", "YOLOv8 Segmentation 1.0",
"YOLOv8 Oriented Bounding Boxes 1.0", "YOLOv8 Pose 1.0",
if dump_format_name in DEFAULT_ATTRIBUTES_FORMATS + [
"MOT 1.1", "Datumaro 1.0", "Open Images V6 1.0", "KITTI 1.0",
]:
self._create_annotations(task, dump_format_name, "default")
else:
Expand Down Expand Up @@ -1067,14 +1065,9 @@ def test_api_v2_tasks_annotations_dump_and_upload_with_datumaro(self):
task = self._create_task(tasks["main"], images)

# create annotations
if dump_format_name in [
"MOT 1.1", "MOTS PNG 1.0",
"PASCAL VOC 1.1", "Segmentation mask 1.1",
"YOLO 1.1", "ImageNet 1.0",
"WiderFace 1.0", "VGGFace2 1.0", "LFW 1.0",
if dump_format_name in DEFAULT_ATTRIBUTES_FORMATS + [
"MOT 1.1", "LFW 1.0",
"Open Images V6 1.0", "Datumaro 1.0", "KITTI 1.0",
"YOLOv8 Detection 1.0", "YOLOv8 Segmentation 1.0",
"YOLOv8 Oriented Bounding Boxes 1.0", "YOLOv8 Pose 1.0",
]:
self._create_annotations(task, dump_format_name, "default")
else:
Expand Down Expand Up @@ -2101,11 +2094,8 @@ def test_api_v2_export_import_dataset(self):

url = self._generate_url_dump_project_dataset(project['id'], dump_format_name)

if dump_format_name in [
"Cityscapes 1.0", "Datumaro 1.0", "ImageNet 1.0",
"MOT 1.1", "MOTS PNG 1.0", "PASCAL VOC 1.1",
"Segmentation mask 1.1", "VGGFace2 1.0",
"WiderFace 1.0", "YOLO 1.1", "YOLOv8 Detection 1.0",
if dump_format_name in DEFAULT_ATTRIBUTES_FORMATS + [
"Datumaro 1.0", "MOT 1.1",
]:
self._create_annotations(task, dump_format_name, "default")
else:
Expand Down
2 changes: 1 addition & 1 deletion cvat/requirements/base.in
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ azure-storage-blob==12.13.0
boto3==1.17.61
clickhouse-connect==0.6.8
coreapi==2.3.3
datumaro @ git+https://github.com/cvat-ai/datumaro.git@393cb666529067060ff57e30cb6e448669274f35
datumaro @ git+https://github.com/cvat-ai/datumaro.git@e612d1bfb76a3c3d3d545187338c841a246619fb
dj-pagination==2.5.0
# Despite direct indication allauth in requirements we should keep 'with_social' for dj-rest-auth
# to avoid possible further versions conflicts (we use registration functionality)
Expand Down
54 changes: 27 additions & 27 deletions cvat/requirements/base.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SHA1:576a1a528bac33626df6c8d11c983263f7a175eb
# SHA1:9ff984f33ae139c68d90acc3e338c6cef7ecf6e9
#
# This file is autogenerated by pip-compile-multi
# To update, run:
Expand All @@ -15,7 +15,7 @@ attrs==21.4.0
# -r cvat/requirements/base.in
# datumaro
# jsonschema
azure-core==1.30.2
azure-core==1.31.0
# via
# azure-storage-blob
# msrest
Expand All @@ -29,12 +29,12 @@ botocore==1.20.112
# s3transfer
cachetools==5.5.0
# via google-auth
certifi==2024.7.4
certifi==2024.8.30
# via
# clickhouse-connect
# msrest
# requests
cffi==1.17.0
cffi==1.17.1
# via cryptography
charset-normalizer==3.3.2
# via requests
Expand All @@ -50,13 +50,13 @@ coreschema==0.0.4
# via coreapi
crontab==1.0.1
# via rq-scheduler
cryptography==43.0.0
cryptography==43.0.1
# via
# azure-storage-blob
# pyjwt
cycler==0.12.1
# via matplotlib
datumaro @ git+https://github.com/cvat-ai/datumaro.git@393cb666529067060ff57e30cb6e448669274f35
datumaro @ git+https://github.com/cvat-ai/datumaro.git@e612d1bfb76a3c3d3d545187338c841a246619fb
# via -r cvat/requirements/base.in
defusedxml==0.7.1
# via
Expand All @@ -66,9 +66,9 @@ deprecated==1.2.14
# via limits
dj-pagination==2.5.0
# via -r cvat/requirements/base.in
dj-rest-auth[with_social]==5.0.2
dj-rest-auth[with-social]==5.0.2
# via -r cvat/requirements/base.in
django==4.2.15
django==4.2.16
# via
# -r cvat/requirements/base.in
# dj-rest-auth
Expand Down Expand Up @@ -116,17 +116,17 @@ easyprocess==1.1
# via pyunpack
entrypoint2==1.1
# via pyunpack
fonttools==4.53.1
fonttools==4.54.1
# via matplotlib
freezegun==1.5.1
# via rq-scheduler
furl==2.1.0
# via -r cvat/requirements/base.in
google-api-core==2.19.2
google-api-core==2.20.0
# via
# google-cloud-core
# google-cloud-storage
google-auth==2.34.0
google-auth==2.35.0
# via
# google-api-core
# google-cloud-core
Expand All @@ -135,19 +135,19 @@ google-cloud-core==2.4.1
# via google-cloud-storage
google-cloud-storage==1.42.0
# via -r cvat/requirements/base.in
google-crc32c==1.5.0
google-crc32c==1.6.0
# via google-resumable-media
google-resumable-media==2.7.2
# via google-cloud-storage
googleapis-common-protos==1.65.0
# via google-api-core
h5py==3.11.0
h5py==3.12.1
# via datumaro
idna==3.8
idna==3.10
# via requests
importlib-metadata==8.4.0
importlib-metadata==8.5.0
# via clickhouse-connect
importlib-resources==6.4.4
importlib-resources==6.4.5
# via limits
inflection==0.5.1
# via drf-spectacular
Expand All @@ -165,7 +165,7 @@ jmespath==0.10.0
# botocore
jsonschema==4.17.3
# via drf-spectacular
kiwisolver==1.4.5
kiwisolver==1.4.7
# via matplotlib
limits==3.13.0
# via python-logstash-async
Expand All @@ -183,7 +183,7 @@ matplotlib==3.8.4
# via
# datumaro
# pycocotools
mmh3==4.1.0
mmh3==5.0.1
# via pottery
msrest==0.7.1
# via azure-storage-blob
Expand All @@ -203,7 +203,7 @@ packaging==24.1
# matplotlib
# nibabel
# tensorboardx
pandas==2.2.2
pandas==2.2.3
# via datumaro
patool==1.12
# via -r cvat/requirements/base.in
Expand All @@ -213,7 +213,7 @@ pottery==3.0.0
# via -r cvat/requirements/base.in
proto-plus==1.24.0
# via google-api-core
protobuf==5.27.4
protobuf==5.28.2
# via
# google-api-core
# googleapis-common-protos
Expand All @@ -223,12 +223,12 @@ psutil==5.9.4
# via -r cvat/requirements/base.in
psycopg2-binary==2.9.5
# via -r cvat/requirements/base.in
pyasn1==0.6.0
pyasn1==0.6.1
# via
# pyasn1-modules
# python-ldap
# rsa
pyasn1-modules==0.4.0
pyasn1-modules==0.4.1
# via
# google-auth
# python-ldap
Expand Down Expand Up @@ -261,7 +261,7 @@ python3-openid==3.2.0
# via django-allauth
python3-saml==1.16.0
# via django-allauth
pytz==2024.1
pytz==2024.2
# via
# clickhouse-connect
# djangorestframework
Expand Down Expand Up @@ -311,7 +311,7 @@ ruamel-yaml==0.18.6
# via datumaro
ruamel-yaml-clib==0.2.8
# via ruamel-yaml
rules==3.4
rules==3.5
# via -r cvat/requirements/base.in
s3transfer==0.4.2
# via boto3
Expand All @@ -337,13 +337,13 @@ typing-extensions==4.12.2
# datumaro
# limits
# pottery
tzdata==2024.1
tzdata==2024.2
# via pandas
uritemplate==4.1.1
# via
# coreapi
# drf-spectacular
urllib3==1.26.19
urllib3==1.26.20
# via
# botocore
# clickhouse-connect
Expand All @@ -354,7 +354,7 @@ xmlsec==1.3.14
# via
# -r cvat/requirements/base.in
# python3-saml
zipp==3.20.1
zipp==3.20.2
# via importlib-metadata
zstandard==0.23.0
# via clickhouse-connect
Loading
Loading