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

Project export #3365

Merged
merged 68 commits into from
Aug 6, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
c53e062
init
ActiveChooN Jun 22, 2021
46e89b0
Fixed typos
ActiveChooN Jun 23, 2021
22fafe3
Merge branch 'develop' into dk/project-export
ActiveChooN Jun 24, 2021
7f4a349
Fixed cache time value
ActiveChooN Jun 24, 2021
4a5bc3a
Added MOTS PNG
ActiveChooN Jun 28, 2021
c57ab56
Merge branch 'develop' into dk/project-export
ActiveChooN Jul 1, 2021
04d14c5
temp
ActiveChooN Jul 2, 2021
f6b833f
Another temp
ActiveChooN Jul 7, 2021
d45bec8
WIP on UI
ActiveChooN Jul 7, 2021
b23a9ba
Added working modal
ActiveChooN Jul 8, 2021
4c22e11
Moved task export to modal
ActiveChooN Jul 9, 2021
a4d6094
Fixed vscode files
ActiveChooN Jul 9, 2021
aadc83c
Removed task actions
ActiveChooN Jul 9, 2021
bcd2034
Fixed image_maker calling
ActiveChooN Jul 12, 2021
3aa16a1
Separated DataExtractor class
ActiveChooN Jul 12, 2021
b59ab03
wip
ActiveChooN Jul 14, 2021
5d9b512
Added export with CVAT format
ActiveChooN Jul 15, 2021
a914d05
Fixed format resetting
ActiveChooN Jul 15, 2021
3b480fa
Fixed dir creating
ActiveChooN Jul 15, 2021
2647eb9
Fixed export in CVAT formats
ActiveChooN Jul 16, 2021
15d226a
Added simple server tests, fixed datumaro format export
ActiveChooN Jul 20, 2021
3da98c4
Reverted settings change
ActiveChooN Jul 20, 2021
d70ee77
Merge branch 'develop' into dk/project-export
ActiveChooN Jul 20, 2021
b8b3d9c
Fixed merge
ActiveChooN Jul 20, 2021
e1f8db6
Fixed some comments
ActiveChooN Jul 21, 2021
98c9083
Update cvat/apps/dataset_manager/bindings.py
ActiveChooN Jul 21, 2021
84f8b7a
Fixed comment
ActiveChooN Jul 21, 2021
4f8d28d
Merge branch 'dk/project-export' of https://github.com/openvinotoolki…
ActiveChooN Jul 21, 2021
29ffac1
Added restrictions for 3d tasks
ActiveChooN Jul 22, 2021
4e2aac1
Fixed validator
ActiveChooN Jul 22, 2021
5a48dfc
Merge branch 'develop' into dk/project-export
ActiveChooN Jul 23, 2021
ff19e71
Fixed linter and tests
ActiveChooN Jul 23, 2021
3e6d7df
Merge remote-tracking branch 'origin/develop' into dk/project-export
ActiveChooN Jul 26, 2021
dc45b9f
Fixed comments
ActiveChooN Jul 27, 2021
6c683ac
Added file extesion to the form
ActiveChooN Jul 27, 2021
abdb59f
Added notification
ActiveChooN Jul 27, 2021
f4c4e87
Fixed header
ActiveChooN Jul 27, 2021
76c073c
Added default format for tasks
ActiveChooN Jul 27, 2021
370f337
Fixed test
ActiveChooN Jul 28, 2021
141f6a6
Merge branch 'develop' into dk/project-export
ActiveChooN Jul 29, 2021
c076584
Fixed notification
ActiveChooN Jul 29, 2021
1f5f6f2
Added some classes
dvkruchinin Jul 29, 2021
7d1b9cf
Tests adaptation
dvkruchinin Jul 29, 2021
3be269c
Merge branch 'dk/project-export' of https://github.com/openvinotoolki…
dvkruchinin Jul 29, 2021
f129f76
Rename classes
dvkruchinin Jul 29, 2021
dc4b56a
The next tests adapdation
dvkruchinin Jul 29, 2021
cd67f5b
Additional tests adaptations.
dvkruchinin Jul 29, 2021
c955995
Some rework main.yaml
dvkruchinin Jul 29, 2021
7e9fcaa
Added debug
dvkruchinin Jul 29, 2021
4be0540
Debug removed
dvkruchinin Jul 29, 2021
415e275
Fixed late binding problem
ActiveChooN Jul 30, 2021
e6c95a2
Fixed 3d default format
ActiveChooN Jul 30, 2021
4a66693
Merge branch 'develop' into dk/project-export
ActiveChooN Jul 30, 2021
c7ed863
Merge pull request #3485 from dvkruchinin/dkru/project-export-adjast-…
ActiveChooN Jul 30, 2021
0687808
Added support for project with 3d tasks
ActiveChooN Aug 2, 2021
7e412f4
Fixed test
ActiveChooN Aug 2, 2021
4fe5598
Merge branch 'develop' into dk/project-export
ActiveChooN Aug 3, 2021
e635db3
Update cvat/apps/dataset_manager/views.py
ActiveChooN Aug 3, 2021
e9f1fc1
Fixed function name
ActiveChooN Aug 3, 2021
0a06baf
Revert "Added support for project with 3d tasks"
ActiveChooN Aug 3, 2021
1387b2f
Changed defaulted subset
ActiveChooN Aug 3, 2021
cbb7a1e
Update cvat/apps/dataset_manager/bindings.py
ActiveChooN Aug 3, 2021
566e490
Fixed project extractor
ActiveChooN Aug 3, 2021
42a974e
Merge branch 'develop' into dk/project-export
ActiveChooN Aug 4, 2021
333bc88
Fixed project export cache invalidation
ActiveChooN Aug 5, 2021
9952d51
Merge branch 'develop' into dk/project-export
ActiveChooN Aug 5, 2021
f5c89ef
Added CHANGELOG, increased versions
ActiveChooN Aug 5, 2021
a73122f
Merge branch 'develop' into dk/project-export
Aug 6, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Revert "Added support for project with 3d tasks"
This reverts commit 0687808.
  • Loading branch information
ActiveChooN committed Aug 3, 2021
commit 0a06baffc4e9d24e0ecf37f1d22675ffd715c447
115 changes: 48 additions & 67 deletions cvat/apps/dataset_manager/bindings.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ class ProjectData(InstanceLabelData):
Track = NamedTuple('Track', [('label', str), ('group', int), ('source', str), ('shapes', List[TrackedShape]), ('task_id', int)])
Tag = NamedTuple('Tag', [('frame', int), ('label', str), ('attributes', List[InstanceLabelData.Attribute]), ('source', str), ('group', int), ('task_id', int)])
Tag.__new__.__defaults__ = (0, )
Frame = NamedTuple('Frame', [('task_id', int), ('subset', str), ('idx', int), ('id', int), ('frame', int), ('name', str), ('width', int), ('height', int), ('labeled_shapes', List[Union[LabeledShape, TrackedShape]]), ('tags', List[Tag])])
Frame = NamedTuple('Frame', [('task_id', int), ('subset', str), ('idx', int), ('frame', int), ('name', str), ('width', int), ('height', int), ('labeled_shapes', List[Union[LabeledShape, TrackedShape]]), ('tags', List[Tag])])

def __init__(self, annotation_irs: Mapping[str, AnnotationIR], db_project: Project, host: str, create_callback: Callable = None):
self._annotation_irs = annotation_irs
Expand Down Expand Up @@ -579,7 +579,6 @@ def _init_frame_info(self):
} for frame in range(task.data.size)})
else:
self._frame_info.update({(task.id, self.rel_frame_id(task.id, db_image.frame)): {
"id": db_image.id,
"path": mangle_image_name(db_image.path, task.subset, original_names),
"width": db_image.width,
"height": db_image.height,
Expand Down Expand Up @@ -683,7 +682,6 @@ def get_frame(task_id: int, idx: int) -> ProjectData.Frame:
task_id=task_id,
subset=frame_info["subset"],
idx=idx,
id=frame_info.get('id',0),
frame=abs_frame,
name=frame_info["path"],
height=frame_info["height"],
Expand Down Expand Up @@ -797,25 +795,20 @@ def __init__(self):
self._categories: Dict[datumaro.AnnotationType, datumaro.LabelCategories] = {}
ActiveChooN marked this conversation as resolved.
Show resolved Hide resolved

@staticmethod
def _load_categories(meta: dict, dimension):
def _load_categories(labels: list):
categories: Dict[datumaro.AnnotationType, datumaro.Categories] = {}

label_categories = datumaro.LabelCategories(attributes=['occluded'])

user_info = {}
if dimension == DimensionType.DIM_3D:
user_info = {"name": meta['owner']['username'],
"createdAt": meta['created'],
"updatedAt": meta['updated']}
for _, label in meta['labels']:
for _, label in labels:
label_categories.add(label['name'])
for _, attr in label['attributes']:
label_categories.attributes.add(attr['name'])


categories[datumaro.AnnotationType.label] = label_categories

return categories, user_info
return categories


def _read_cvat_anno(self, cvat_frame_anno: Union[ProjectData.Frame, TaskData.Frame], labels: list):
categories = self.categories()
Expand All @@ -830,9 +823,9 @@ def map_label(name): return label_cat.find(name)[0]


class CvatTaskDataExtractor(CVATDataExtractor):
def __init__(self, task_data, include_images = False, format_type = None, dimension = DimensionType.DIM_2D):
def __init__(self, task_data, include_images=False, format_type=None, dimension=DimensionType.DIM_2D):
super().__init__()
self._categories, self._user = self._load_categories(task_data.meta['task'], dimension=dimension)
self._categories, self._user = self._load_categories(task_data, dimension=dimension)
self._dimension = dimension
self._format_type = format_type
dm_items = []
Expand Down Expand Up @@ -898,9 +891,11 @@ def _make_image(i, **kwargs):
attributes["createdAt"] = self._user["createdAt"]
attributes["updatedAt"] = self._user["updatedAt"]
attributes["labels"] = []
for (idx, (_, label)) in enumerate(task_data.meta['task']['labels']):
attributes["labels"].append({"label_id": idx, "name": label["name"], "color": label["color"]})
index = 0
for _, label in task_data.meta['task']['labels']:
attributes["labels"].append({"label_id": index, "name": label["name"], "color": label["color"]})
attributes["track_id"] = -1
index += 1

dm_item = datumaro.DatasetItem(id=osp.split(frame_data.name)[-1].split('.')[0],
annotations=dm_anno, point_cloud=dm_image[0], related_images=dm_image[1],
Expand All @@ -910,6 +905,27 @@ def _make_image(i, **kwargs):

self._items = dm_items

@staticmethod
def _load_categories(cvat_anno, dimension): # pylint: disable=arguments-differ
categories = {}

label_categories = datumaro.LabelCategories(attributes=['occluded'])

user_info = {}
if dimension == DimensionType.DIM_3D:
user_info = {"name": cvat_anno.meta['task']['owner']['username'],
"createdAt": cvat_anno.meta['task']['created'],
"updatedAt": cvat_anno.meta['task']['updated']}
for _, label in cvat_anno.meta['task']['labels']:
label_categories.add(label['name'])
for _, attr in label['attributes']:
label_categories.attributes.add(attr['name'])


categories[datumaro.AnnotationType.label] = label_categories

return categories, user_info

def _read_cvat_anno(self, cvat_frame_anno: TaskData.Frame, labels: list):
categories = self.categories()
label_cat = categories[datumaro.AnnotationType.label]
Expand All @@ -922,11 +938,9 @@ def map_label(name): return label_cat.find(name)[0]
return convert_cvat_anno_to_dm(cvat_frame_anno, label_attrs, map_label, self._format_type, self._dimension)

class CVATProjectDataExtractor(CVATDataExtractor):
def __init__(self, project_data: ProjectData, include_images: bool = False, format_type: str = None, dimension: DimensionType = DimensionType.DIM_2D):
def __init__(self, project_data: ProjectData, include_images: bool = False):
super().__init__()
self._categories, self._user = self._load_categories(project_data.meta['project'], dimension)
self._dimension = dimension
self._format_type = format_type
self._categories = self._load_categories(project_data.meta['project']['labels'])

dm_items: List[datumaro.DatasetItem] = []

Expand All @@ -936,27 +950,12 @@ def __init__(self, project_data: ProjectData, include_images: bool = False, form
for task in project_data.tasks:
is_video = task.mode == 'interpolation'
ext_per_task[task.id] = FrameProvider.VIDEO_FRAME_EXT if is_video else ''
if self._dimension == DimensionType.DIM_3D:
def image_maker_factory(task):
def _make_image(i, **kwargs):
loader = osp.join(
task.data.get_upload_dirname(), kwargs['path'],
)
related_images = []
image = Img.objects.get(id=i)
for i in image.related_files.all():
path = osp.realpath(str(i.path))
if osp.isfile(path):
related_images.append(path)
return loader, related_images
return _make_image
image_maker_per_task[task.id] = image_maker_factory(task)
elif include_images:
if include_images:
frame_provider = FrameProvider(task.data)
if is_video:
# optimization for videos: use numpy arrays instead of bytes
# some formats or transforms can require image data
def image_maker_factory(task):
frame_provider = FrameProvider(task.data)
def image_maker_factory(frame_provider):
def _make_image(i, **kwargs):
loader = lambda _: frame_provider.get_frame(i,
quality=frame_provider.Quality.ORIGINAL,
Expand All @@ -965,58 +964,40 @@ def _make_image(i, **kwargs):
return _make_image
else:
# for images use encoded data to avoid recoding
def image_maker_factory(task):
frame_provider = FrameProvider(task.data)
def image_maker_factory(frame_provider):
def _make_image(i, **kwargs):
loader = lambda _: frame_provider.get_frame(i,
quality=frame_provider.Quality.ORIGINAL,
out_type=frame_provider.Type.BUFFER)[0].getvalue()
return ByteImage(data=loader, **kwargs)
return _make_image
image_maker_per_task[task.id] = image_maker_factory(task)
image_maker_per_task[task.id] = image_maker_factory(frame_provider)

for frame_data in project_data.group_by_frame(include_empty=True):
image_args = {
'path': frame_data.name + ext_per_task[frame_data.task_id],
'size': (frame_data.height, frame_data.width),
}
if self._dimension == DimensionType.DIM_3D:
dm_image = image_maker_per_task[frame_data.task_id](frame_data.id, **image_args)
elif include_images:
if include_images:
dm_image = image_maker_per_task[frame_data.task_id](frame_data.idx, **image_args)
else:
dm_image = Image(**image_args)
dm_anno = self._read_cvat_anno(frame_data, project_data.meta['project']['labels'])
if self._dimension == DimensionType.DIM_2D:
dm_item = datumaro.DatasetItem(id=osp.splitext(frame_data.name)[0],
annotations=dm_anno, image=dm_image,
subset=frame_data.subset,
attributes={'frame': frame_data.frame}
)
else:
attributes = {'frame': frame_data.frame}
if format_type == "sly_pointcloud":
attributes["name"] = self._user["name"]
attributes["createdAt"] = self._user["createdAt"]
attributes["updatedAt"] = self._user["updatedAt"]
attributes["labels"] = []
for (idx, (_, label)) in enumerate(project_data.meta['project']['labels']):
attributes["labels"].append({"label_id": idx, "name": label["name"], "color": label["color"]})
attributes["track_id"] = -1

dm_item = datumaro.DatasetItem(id=osp.split(frame_data.name)[-1].split('.')[0],
annotations=dm_anno, point_cloud=dm_image[0], related_images=dm_image[1],
attributes=attributes)
dm_item = datumaro.DatasetItem(id=osp.splitext(frame_data.name)[0],
annotations=dm_anno, image=dm_image,
subset=frame_data.subset,
attributes={'frame': frame_data.frame}
)
dm_items.append(dm_item)

self._items = dm_items


def GetCVATDataExtractor(instance_data: Union[ProjectData, TaskData], include_images: bool = False, format_type: str = None, dimension: DimensionType = DimensionType.DIM_2D):
def GetCVATDataExtractor(instance_data: Union[ProjectData, TaskData], include_images: bool=False):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably, we need to find more descriptive term instead of "instance".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, I can't think of a new one. I guess it's not a big problem, because it has a descriptive type. But if you have any ideas, I will change that.

if isinstance(instance_data, ProjectData):
return CVATProjectDataExtractor(instance_data, include_images, format_type, dimension)
return CVATProjectDataExtractor(instance_data, include_images)
else:
return CvatTaskDataExtractor(instance_data, include_images, format_type, dimension)
return CvatTaskDataExtractor(instance_data, include_images)

class CvatImportError(Exception):
pass
Expand Down
7 changes: 5 additions & 2 deletions cvat/apps/dataset_manager/formats/pointcloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from datumaro.components.dataset import Dataset

from cvat.apps.dataset_manager.bindings import (GetCVATDataExtractor,
from cvat.apps.dataset_manager.bindings import (CvatTaskDataExtractor, TaskData,
import_dm_annotations)
from cvat.apps.dataset_manager.util import make_zip_archive
from cvat.apps.engine.models import DimensionType
Expand All @@ -18,7 +18,10 @@
@exporter(name='Sly Point Cloud Format', ext='ZIP', version='1.0', dimension=DimensionType.DIM_3D)
def _export_images(dst_file, task_data, save_images=False):

dataset = Dataset.from_extractors(GetCVATDataExtractor(
if not isinstance(task_data, TaskData):
raise Exception("Export to \"Sly Point Cloud\" format is working only with tasks temporarily")

dataset = Dataset.from_extractors(CvatTaskDataExtractor(
task_data, include_images=save_images, format_type='sly_pointcloud', dimension=DimensionType.DIM_3D), env=dm_env)

with TemporaryDirectory() as temp_dir:
Expand Down
7 changes: 5 additions & 2 deletions cvat/apps/dataset_manager/formats/velodynepoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from datumaro.components.dataset import Dataset

from cvat.apps.dataset_manager.bindings import GetCVATDataExtractor, \
from cvat.apps.dataset_manager.bindings import CvatTaskDataExtractor, TaskData, \
import_dm_annotations
from .registry import dm_env

Expand All @@ -20,7 +20,10 @@
@exporter(name='Kitti Raw Format', ext='ZIP', version='1.0', dimension=DimensionType.DIM_3D)
def _export_images(dst_file, task_data, save_images=False):

dataset = Dataset.from_extractors(GetCVATDataExtractor(
if not isinstance(task_data, TaskData):
raise Exception("Export to \"Kitti raw\" format is working only with tasks temporarily")

dataset = Dataset.from_extractors(CvatTaskDataExtractor(
task_data, include_images=save_images, format_type="kitti_raw", dimension=DimensionType.DIM_3D), env=dm_env)

with TemporaryDirectory() as temp_dir:
Expand Down