Add KITTI format (#3757)

main
Kirill Sizov 4 years ago committed by GitHub
parent cc801b21ed
commit e4aa0ea15a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add a tutorial on attaching cloud storage AWS-S3 (<https://github.com/openvinotoolkit/cvat/pull/3745>)
and Azure Blob Container (<https://github.com/openvinotoolkit/cvat/pull/3778>)
- The feature to remove annotations in a specified range of frames (<https://github.com/openvinotoolkit/cvat/pull/3617>)
- Add KITTI segmentation and detection format (<https://github.com/openvinotoolkit/cvat/pull/3757>)
- Add LFW format (<https://github.com/openvinotoolkit/cvat/pull/3770>)
- Add Cityscapes format (<https://github.com/openvinotoolkit/cvat/pull/3758>)
- Add Open Images V6 format (<https://github.com/openvinotoolkit/cvat/pull/3679>)

@ -0,0 +1,53 @@
# Copyright (C) 2021 Intel Corporation
#
# SPDX-License-Identifier: MIT
import os.path as osp
from tempfile import TemporaryDirectory
from datumaro.components.dataset import Dataset
from datumaro.plugins.kitti_format.format import KittiPath, write_label_map
from pyunpack import Archive
from cvat.apps.dataset_manager.bindings import (GetCVATDataExtractor,
ProjectData, import_dm_annotations)
from cvat.apps.dataset_manager.util import make_zip_archive
from .registry import dm_env, exporter, importer
from .utils import make_colormap
@exporter(name='KITTI', ext='ZIP', version='1.0')
def _export(dst_file, instance_data, save_images=False):
dataset = Dataset.from_extractors(GetCVATDataExtractor(instance_data,
include_images=save_images), env=dm_env)
with TemporaryDirectory() as tmp_dir:
dataset.transform('polygons_to_masks')
dataset.transform('merge_instance_segments')
dataset.export(tmp_dir, format='kitti',
label_map={k: v[0] for k, v in make_colormap(instance_data).items()},
apply_colormap=True, save_images=save_images
)
make_zip_archive(tmp_dir, dst_file)
@importer(name='KITTI', ext='ZIP', version='1.0')
def _import(src_file, instance_data):
with TemporaryDirectory() as tmp_dir:
Archive(src_file.name).extractall(tmp_dir)
color_map = {k: v[0] for k, v in make_colormap(instance_data).items()}
color_map_path = osp.join(tmp_dir, KittiPath.LABELMAP_FILE)
if not osp.isfile(color_map_path):
write_label_map(color_map_path, color_map)
dataset = Dataset.import_from(tmp_dir, format='kitti', env=dm_env)
labels_meta = instance_data.meta['project']['labels'] \
if isinstance(instance_data, ProjectData) else instance_data.meta['task']['labels']
if 'background' not in [label['name'] for _, label in labels_meta]:
dataset.filter('/item/annotation[label != "background"]',
filter_annotations=True)
dataset.transform('masks_to_polygons')
import_dm_annotations(dataset, instance_data)

@ -121,6 +121,7 @@ import cvat.apps.dataset_manager.formats.market1501
import cvat.apps.dataset_manager.formats.icdar
import cvat.apps.dataset_manager.formats.velodynepoint
import cvat.apps.dataset_manager.formats.pointcloud
import cvat.apps.dataset_manager.formats.kitti
import cvat.apps.dataset_manager.formats.lfw
import cvat.apps.dataset_manager.formats.cityscapes
import cvat.apps.dataset_manager.formats.openimages

@ -7,7 +7,6 @@ from hashlib import blake2s
from datumaro.util.os_util import make_file_name
def get_color_from_index(index):
def get_bit(number, index):
return (number >> index) & 1

@ -1198,6 +1198,24 @@
],
"tracks": []
},
"KITTI 1.0": {
"version": 0,
"tags": [],
"shapes": [
{
"type": "polygon",
"occluded": false,
"z_order": 0,
"points": [10.0, 20.0, 10.0, 25.0, 20.0, 10.0, 20.0, 25.0, 10.0, 20.0],
"frame": 0,
"label_id": null,
"group": 0,
"source": "manual",
"attributes": []
}
],
"tracks": []
},
"LFW 1.0": {
"version": 0,
"tags": [

@ -296,6 +296,7 @@ class TaskExportTest(_DbTestBase):
'ICDAR Segmentation 1.0',
'Kitti Raw Format 1.0',
'Sly Point Cloud Format 1.0',
'KITTI 1.0',
'LFW 1.0',
'Cityscapes 1.0',
'Open Images V6 1.0'
@ -325,6 +326,7 @@ class TaskExportTest(_DbTestBase):
'ICDAR Segmentation 1.0',
'Kitti Raw Format 1.0',
'Sly Point Cloud Format 1.0',
'KITTI 1.0',
'LFW 1.0',
'Cityscapes 1.0',
'Open Images V6 1.0',
@ -376,6 +378,7 @@ class TaskExportTest(_DbTestBase):
('ICDAR Recognition 1.0', 'icdar_word_recognition'),
('ICDAR Localization 1.0', 'icdar_text_localization'),
('ICDAR Segmentation 1.0', 'icdar_text_segmentation'),
# ('KITTI 1.0', 'kitti') format does not support empty annotations
('LFW 1.0', 'lfw'),
# ('Cityscapes 1.0', 'cityscapes'), does not support, empty annotations
]:
@ -785,17 +788,6 @@ class TaskAnnotationsImportTest(_DbTestBase):
"type": "rectangle",
"occluded": False,
}]
elif annotation_format == "VGGFace2 1.0":
shapes = [{
"frame": 1,
"label_id": task["labels"][1]["id"],
"group": None,
"source": "manual",
"attributes": [],
"points": [2.0, 2.1, 40, 50.7],
"type": "rectangle",
"occluded": False
}]
else:
rectangle_shape_wo_attrs = {
"frame": 1,
@ -803,7 +795,7 @@ class TaskAnnotationsImportTest(_DbTestBase):
"group": 0,
"source": "manual",
"attributes": [],
"points": [2.0, 2.1, 40, 50.7],
"points": [2.0, 2.1, 40, 10.7],
"type": "rectangle",
"occluded": False,
}
@ -823,7 +815,7 @@ class TaskAnnotationsImportTest(_DbTestBase):
"value": task["labels"][0]["attributes"][1]["default_value"]
}
],
"points": [1.0, 2.1, 10.6, 53.22],
"points": [1.0, 2.1, 10.6, 13.22],
"type": "rectangle",
"occluded": False,
}
@ -838,7 +830,7 @@ class TaskAnnotationsImportTest(_DbTestBase):
{
"frame": 0,
"attributes": [],
"points": [1.0, 2.1, 10.6, 53.22, 90, 90.222],
"points": [1.0, 2.1, 10.6, 53.22, 30, 20.222],
"type": "polygon",
"occluded": False,
"outside": False
@ -871,7 +863,7 @@ class TaskAnnotationsImportTest(_DbTestBase):
}
if annotation_format == "VGGFace2 1.0":
shapes = rectangle_shape_wo_attrs
shapes = [rectangle_shape_wo_attrs]
elif annotation_format == "CVAT 1.1":
shapes = [rectangle_shape_wo_attrs,
rectangle_shape_with_attrs]

@ -872,6 +872,7 @@ class TaskDumpUploadTest(_DbTestBase):
with self.subTest(format=upload_format_name):
if upload_format_name in [
"MOTS PNG 1.0", # issue #2925 and changed points values
"KITTI 1.0", # format does not support empty annotation
"Cityscapes 1.0" # formats doesn't support empty annotations
]:
self.skipTest("Format is fail")
@ -920,7 +921,7 @@ class TaskDumpUploadTest(_DbTestBase):
"PASCAL VOC 1.1", "Segmentation mask 1.1",
"TFRecord 1.0", "YOLO 1.1", "ImageNet 1.0",
"WiderFace 1.0", "VGGFace2 1.0", "Cityscapes 1.0",
"Datumaro 1.0", "Open Images V6 1.0"
"Datumaro 1.0", "Open Images V6 1.0", "KITTI 1.0"
]:
self._create_annotations(task, dump_format_name, "default")
else:
@ -1012,6 +1013,7 @@ class TaskDumpUploadTest(_DbTestBase):
"Open Images V6 1.0", # changed points values
'Kitti Raw Format 1.0',
'Sly Point Cloud Format 1.0',
'KITTI 1.0', # changed points values
'Cityscapes 1.0', # changed points value
'Datumaro 3D 1.0'
]:
@ -1034,7 +1036,7 @@ class TaskDumpUploadTest(_DbTestBase):
"PASCAL VOC 1.1", "Segmentation mask 1.1",
"TFRecord 1.0", "YOLO 1.1", "ImageNet 1.0",
"WiderFace 1.0", "VGGFace2 1.0", "LFW 1.0",
"Open Images V6 1.0", "Datumaro 1.0"
"Open Images V6 1.0", "Datumaro 1.0", "KITTI 1.0"
]:
self._create_annotations(task, dump_format_name, "default")
else:

@ -4822,6 +4822,10 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
annotations["shapes"] = points_wo_attrs \
+ tags_wo_attrs
elif annotation_format == "KITTI 1.0":
annotations["shapes"] = rectangle_shapes_wo_attrs \
+ polygon_shapes_wo_attrs
elif annotation_format == "Market-1501 1.0":
tags_with_attrs = [{
"frame": 1,

@ -5,11 +5,11 @@ weight: 5
# [MS COCO Object Detection](http://cocodataset.org/#format-data)
- [Format specification](https://github.com/openvinotoolkit/datumaro/blob/develop/docs/formats/coco_user_manual.md#format-specification)
- [Format specification](https://openvinotoolkit.github.io/datumaro/docs/formats/coco/)
## COCO export
Downloaded file: a zip archive with the structure described [here](https://github.com/openvinotoolkit/datumaro/blob/develop/docs/formats/coco_user_manual.md#load-coco-dataset)
Downloaded file: a zip archive with the structure described [here](https://openvinotoolkit.github.io/datumaro/docs/formats/coco/#import-coco-dataset)
- supported annotations: Polygons, Rectangles
- supported attributes:
@ -21,13 +21,13 @@ Downloaded file: a zip archive with the structure described [here](https://githu
- `score` (number) - the annotation `score` field
- arbitrary attributes - will be stored in the `attributes` annotation section
Support for COCO tasks via Datumaro is described [here](https://github.com/openvinotoolkit/datumaro/blob/develop/docs/formats/coco_user_manual.md#export-to-coco)
Support for COCO tasks via Datumaro is described [here](https://openvinotoolkit.github.io/datumaro/docs/formats/coco/#export-to-other-formats)
For example, [support for COCO keypoints over Datumaro](https://github.com/openvinotoolkit/cvat/issues/2910#issuecomment-726077582):
1. Install [Datumaro](https://github.com/openvinotoolkit/datumaro)
`pip install datumaro`
1. Export the task in the `Datumaro` format, unzip
1. Export the Datumaro project in `coco` / `coco_person_keypoints` formats
2. Export the task in the `Datumaro` format, unzip
3. Export the Datumaro project in `coco` / `coco_person_keypoints` formats
`datum export -f coco -p path/to/project [-- --save-images]`
This way, one can export CVAT points as single keypoints or
@ -36,29 +36,29 @@ keypoint lists (without the `visibility` COCO flag).
## COCO import
Uploaded file: a single unpacked `*.json` or a zip archive with the structure described
[here](https://github.com/openvinotoolkit/datumaro/blob/develop/docs/formats/coco_user_manual.md#load-coco-dataset)
[here](https://openvinotoolkit.github.io/datumaro/docs/formats/coco/#import-coco-dataset)
(without images).
- supported annotations: Polygons, Rectangles (if the `segmentation` field is empty)
## How to create a task from MS COCO dataset
1. Download the [MS COCO dataset](https://github.com/openvinotoolkit/datumaro/blob/develop/docs/formats/coco_user_manual.md#load-COCO-dataset).
1. Download the [MS COCO dataset](https://openvinotoolkit.github.io/datumaro/docs/formats/coco/#import-coco-dataset).
For example `val images` and `instances` annotations
1. Create a CVAT task with the following labels:
2. Create a CVAT task with the following labels:
```bash
person bicycle car motorcycle airplane bus train truck boat "traffic light" "fire hydrant" "stop sign" "parking meter" bench bird cat dog horse sheep cow elephant bear zebra giraffe backpack umbrella handbag tie suitcase frisbee skis snowboard "sports ball" kite "baseball bat" "baseball glove" skateboard surfboard "tennis racket" bottle "wine glass" cup fork knife spoon bowl banana apple sandwich orange broccoli carrot "hot dog" pizza donut cake chair couch "potted plant" bed "dining table" toilet tv laptop mouse remote keyboard "cell phone" microwave oven toaster sink refrigerator book clock vase scissors "teddy bear" "hair drier" toothbrush
```
1. Select `val2017.zip` as data
3. Select `val2017.zip` as data
(See [Creating an annotation task](/docs/manual/basics/creating_an_annotation_task/)
guide for details)
2. Unpack `annotations_trainval2017.zip`
4. Unpack `annotations_trainval2017.zip`
3. click `Upload annotation` button,
5. click `Upload annotation` button,
choose `COCO 1.1` and select `instances_val2017.json`
annotation file. It can take some time.

@ -0,0 +1,95 @@
---
linkTitle: 'KITTI'
weight: 17
---
# [KITTI](http://www.cvlibs.net/datasets/kitti/)
- [Format specification for KITTI detection](https://s3.eu-central-1.amazonaws.com/avg-kitti/devkit_object.zip)
- [Format specification for KITTI segmentation](https://s3.eu-central-1.amazonaws.com/avg-kitti/devkit_semantics.zip)
- supported annotations:
- Rectangles (detection task)
- Polygon (segmentation task)
- supported attributes:
- `occluded` (both UI option and a separate attribute).
Indicates that a significant portion of the object within
the bounding box is occluded by another object
- `truncated` supported only for rectangles
(should be defined for labels as `checkbox` -es).
Indicates that the bounding box specified for the object
does not correspond to the full extent of the object
- 'is_crowd' supported only for polygons
(should be defined for labels as `checkbox` -es).
Indicates that the annotation covers multiple instances of the same class
## KITTI annotations export
Downloaded file: a zip archive of the following structure:
```
└─ annotations.zip/
├── label_colors.txt # list of pairs r g b label_name
├── labels.txt # list of labels
└── default/
├── label_2/ # left color camera label files
│ ├── <image_name_1>.txt
│ ├── <image_name_2>.txt
│ └── ...
├── instance/ # instance segmentation masks
│ ├── <image_name_1>.png
│ ├── <image_name_2>.png
│ └── ...
├── semantic/ # semantic segmentation masks (labels are encoded by its id)
│ ├── <image_name_1>.png
│ ├── <image_name_2>.png
│ └── ...
└── semantic_rgb/ # semantic segmentation masks (labels are encoded by its color)
├── <image_name_1>.png
├── <image_name_2>.png
└── ...
```
## KITTI annotations import
You can upload KITTI annotations in two ways:
rectangles for the detection task and
masks for the segmentation task.
For detection tasks the uploading archive should have the following structure:
```
└─ annotations.zip/
├── labels.txt # optional, labels list for non-original detection labels
└── <subset_name>/
├── label_2/ # left color camera label files
│ ├── <image_name_1>.txt
│ ├── <image_name_2>.txt
│ └── ...
```
For segmentation tasks the uploading archive should have the following structure:
```
└─ annotations.zip/
├── label_colors.txt # optional, color map for non-original segmentation labels
└── <subset_name>/
├── instance/ # instance segmentation masks
│ ├── <image_name_1>.png
│ ├── <image_name_2>.png
│ └── ...
├── semantic/ # optional, semantic segmentation masks (labels are encoded by its id)
│ ├── <image_name_1>.png
│ ├── <image_name_2>.png
│ └── ...
└── semantic_rgb/ # optional, semantic segmentation masks (labels are encoded by its color)
├── <image_name_1>.png
├── <image_name_2>.png
└── ...
```
All annotation files and masks should have structures
that are described in the original format specification.
Loading…
Cancel
Save