From 072482ffe88f5143dd07db3ef9b981db8820daa4 Mon Sep 17 00:00:00 2001 From: Maria Khrustaleva Date: Thu, 1 Oct 2020 15:24:55 +0300 Subject: [PATCH] Changed "prepare data on the fly" functionality (#2217) * Added ability to upload meta information with video & some fixes * Added documentation for data on the fly preparation * Added ability to prepare meta information for video manually * fix * style: fix codacy issues * Refactoring * docs: add optional parameter * Add test * Add license header * Update CHANGELOG Co-authored-by: Boris Sekachev --- CHANGELOG.md | 3 + cvat/apps/documentation/data_on_fly.md | 35 ++++++ .../static/documentation/images/image128.jpg | Bin 43218 -> 0 bytes .../images/image128_use_cache.jpg | Bin 0 -> 38770 bytes cvat/apps/documentation/user_guide.md | 9 +- cvat/apps/engine/prepare.py | 110 +++++++++++++++--- cvat/apps/engine/task.py | 75 ++++++++---- cvat/apps/engine/tests/_test_rest_api.py | 28 +++++ cvat/settings/base.py | 4 +- utils/prepare_meta_information/README.md | 29 +++++ utils/prepare_meta_information/prepare.py | 37 ++++++ 11 files changed, 292 insertions(+), 38 deletions(-) create mode 100644 cvat/apps/documentation/data_on_fly.md delete mode 100644 cvat/apps/documentation/static/documentation/images/image128.jpg create mode 100644 cvat/apps/documentation/static/documentation/images/image128_use_cache.jpg create mode 100644 utils/prepare_meta_information/README.md create mode 100644 utils/prepare_meta_information/prepare.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 0700f075..87dc74e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 It supports regular navigation, searching a frame according to annotations filters and searching the nearest frame without any annotations () - MacOS users notes in CONTRIBUTING.md +- Ability to prepare meta information manually () +- Ability to upload prepared meta information along with a video when creating a task () - Optional chaining plugin for cvat-canvas and cvat-ui () ### Changed @@ -46,6 +48,7 @@ filters and searching the nearest frame without any annotations () - Fixed use case when UI throws exception: Cannot read property 'objectType' of undefined #2053 () - Fixed use case when logs could be saved twice or more times #2202 () +- Fixed issues from #2112 () ### Security - diff --git a/cvat/apps/documentation/data_on_fly.md b/cvat/apps/documentation/data_on_fly.md new file mode 100644 index 00000000..87c99264 --- /dev/null +++ b/cvat/apps/documentation/data_on_fly.md @@ -0,0 +1,35 @@ +# Data preparation on the fly + +## Description +Data on the fly processing is a way of working with data, the main idea of which is as follows: +Minimum necessary meta information is collected, when task is created. +This meta information allows in the future to create a necessary chunks when receiving a request from a client. + +Generated chunks are stored in a cache of limited size with a policy of evicting less popular items. + +When a request received from a client, the required chunk is searched for in the cache. +If the chunk does not exist yet, it is created using a prepared meta information and then put into the cache. + +This method of working with data allows: +- reduce the task creation time. +- store data in a cache of limited size with a policy of evicting less popular items. + +## Prepare meta information +Different meta information is collected for different types of uploaded data. +### Video +For video, this is a valid mapping of key frame numbers and their timestamps. This information is saved to `meta_info.txt`. + +Unfortunately, this method will not work for all videos with valid meta information. +If there are not enough keyframes in the video for smooth video decoding, the task will be created in the old way. + +#### Uploading meta information along with data + +When creating a task, you can upload a file with meta information along with the video, +which will further reduce the time for creating a task. +You can see how to prepare meta information [here](/utils/prepare_meta_information/README.md). + +It is worth noting that the generated file also contains information about the number of frames in the video at the end. + +### Images +Mapping of chunk number and paths to images that should enter the chunk +is saved at the time of creating a task in a files `dummy_{chunk_number}.txt` diff --git a/cvat/apps/documentation/static/documentation/images/image128.jpg b/cvat/apps/documentation/static/documentation/images/image128.jpg deleted file mode 100644 index e1e196d5bc508718f3abf79263412a1fe26633ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43218 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 0 or unique_entries > 1: unique_types = ', '.join([k for k, v in MEDIA_TYPES.items() if v['unique']]) multiply_types = ', '.join([k for k, v in MEDIA_TYPES.items() if not v['unique']]) @@ -219,8 +224,12 @@ def _create_thread(tid, data): if data['remote_files']: data['remote_files'] = _download_data(data['remote_files'], upload_dir) - media = _count_files(data) - media, task_mode = _validate_data(media) + meta_info_file = [] + media = _count_files(data, meta_info_file) + media, task_mode = _validate_data(media, meta_info_file) + if meta_info_file: + assert settings.USE_CACHE and db_data.storage_method == StorageMethodChoice.CACHE, \ + "File with meta information can be uploaded if 'Use cache' option is also selected" if data['server_files']: _copy_data_from_share(data['server_files'], upload_dir) @@ -290,25 +299,51 @@ def _create_thread(tid, data): if task_mode == MEDIA_TYPES['video']['mode']: try: - analyzer = AnalyzeVideo(source_path=os.path.join(upload_dir, media_files[0])) - analyzer.check_type_first_frame() - analyzer.check_video_timestamps_sequences() - - meta_info = PrepareInfo(source_path=os.path.join(upload_dir, media_files[0]), - meta_path=os.path.join(upload_dir, 'meta_info.txt')) - meta_info.save_key_frames() - meta_info.check_seek_key_frames() - meta_info.save_meta_info() + if meta_info_file: + try: + from cvat.apps.engine.prepare import UploadedMeta + if os.path.split(meta_info_file[0])[0]: + os.replace( + os.path.join(upload_dir, meta_info_file[0]), + db_data.get_meta_path() + ) + meta_info = UploadedMeta(source_path=os.path.join(upload_dir, media_files[0]), + meta_path=db_data.get_meta_path()) + meta_info.check_seek_key_frames() + meta_info.check_frames_numbers() + meta_info.save_meta_info() + assert len(meta_info.key_frames) > 0, 'No key frames.' + except Exception as ex: + base_msg = str(ex) if isinstance(ex, AssertionError) else \ + 'Invalid meta information was upload.' + job.meta['status'] = '{} Start prepare valid meta information.'.format(base_msg) + job.save_meta() + meta_info, smooth_decoding = prepare_meta( + media_file=media_files[0], + upload_dir=upload_dir, + chunk_size=db_data.chunk_size + ) + assert smooth_decoding == True, 'Too few keyframes for smooth video decoding.' + else: + meta_info, smooth_decoding = prepare_meta( + media_file=media_files[0], + upload_dir=upload_dir, + chunk_size=db_data.chunk_size + ) + assert smooth_decoding == True, 'Too few keyframes for smooth video decoding.' all_frames = meta_info.get_task_size() + video_size = meta_info.frame_sizes + db_data.size = len(range(db_data.start_frame, min(data['stop_frame'] + 1 if data['stop_frame'] else all_frames, all_frames), db_data.get_frame_step())) video_path = os.path.join(upload_dir, media_files[0]) - frame = meta_info.key_frames.get(next(iter(meta_info.key_frames))) - video_size = (frame.width, frame.height) - - except Exception: + except Exception as ex: db_data.storage_method = StorageMethodChoice.FILE_SYSTEM - + if os.path.exists(db_data.get_meta_path()): + os.remove(db_data.get_meta_path()) + base_msg = str(ex) if isinstance(ex, AssertionError) else "Uploaded video does not support a quick way of task creating." + job.meta['status'] = "{} The task will be created using the old method".format(base_msg) + job.save_meta() else:#images,archive db_data.size = len(extractor) diff --git a/cvat/apps/engine/tests/_test_rest_api.py b/cvat/apps/engine/tests/_test_rest_api.py index 1cfdd42c..8518c974 100644 --- a/cvat/apps/engine/tests/_test_rest_api.py +++ b/cvat/apps/engine/tests/_test_rest_api.py @@ -81,6 +81,7 @@ from rest_framework.test import APIClient, APITestCase from cvat.apps.engine.models import (AttributeType, Data, Job, Project, Segment, StatusChoice, Task, StorageMethodChoice) +from cvat.apps.engine.prepare import prepare_meta, prepare_meta_for_upload _setUpModule() @@ -1644,6 +1645,8 @@ class TaskDataAPITestCase(APITestCase): path = os.path.join(settings.SHARE_ROOT, "videos", "test_video_1.mp4") os.remove(path) + path = os.path.join(settings.SHARE_ROOT, "videos", "meta_info.txt") + os.remove(path) def _run_api_v1_tasks_id_data_post(self, tid, user, data): with ForceLogin(user, self.client): @@ -2057,6 +2060,31 @@ class TaskDataAPITestCase(APITestCase): self._test_api_v1_tasks_id_data_spec(user, task_spec, task_data, self.ChunkType.IMAGESET, self.ChunkType.IMAGESET, image_sizes) + prepare_meta_for_upload( + prepare_meta, + os.path.join(settings.SHARE_ROOT, "videos", "test_video_1.mp4"), + os.path.join(settings.SHARE_ROOT, "videos") + ) + task_spec = { + "name": "my video with meta info task #11", + "overlap": 0, + "segment_size": 0, + "labels": [ + {"name": "car"}, + {"name": "person"}, + ] + } + task_data = { + "server_files[0]": os.path.join("videos", "test_video_1.mp4"), + "server_files[1]": os.path.join("videos", "meta_info.txt"), + "image_quality": 70, + "use_cache": True + } + image_sizes = self._image_sizes[task_data['server_files[0]']] + + self._test_api_v1_tasks_id_data_spec(user, task_spec, task_data, self.ChunkType.VIDEO, + self.ChunkType.VIDEO, image_sizes, StorageMethodChoice.CACHE) + def test_api_v1_tasks_id_data_admin(self): self._test_api_v1_tasks_id_data(self.admin) diff --git a/cvat/settings/base.py b/cvat/settings/base.py index 1e3fe437..7df15709 100644 --- a/cvat/settings/base.py +++ b/cvat/settings/base.py @@ -427,14 +427,14 @@ RESTRICTIONS = { ), } +# http://www.grantjenks.com/docs/diskcache/tutorial.html#djangocache CACHES = { 'default' : { 'BACKEND' : 'diskcache.DjangoCache', 'LOCATION' : CACHE_ROOT, 'TIMEOUT' : None, 'OPTIONS' : { - #'statistics' :True, - 'size_limit' : 2 ** 40, # 1 тб + 'size_limit' : 2 ** 40, # 1 Tb } } } diff --git a/utils/prepare_meta_information/README.md b/utils/prepare_meta_information/README.md new file mode 100644 index 00000000..92d58774 --- /dev/null +++ b/utils/prepare_meta_information/README.md @@ -0,0 +1,29 @@ +# Simple command line for prepare meta information for video data + +**Usage** +```bash +usage: prepare.py [-h] [-chunk_size CHUNK_SIZE] video_file meta_directory + +positional arguments: + video_file Path to video file + meta_directory Directory where the file with meta information will be saved + +optional arguments: + -h, --help show this help message and exit + -chunk_size CHUNK_SIZE + Chunk size that will be specified when creating the task with specified video and generated meta information +``` + +**NOTE**: For smooth video decoding, the `chunk size` must be greater than or equal to the ratio of number of frames +to a number of key frames. +You can understand the approximate `chunk size` by preparing and looking at the file with meta information. + +**NOTE**: If ratio of number of frames to number of key frames is small compared to the `chunk size`, +then when creating a task with prepared meta information, you should expect that the waiting time for some chunks +will be longer than the waiting time for other chunks. (At the first iteration, when there is no chunk in the cache) + +**Examples** + +```bash +python prepare.py ~/Documents/some_video.mp4 ~/Documents +``` diff --git a/utils/prepare_meta_information/prepare.py b/utils/prepare_meta_information/prepare.py new file mode 100644 index 00000000..0cd200a0 --- /dev/null +++ b/utils/prepare_meta_information/prepare.py @@ -0,0 +1,37 @@ +# Copyright (C) 2020 Intel Corporation +# +# SPDX-License-Identifier: MIT +import argparse +import sys +import os + +def get_args(): + parser = argparse.ArgumentParser() + parser.add_argument('video_file', + type=str, + help='Path to video file') + parser.add_argument('meta_directory', + type=str, + help='Directory where the file with meta information will be saved') + parser.add_argument('-chunk_size', + type=int, + help='Chunk size that will be specified when creating the task with specified video and generated meta information') + + return parser.parse_args() + +def main(): + args = get_args() + try: + smooth_decoding = prepare_meta_for_upload(prepare_meta, args.video_file, None, args.meta_directory, args.chunk_size) + print('Meta information for video has been prepared') + + if smooth_decoding != None and not smooth_decoding: + print('NOTE: prepared meta information contains too few key frames for smooth decoding.') + except Exception: + print('Impossible to prepare meta information') + +if __name__ == "__main__": + base_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + sys.path.append(base_dir) + from cvat.apps.engine.prepare import prepare_meta, prepare_meta_for_upload + main() \ No newline at end of file