From 7286d659bdc3ff346cb0322fcccd398801043f64 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Mon, 19 Feb 2024 16:41:40 +0200 Subject: [PATCH] Drop support of the TFRecord format (#7416) Usage statistics on app.cvat.ai show that this format is rarely used, with single-digit numbers of projects/tasks/jobs being exported or imported using this format. Moreover, TensorFlow's popularity appears to be shrinking, so I'm not expecting this format to make a comeback. Meanwhile, supporting this format has a cost that has to be borne by everyone deploying CVAT, because it requires TensorFlow to be installed and loaded. This has various ill effects: 1. Loading time is increased. In my testing, even a command as trivial as `manage.py --help` is slowed down by 3.6 seconds. This may not seem like much, but the effect is compounded, because we have multiple processes (server + workers) all loading the same codebase. Plus, the container entrypoint may execute several Django commands. 2. Memory usage is increased. TensorFlow adds ~100MB of RAM usage per process with data alone; and the libraries add more (although it's hard to estimate the impact of library code, since it can be shared between processes in RAM). 3. Docker image size is increased by ~1.5GB (when unpacked). This is more than half of the current total size! Building time is increased as well. Overall, it seems that the drawbacks of keeping support for this format outweigh the benefits, so it's time to drop it. --- README.md | 1 - .../20240131_180300_roman_remove_tfrecord.md | 4 + cvat/apps/dataset_manager/formats/registry.py | 8 - cvat/apps/dataset_manager/formats/tfrecord.py | 38 ---- .../tests/assets/annotations.json | 18 -- .../dataset_manager/tests/test_formats.py | 3 - .../tests/test_rest_api_formats.py | 14 +- cvat/apps/engine/tests/test_rest_api.py | 5 +- cvat/requirements/base.in | 1 - cvat/requirements/base.txt | 77 +------ cvat/requirements/development.txt | 2 + cvat/requirements/production.txt | 2 - .../contributing/development-environment.md | 5 - .../contributing/new-annotation-format.md | 1 - .../annotation-with-polygons/creating-mask.md | 1 - .../en/docs/manual/advanced/formats/_index.md | 1 - .../advanced/formats/format-tfrecord.md | 215 ------------------ 17 files changed, 18 insertions(+), 378 deletions(-) create mode 100644 changelog.d/20240131_180300_roman_remove_tfrecord.md delete mode 100644 cvat/apps/dataset_manager/formats/tfrecord.py delete mode 100644 site/content/en/docs/manual/advanced/formats/format-tfrecord.md diff --git a/README.md b/README.md index 5391fc2e5197..8d617c01eb9b 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,6 @@ For more information about the supported formats, see: | [YOLO](https://pjreddie.com/darknet/yolo/) | ✔️ | ✔️ | | [MS COCO Object Detection](http://cocodataset.org/#format-data) | ✔️ | ✔️ | | [MS COCO Keypoints Detection](http://cocodataset.org/#format-data) | ✔️ | ✔️ | -| [TFrecord](https://www.tensorflow.org/tutorials/load_data/tfrecord) | ✔️ | ✔️ | | [MOT](https://motchallenge.net/) | ✔️ | ✔️ | | [MOTS PNG](https://www.vision.rwth-aachen.de/page/mots) | ✔️ | ✔️ | | [LabelMe 3.0](http://labelme.csail.mit.edu/Release3.0) | ✔️ | ✔️ | diff --git a/changelog.d/20240131_180300_roman_remove_tfrecord.md b/changelog.d/20240131_180300_roman_remove_tfrecord.md new file mode 100644 index 000000000000..419b2684e8e3 --- /dev/null +++ b/changelog.d/20240131_180300_roman_remove_tfrecord.md @@ -0,0 +1,4 @@ +### Removed + +- Removed support for the TFRecord dataset format + () diff --git a/cvat/apps/dataset_manager/formats/registry.py b/cvat/apps/dataset_manager/formats/registry.py index ddd3582805f6..41a8b980ba96 100644 --- a/cvat/apps/dataset_manager/formats/registry.py +++ b/cvat/apps/dataset_manager/formats/registry.py @@ -95,13 +95,6 @@ def make_exporter(name): return EXPORT_FORMATS[name]() -# Add checking for TF availability to avoid CVAT sever instance / interpreter -# crash and provide a meaningful diagnostic message in the case of AVX -# instructions unavailability: -# https://github.com/openvinotoolkit/cvat/pull/1567 -import datumaro.util.tf_util as TF -TF.enable_tf_check = True - # pylint: disable=unused-import import cvat.apps.dataset_manager.formats.coco import cvat.apps.dataset_manager.formats.cvat @@ -111,7 +104,6 @@ def make_exporter(name): import cvat.apps.dataset_manager.formats.mot import cvat.apps.dataset_manager.formats.mots import cvat.apps.dataset_manager.formats.pascal_voc -import cvat.apps.dataset_manager.formats.tfrecord import cvat.apps.dataset_manager.formats.yolo import cvat.apps.dataset_manager.formats.imagenet import cvat.apps.dataset_manager.formats.camvid diff --git a/cvat/apps/dataset_manager/formats/tfrecord.py b/cvat/apps/dataset_manager/formats/tfrecord.py deleted file mode 100644 index 0bc3fa112165..000000000000 --- a/cvat/apps/dataset_manager/formats/tfrecord.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (C) 2019-2022 Intel Corporation -# Copyright (C) 2023-2024 CVAT.ai Corporation -# -# SPDX-License-Identifier: MIT - -from pyunpack import Archive - -from cvat.apps.dataset_manager.bindings import (GetCVATDataExtractor, - import_dm_annotations) -from cvat.apps.dataset_manager.util import make_zip_archive -from datumaro.components.project import Dataset - -from .registry import dm_env, exporter, importer - -from datumaro.util.tf_util import import_tf -try: - import_tf() - tf_available = True -except ImportError: - tf_available = False - - -@exporter(name='TFRecord', ext='ZIP', version='1.0', enabled=tf_available) -def _export(dst_file, temp_dir, instance_data, save_images=False): - with GetCVATDataExtractor(instance_data, include_images=save_images) as extractor: - dataset = Dataset.from_extractors(extractor, env=dm_env) - dataset.export(temp_dir, 'tf_detection_api', save_images=save_images) - - make_zip_archive(temp_dir, dst_file) - -@importer(name='TFRecord', ext='ZIP', version='1.0', enabled=tf_available) -def _import(src_file, temp_dir, instance_data, load_data_callback=None, **kwargs): - Archive(src_file.name).extractall(temp_dir) - - dataset = Dataset.import_from(temp_dir, 'tf_detection_api', env=dm_env) - if load_data_callback is not None: - load_data_callback(dataset, instance_data) - import_dm_annotations(dataset, instance_data) diff --git a/cvat/apps/dataset_manager/tests/assets/annotations.json b/cvat/apps/dataset_manager/tests/assets/annotations.json index 1b1d5f0cf2ae..6035e40fbd30 100644 --- a/cvat/apps/dataset_manager/tests/assets/annotations.json +++ b/cvat/apps/dataset_manager/tests/assets/annotations.json @@ -701,24 +701,6 @@ ], "tracks": [] }, - "TFRecord 1.0": { - "version": 0, - "tags": [], - "shapes": [ - { - "type": "rectangle", - "occluded": false, - "z_order": 0, - "points": [16.5, 17.2, 38.89, 25.63], - "frame": 0, - "label_id": null, - "group": 0, - "source": "manual", - "attributes": [] - } - ], - "tracks": [] - }, "YOLO 1.1": { "version": 0, "tags": [], diff --git a/cvat/apps/dataset_manager/tests/test_formats.py b/cvat/apps/dataset_manager/tests/test_formats.py index c710013d547d..1c7db60814d0 100644 --- a/cvat/apps/dataset_manager/tests/test_formats.py +++ b/cvat/apps/dataset_manager/tests/test_formats.py @@ -295,7 +295,6 @@ def test_export_formats_query(self): 'MOTS PNG 1.0', 'PASCAL VOC 1.1', 'Segmentation mask 1.1', - 'TFRecord 1.0', 'YOLO 1.1', 'ImageNet 1.0', 'CamVid 1.0', @@ -326,7 +325,6 @@ def test_import_formats_query(self): 'MOTS PNG 1.0', 'PASCAL VOC 1.1', 'Segmentation mask 1.1', - 'TFRecord 1.0', 'YOLO 1.1', 'ImageNet 1.0', 'CamVid 1.0', @@ -381,7 +379,6 @@ def test_empty_images_are_exported(self): # ('MOTS PNG 1.0', 'mots_png'), # does not support ('PASCAL VOC 1.1', 'voc'), ('Segmentation mask 1.1', 'voc'), - ('TFRecord 1.0', 'tf_detection_api'), ('YOLO 1.1', 'yolo'), ('ImageNet 1.0', 'imagenet_txt'), ('CamVid 1.0', 'camvid'), diff --git a/cvat/apps/dataset_manager/tests/test_rest_api_formats.py b/cvat/apps/dataset_manager/tests/test_rest_api_formats.py index 0c00ec178935..7c30344d2bab 100644 --- a/cvat/apps/dataset_manager/tests/test_rest_api_formats.py +++ b/cvat/apps/dataset_manager/tests/test_rest_api_formats.py @@ -417,7 +417,7 @@ def test_api_v2_dump_and_upload_annotations_with_objects_type_is_shape(self): "Cityscapes 1.0", "Datumaro 1.0", "ImageNet 1.0", "MOTS PNG 1.0", "PASCAL VOC 1.1", "Segmentation mask 1.1", - "TFRecord 1.0", "VGGFace2 1.0", + "VGGFace2 1.0", "WiderFace 1.0", "YOLO 1.1" ]: self._create_annotations(task, dump_format_name, "default") @@ -522,7 +522,7 @@ def test_api_v2_dump_annotations_with_objects_type_is_track(self): if dump_format_name in [ "Cityscapes 1.0", "ImageNet 1.0", "MOTS PNG 1.0", "PASCAL VOC 1.1", - "Segmentation mask 1.1", "TFRecord 1.0", + "Segmentation mask 1.1", "VGGFace2 1.0", "WiderFace 1.0", "YOLO 1.1" ]: self._create_annotations(task, dump_format_name, "default") @@ -968,7 +968,7 @@ def test_api_v2_rewriting_annotations(self): if dump_format_name in [ "MOT 1.1", "PASCAL VOC 1.1", "Segmentation mask 1.1", - "TFRecord 1.0", "YOLO 1.1", "ImageNet 1.0", + "YOLO 1.1", "ImageNet 1.0", "WiderFace 1.0", "VGGFace2 1.0", "Datumaro 1.0", "Open Images V6 1.0", "KITTI 1.0" ]: @@ -1084,7 +1084,7 @@ def test_api_v2_tasks_annotations_dump_and_upload_with_datumaro(self): if dump_format_name in [ "MOT 1.1", "MOTS PNG 1.0", "PASCAL VOC 1.1", "Segmentation mask 1.1", - "TFRecord 1.0", "YOLO 1.1", "ImageNet 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", "KITTI 1.0" ]: @@ -1287,7 +1287,7 @@ def test_api_v2_export_import_dataset(self): dump_format_name = dump_format.DISPLAY_NAME if dump_format_name in [ 'Cityscapes 1.0', 'LFW 1.0', 'Market-1501 1.0', - 'MOT 1.1', 'TFRecord 1.0' + 'MOT 1.1', ]: # TO-DO: fix bug for this formats continue @@ -1303,7 +1303,7 @@ def test_api_v2_export_import_dataset(self): 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", "TFRecord 1.0", "VGGFace2 1.0", + "Segmentation mask 1.1", "VGGFace2 1.0", "WiderFace 1.0", "YOLO 1.1" ]: self._create_annotations(task, dump_format_name, "default") @@ -1344,7 +1344,7 @@ def test_api_v2_export_import_dataset(self): upload_format_name = upload_format.DISPLAY_NAME if upload_format_name in [ 'Cityscapes 1.0', 'LFW 1.0', 'Market-1501 1.0', - 'MOT 1.1', 'TFRecord 1.0' + 'MOT 1.1', ]: # TO-DO: fix bug for this formats continue diff --git a/cvat/apps/engine/tests/test_rest_api.py b/cvat/apps/engine/tests/test_rest_api.py index 60c2a3fdb4b3..a809450992b0 100644 --- a/cvat/apps/engine/tests/test_rest_api.py +++ b/cvat/apps/engine/tests/test_rest_api.py @@ -6031,8 +6031,7 @@ def _get_initial_annotation(annotation_format): annotations["shapes"] = rectangle_shapes_wo_attrs annotations["tags"] = tags_wo_attrs - elif annotation_format == "YOLO 1.1" or \ - annotation_format == "TFRecord 1.0": + elif annotation_format == "YOLO 1.1": annotations["shapes"] = rectangle_shapes_wo_attrs elif annotation_format == "COCO 1.0": @@ -6404,8 +6403,6 @@ def etree_to_dict(t): for json in jsons: coco = coco_loader.COCO(json) self.assertTrue(coco.getAnnIds()) - elif format_name == "TFRecord 1.0": - self.assertTrue(zipfile.is_zipfile(content)) elif format_name == "Segmentation mask 1.1": self.assertTrue(zipfile.is_zipfile(content)) diff --git a/cvat/requirements/base.in b/cvat/requirements/base.in index 5b685b2842a1..e9b37657ed7e 100644 --- a/cvat/requirements/base.in +++ b/cvat/requirements/base.in @@ -51,4 +51,3 @@ rq-scheduler==0.13.1 rq==1.15.1 rules>=3.3 Shapely==1.7.1 -tensorflow==2.11.1 # Optional requirement of Datumaro. Use tensorflow-macos==2.8.0 for Mac M1 diff --git a/cvat/requirements/base.txt b/cvat/requirements/base.txt index e0f6e9e27c23..c8bf63e672a6 100644 --- a/cvat/requirements/base.txt +++ b/cvat/requirements/base.txt @@ -1,4 +1,4 @@ -# SHA1:07743309d7b390659b762ca30db20ebc07ac81bc +# SHA1:55af6f61daa4ceab3e9aa358d3109c7af9660c0a # # This file is autogenerated by pip-compile-multi # To update, run: @@ -6,14 +6,8 @@ # pip-compile-multi # -r ../../utils/dataset_manifest/requirements.txt -absl-py==2.0.0 - # via - # tensorboard - # tensorflow asgiref==3.7.2 # via django -astunparse==1.6.3 - # via tensorflow async-timeout==4.0.3 # via redis attrs==21.4.0 @@ -122,16 +116,12 @@ easyprocess==1.1 # via pyunpack entrypoint2==1.1 # via pyunpack -flatbuffers==23.5.26 - # via tensorflow fonttools==4.43.1 # via matplotlib freezegun==1.2.2 # via rq-scheduler furl==2.1.0 # via -r cvat/requirements/base.in -gast==0.4.0 - # via tensorflow google-api-core==2.12.0 # via # google-cloud-core @@ -139,32 +129,20 @@ google-api-core==2.12.0 google-auth==2.23.3 # via # google-api-core - # google-auth-oauthlib # google-cloud-core # google-cloud-storage - # tensorboard -google-auth-oauthlib==0.4.6 - # via tensorboard google-cloud-core==2.3.3 # via google-cloud-storage google-cloud-storage==1.42.0 # via -r cvat/requirements/base.in google-crc32c==1.5.0 # via google-resumable-media -google-pasta==0.2.0 - # via tensorflow google-resumable-media==2.6.0 # via google-cloud-storage googleapis-common-protos==1.60.0 # via google-api-core -grpcio==1.59.0 - # via - # tensorboard - # tensorflow h5py==3.10.0 - # via - # datumaro - # tensorflow + # via datumaro idna==3.4 # via requests importlib-metadata==6.8.0 @@ -185,24 +163,16 @@ jmespath==0.10.0 # botocore jsonschema==4.17.3 # via drf-spectacular -keras==2.11.0 - # via tensorflow kiwisolver==1.4.5 # via matplotlib -libclang==16.0.6 - # via tensorflow limits==3.6.0 # via python-logstash-async lxml==4.9.3 # via datumaro lz4==4.3.2 # via clickhouse-connect -markdown==3.5 - # via tensorboard markupsafe==2.1.3 - # via - # jinja2 - # werkzeug + # via jinja2 matplotlib==3.8.0 # via # datumaro @@ -215,8 +185,6 @@ nibabel==5.1.0 # via datumaro oauthlib==3.2.2 # via requests-oauthlib -opt-einsum==3.3.0 - # via tensorflow orderedmultidict==1.0.1 # via furl orjson==3.9.8 @@ -227,7 +195,6 @@ packaging==23.2 # matplotlib # nibabel # tensorboardx - # tensorflow pandas==2.1.1 # via datumaro patool==1.12 @@ -238,9 +205,7 @@ protobuf==3.19.6 # via # google-api-core # googleapis-common-protos - # tensorboard # tensorboardx - # tensorflow psutil==5.9.4 # via -r cvat/requirements/base.in psycopg2-binary==2.9.5 @@ -311,11 +276,9 @@ requests==2.31.0 # msrest # python-logstash-async # requests-oauthlib - # tensorboard requests-oauthlib==1.3.1 # via # django-allauth - # google-auth-oauthlib # msrest rjsmin==1.2.1 # via django-compressor @@ -342,39 +305,21 @@ shapely==1.7.1 # via -r cvat/requirements/base.in six==1.16.0 # via - # astunparse # azure-core # furl - # google-pasta # isodate # orderedmultidict # python-dateutil - # tensorflow sqlparse==0.4.4 # via django -tensorboard==2.11.2 - # via tensorflow -tensorboard-data-server==0.6.1 - # via tensorboard -tensorboard-plugin-wit==1.8.1 - # via tensorboard tensorboardx==2.6 # via datumaro -tensorflow==2.11.1 - # via -r cvat/requirements/base.in -tensorflow-estimator==2.11.0 - # via tensorflow -tensorflow-io-gcs-filesystem==0.34.0 - # via tensorflow -termcolor==2.3.0 - # via tensorflow typing-extensions==4.8.0 # via # asgiref # azure-core # datumaro # limits - # tensorflow tzdata==2023.3 # via pandas uritemplate==4.1.1 @@ -386,23 +331,9 @@ urllib3==1.26.18 # botocore # clickhouse-connect # requests -werkzeug==3.0.0 - # via tensorboard -wheel==0.41.2 - # via - # astunparse - # tensorboard wrapt==1.15.0 - # via - # deprecated - # tensorflow + # via deprecated zipp==3.17.0 # via importlib-metadata zstandard==0.21.0 # via clickhouse-connect - -# The following packages are considered to be unsafe in a requirements file: -setuptools==68.2.2 - # via - # tensorboard - # tensorflow diff --git a/cvat/requirements/development.txt b/cvat/requirements/development.txt index 44f7c896a059..995112dbc937 100644 --- a/cvat/requirements/development.txt +++ b/cvat/requirements/development.txt @@ -62,3 +62,5 @@ tornado==6.3.3 # via snakeviz # The following packages are considered to be unsafe in a requirements file: +setuptools==68.2.2 + # via astroid diff --git a/cvat/requirements/production.txt b/cvat/requirements/production.txt index 7844036189b7..a919444f96cf 100644 --- a/cvat/requirements/production.txt +++ b/cvat/requirements/production.txt @@ -28,5 +28,3 @@ watchfiles==0.20.0 # via uvicorn websockets==11.0.3 # via uvicorn - -# The following packages are considered to be unsafe in a requirements file: diff --git a/site/content/en/docs/contributing/development-environment.md b/site/content/en/docs/contributing/development-environment.md index 42bbcda4a41d..917e1566eca0 100644 --- a/site/content/en/docs/contributing/development-environment.md +++ b/site/content/en/docs/contributing/development-environment.md @@ -138,11 +138,6 @@ description: 'Installing a development environment for different operating syste > ``` > sudo ln -s /opt/homebrew/lib/libgeos_c.dylib /usr/local/lib > ``` - > - > On Mac with Apple Silicon (M1) in order to install TensorFlow you will have - > to edit `cvat/requirements/base.txt`. - > Change `tensorflow` to `tensorflow-macos` - > May need to downgrade version Python to 3.9.\* or upgrade version `tensorflow-macos` > Note for Arch Linux users: > diff --git a/site/content/en/docs/contributing/new-annotation-format.md b/site/content/en/docs/contributing/new-annotation-format.md index 95118ce522e0..4ced1e15af1e 100644 --- a/site/content/en/docs/contributing/new-annotation-format.md +++ b/site/content/en/docs/contributing/new-annotation-format.md @@ -150,7 +150,6 @@ task_data.add_shape(shape) - [COCO](/docs/manual/advanced/formats/format-coco/) - [PASCAL VOC and mask](/docs/manual/advanced/formats/format-voc/) - [YOLO](/docs/manual/advanced/formats/format-yolo/) -- [TF detection API](/docs/manual/advanced/formats/format-tfrecord/) - [ImageNet](/docs/manual/advanced/formats/format-imagenet/) - [CamVid](/docs/manual/advanced/formats/format-camvid/) - [WIDER Face](/docs/manual/advanced/formats/format-widerface/) diff --git a/site/content/en/docs/manual/advanced/annotation-with-polygons/creating-mask.md b/site/content/en/docs/manual/advanced/annotation-with-polygons/creating-mask.md index 0da2b294b7fe..7ec1a13d0586 100644 --- a/site/content/en/docs/manual/advanced/annotation-with-polygons/creating-mask.md +++ b/site/content/en/docs/manual/advanced/annotation-with-polygons/creating-mask.md @@ -33,7 +33,6 @@ There are several formats in CVAT that can be used to export masks: - `MOTS` - `ICDAR` - `COCO` (RLE-encoded instance masks, [guide](/docs/manual/advanced/formats/format-coco)) -- `TFRecord` ([over Datumaro](https://github.com/cvat-ai/datumaro/blob/develop/docs/user_manual.md), [guide](/docs/manual/advanced/formats/format-tfrecord)): - `Datumaro` An example of exported masks (in the `Segmentation Mask` format): diff --git a/site/content/en/docs/manual/advanced/formats/_index.md b/site/content/en/docs/manual/advanced/formats/_index.md index 418aefb514a9..fb5b65e6a82e 100644 --- a/site/content/en/docs/manual/advanced/formats/_index.md +++ b/site/content/en/docs/manual/advanced/formats/_index.md @@ -43,7 +43,6 @@ The table below outlines the available formats for data export in CVAT. | [Open Images 1.0](format-openimages) | .csv | Detection,
Classification,
Semantic Segmentaion | Faster R-CNN, YOLO, U-Net,
CornerNet, and others. | Bounding Boxes, Tags, Polygons | Specific attributes | Not supported | | [PASCAL VOC 1.0](format-voc) | .xml | Classification, Detection | Faster R-CNN, SSD, YOLO,
AlexNet, and others. | Bounding Boxes, Tags, Polygons | Specific attributes | Not supported | | [Segmentation Mask 1.0](format-smask) | .txt | Semantic Segmentation | Faster R-CNN, SSD, YOLO,
AlexNet, and others. | Polygons | No attributes | Not supported | -| [TFRecord 1.0](format-tfrecord) | .pbtxt | Detection
Classification | SSD, Faster R-CNN, YOLO,
GG16, ResNet, Inception, MobileNet,
and others. | Bounding Boxes, Polygons | No attributes | Not supported | | [VGGFace2 1.0](format-vggface2) | .csv | Face recognition | VGGFace, ResNet, Inception,
and others. | Bounding Boxes, Points | No attributes | Not supported | | [WIDER Face 1.0](format-widerface) | .txt | Detection | SSD (Single Shot MultiBox Detector), Faster R-CNN, YOLO,
and others. | Bounding Boxes, Tags | Specific attributes | Not supported | | [YOLO 1.0](format-yolo) | .txt | Detection | YOLOv1, YOLOv2 (YOLO9000),
YOLOv3, YOLOv4, and others. | Bounding Boxes | No attributes | Not supported | diff --git a/site/content/en/docs/manual/advanced/formats/format-tfrecord.md b/site/content/en/docs/manual/advanced/formats/format-tfrecord.md deleted file mode 100644 index 8dcc96f92b24..000000000000 --- a/site/content/en/docs/manual/advanced/formats/format-tfrecord.md +++ /dev/null @@ -1,215 +0,0 @@ ---- -title: 'TFRecord' -linkTitle: 'TFRecord' -weight: 8 -description: 'How to export and import data in TFRecord format' ---- - -The TFRecord format is tightly integrated with TensorFlow -and is commonly used for training models within the TensorFlow ecosystem. - -TFRecord is an incredibly flexible data format. -We strive to align our implementation with the -format employed by the [TensorFlow Object Detection API](https://github.com/tensorflow/models/tree/master/research/object_detection), -making only minimal changes as necessary. - -For more information, see: - -- [TFRecord](https://www.tensorflow.org/tutorials/load_data/tfrecord) -- [Dataset examples](https://github.com/cvat-ai/datumaro/tree/v0.3/tests/assets/tf_detection_api_dataset) - -This format does not have a fixed structure, so in -CVAT the following structure is used: - -```python -image_feature_description = { - 'image/filename': tf.io.FixedLenFeature([], tf.string), - 'image/source_id': tf.io.FixedLenFeature([], tf.string), - 'image/height': tf.io.FixedLenFeature([], tf.int64), - 'image/width': tf.io.FixedLenFeature([], tf.int64), - # Object boxes and classes. - 'image/object/bbox/xmin': tf.io.VarLenFeature(tf.float32), - 'image/object/bbox/xmax': tf.io.VarLenFeature(tf.float32), - 'image/object/bbox/ymin': tf.io.VarLenFeature(tf.float32), - 'image/object/bbox/ymax': tf.io.VarLenFeature(tf.float32), - 'image/object/class/label': tf.io.VarLenFeature(tf.int64), - 'image/object/class/text': tf.io.VarLenFeature(tf.string), -} -``` - -## TFRecord export - -For export of images: - -- Supported annotations: Bounding Boxes, Polygons - (as masks, manually over [Datumaro](https://github.com/cvat-ai/datumaro/blob/develop/docs/user_manual.md)) -- Attributes: Not supported. -- Tracks: Not supported. - -The downloaded file is a .zip archive with the following structure: - -```bash -taskname.zip/ -├── default.tfrecord -└── label_map.pbtxt - -# label_map.pbtxt -item { - id: 1 - name: 'label_0' -} -item { - id: 2 - name: 'label_1' -} -... -``` - -How to export masks: - -1. Export annotations in [Datumaro](/docs/manual/advanced/formats/format-datumaro/) format. -1. Apply `polygons_to_masks` and `boxes_to_masks` transforms: - - ```bash - datum transform -t polygons_to_masks -p path/to/proj -o ptm - datum transform -t boxes_to_masks -p ptm -o btm - ``` - -1. Export in the `TF Detection API` format: - - ```bash - datum export -f tf_detection_api -p btm [-- --save-images] - ``` - -## TFRecord import - -Uploaded file: a zip archive of following structure: - -```bash -taskname.zip/ -└── .tfrecord -``` - -- supported annotations: Rectangles - -## How to create a task from TFRecord dataset (from VOC2007 for example) - -1. Create `label_map.pbtxt` file with the following content: - -```js -item { - id: 1 - name: 'aeroplane' -} -item { - id: 2 - name: 'bicycle' -} -item { - id: 3 - name: 'bird' -} -item { - id: 4 - name: 'boat' -} -item { - id: 5 - name: 'bottle' -} -item { - id: 6 - name: 'bus' -} -item { - id: 7 - name: 'car' -} -item { - id: 8 - name: 'cat' -} -item { - id: 9 - name: 'chair' -} -item { - id: 10 - name: 'cow' -} -item { - id: 11 - name: 'diningtable' -} -item { - id: 12 - name: 'dog' -} -item { - id: 13 - name: 'horse' -} -item { - id: 14 - name: 'motorbike' -} -item { - id: 15 - name: 'person' -} -item { - id: 16 - name: 'pottedplant' -} -item { - id: 17 - name: 'sheep' -} -item { - id: 18 - name: 'sofa' -} -item { - id: 19 - name: 'train' -} -item { - id: 20 - name: 'tvmonitor' -} -``` - -1. Use [create_pascal_tf_record.py](https://github.com/tensorflow/models/blob/master/research/object_detection/dataset_tools/create_pascal_tf_record.py) - -to convert VOC2007 dataset to TFRecord format. -As example: - -```bash -python create_pascal_tf_record.py --data_dir --set train --year VOC2007 --output_path pascal.tfrecord --label_map_path label_map.pbtxt -``` - -1. Zip train images - - ```bash - cat /VOC2007/ImageSets/Main/train.txt | while read p; do echo /VOC2007/JPEGImages/${p}.jpg ; done | zip images.zip -j -@ - ``` - -1. Create a CVAT task with the following labels: - - ```bash - aeroplane bicycle bird boat bottle bus car cat chair cow diningtable dog horse motorbike person pottedplant sheep sofa train tvmonitor - ``` - - Select images. zip as data. - See [Creating an annotation task](/docs/manual/basics/creating_an_annotation_task/) - guide for details. - -1. Zip `pascal.tfrecord` and `label_map.pbtxt` files together - - ```bash - zip anno.zip -j - ``` - -1. Click `Upload annotation` button, choose `TFRecord 1.0` and select the zip file - - with labels from the previous step. It may take some time.