Skip to content

Loading Datasets From Disk

FiftyOne provides native support for importing datasets from disk in a variety of common formats, and it can be easily extended to import datasets in custom formats.

Note

Did you know? You can import media and/or labels from within the FiftyOne App by installing the @voxel51/io plugin!

Note

If your data is in a custom format, writing a simple loop is the easiest way to load your data into FiftyOne.

Basic recipe

The interface for creating a FiftyOne Dataset for your data on disk is conveniently exposed via the Python library and the CLI. The basic recipe is that you simply specify the path(s) to the data on disk and the type of dataset that you’re loading.

Supported formats

Each supported dataset type is represented by a subclass of fiftyone.types.Dataset, which is used by the Python library and CLI to refer to the corresponding dataset format when reading the dataset from disk.

Dataset Type Description
ImageDirectory A directory of images.
VideoDirectory A directory of videos.
MediaDirectory A directory of media files.
FiftyOneImageClassificationDataset A labeled dataset consisting of images and their associated classification labels
in a simple JSON format.
ImageClassificationDirectoryTree A directory tree whose subfolders define an image classification dataset.
VideoClassificationDirectoryTree A directory tree whose subfolders define a video classification dataset.
TFImageClassificationDataset A labeled dataset consisting of images and their associated classification labels
stored as TFRecords.
FiftyOneImageDetectionDataset A labeled dataset consisting of images and their associated object detections
stored in a simple JSON format.
FiftyOneTemporalDetectionDataset A labeled dataset consisting of videos and their associated temporal detections in
a simple JSON format.
COCODetectionDataset A labeled dataset consisting of images and their associated object detections
saved in COCO Object Detection Format.
VOCDetectionDataset A labeled dataset consisting of images and their associated object detections
saved in VOC format.
KITTIDetectionDataset A labeled dataset consisting of images and their associated object detections
saved in KITTI format.
YOLOv4Dataset A labeled dataset consisting of images and their associated object detections
saved in YOLOv4 format.
YOLOv5Dataset A labeled dataset consisting of images and their associated object detections
saved in YOLOv5 format.
TFObjectDetectionDataset A labeled dataset consisting of images and their associated object detections
stored as TFRecords in TF Object Detection API format.
ImageSegmentationDirectory A labeled dataset consisting of images and their associated semantic segmentations
stored as images on disk.
CVATImageDataset A labeled dataset consisting of images and their associated multitask labels
stored in CVAT image format.
CVATVideoDataset A labeled dataset consisting of videos and their associated multitask labels
stored in CVAT video format.
OpenLABELImageDataset A labeled dataset consisting of images and their associated multitask labels
stored in OpenLABEL format.
OpenLABELVideoDataset A labeled dataset consisting of videos and their associated multitask labels
stored in OpenLABEL format.
FiftyOneImageLabelsDataset A labeled dataset consisting of images and their associated multitask predictions
stored in ETA ImageLabels format.
BDDDataset A labeled dataset consisting of images and their associated multitask predictions
saved in Berkeley DeepDrive (BDD) format.
CSVDataset A labeled dataset consisting of images or videos and their associated field values
stored as columns of a CSV file.
DICOMDataset An image dataset whose image data and optional properties are stored in
DICOM format.
GeoJSONDataset An image or video dataset whose location data and labels are stored in
GeoJSON format.
GeoTIFFDataset An image dataset whose image and geolocation data are stored in
GeoTIFF format.
FiftyOneVideoLabelsDataset A labeled dataset consisting of videos and their associated multitask predictions
stored in ETA VideoLabels format.
FiftyOneDataset A dataset consisting of an entire serialized Dataset and its associated source
media.
Custom formats Import datasets in custom formats by defining your own Dataset or
DatasetImporter class.

ImageDirectory

The fiftyone.types.ImageDirectory type represents a directory of images.

Datasets of this type are read in the following format:

<dataset_dir>/
    <filename1>.<ext>
    <filename2>.<ext>

where files with non-image MIME types are omitted.

By default, the dataset may contain nested subfolders of images, which are recursively listed.

Note

See ImageDirectoryImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from a directory of images as follows:

VideoDirectory

The fiftyone.types.VideoDirectory type represents a directory of videos.

Datasets of this type are read in the following format:

<dataset_dir>/
    <filename1>.<ext>
    <filename2>.<ext>

where files with non-video MIME types are omitted.

By default, the dataset may contain nested subfolders of videos, which are recursively listed.

Note

See VideoDirectoryImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from a directory of videos as follows:

MediaDirectory

The fiftyone.types.MediaDirectory type represents a directory of media files.

Datasets of this type are read in the following format:

<dataset_dir>/
    <filename1>.<ext>
    <filename2>.<ext>

Note

All files must have the same media type (image, video, point cloud, etc.)

By default, the dataset may contain nested subfolders of media files, which are recursively listed.

Note

See MediaDirectoryImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from a directory of media files as follows:

FiftyOneImageClassificationDataset

The fiftyone.types.FiftyOneImageClassificationDataset type represents a labeled dataset consisting of images and their associated classification label(s) stored in a simple JSON format.

Datasets of this type are read in the following format:

<dataset_dir>/
    data/
        <uuid1>.<ext>
        <uuid2>.<ext>
        ...
    labels.json

In the simplest case, labels.json can be a JSON file in the following format:

{
    "classes": [\
        "<labelA>",\
        "<labelB>",\
        ...\
    ],
    "labels": {
        "<uuid1>": <target>,
        "<uuid2>": <target>,
        ...
    }
}

If the classes field is provided, the target values are class IDs that are mapped to class label strings via classes[target]. If no classes field is provided, then the target values directly store the label strings.

The target value in labels for unlabeled images is None (or missing).

The UUIDs can also be relative paths like path/to/uuid, in which case the images in data/ should be arranged in nested subfolders with the corresponding names, or they can be absolute paths, in which case the images may or may not be in data/.

Alternatively, labels.json can contain predictions with associated confidences and additional attributes in the following format:

{
    "classes": [\
        "<labelA>",\
        "<labelB>",\
        ...\
    ],
    "labels": {
        "<uuid1>": {
            "label": <target>,
            "confidence": <optional-confidence>,
            "attributes": {
                <optional-name>: <optional-value>,
                ...
            }
        },
        "<uuid2>": {
            "label": <target>,
            "confidence": <optional-confidence>,
            "attributes": {
                <optional-name>: <optional-value>,
                ...
            }
        },
        ...
    }
}

You can also load multilabel classifications in this format by storing lists of targets in labels.json:

{
    "classes": [\
        "<labelA>",\
        "<labelB>",\
        ...\
    ],
    "labels": {
        "<uuid1>": [<target1>, <target2>, ...],
        "<uuid2>": [<target1>, <target2>, ...],
        ...
    }
}

where the target values in labels can be class strings, class IDs, or dicts in the format described above defining class labels, confidences, and optional attributes.

Note

See FiftyOneImageClassificationDatasetImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from an image classification dataset stored in the above format as follows:

You can also independently specify the locations of the labels and the root directory containing the corresponding media files by providing the labels_path and data_path parameters rather than dataset_dir:

Note

If the UUIDs in your labels are absolute paths to the source media, then you can omit the data_path parameter from the example above.

ImageClassificationDirectoryTree

The fiftyone.types.ImageClassificationDirectoryTree type represents a directory tree whose subfolders define an image classification dataset.

Datasets of this type are read in the following format:

<dataset_dir>/
    <classA>/
        <image1>.<ext>
        <image2>.<ext>
        ...
    <classB>/
        <image1>.<ext>
        <image2>.<ext>
        ...
    ...

Unlabeled images are stored in a subdirectory named _unlabeled.

Each class folder may contain nested subfolders of images.

Note

See ImageClassificationDirectoryTreeImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from an image classification directory tree stored in the above format as follows:

VideoClassificationDirectoryTree

The fiftyone.types.VideoClassificationDirectoryTree type represents a directory tree whose subfolders define a video classification dataset.

Datasets of this type are read in the following format:

<dataset_dir>/
    <classA>/
        <video1>.<ext>
        <video2>.<ext>
        ...
    <classB>/
        <video1>.<ext>
        <video2>.<ext>
        ...
    ...

Unlabeled videos are stored in a subdirectory named _unlabeled.

Each class folder may contain nested subfolders of videos.

Note

See VideoClassificationDirectoryTreeImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from a video classification directory tree stored in the above format as follows:

TFImageClassificationDataset

The fiftyone.types.TFImageClassificationDataset type represents a labeled dataset consisting of images and their associated classification labels stored as TFRecords.

Datasets of this type are read in the following format:

<dataset_dir>/
    tf.records-?????-of-?????

where the features of the (possibly sharded) TFRecords are stored in the following format:

{
    # Image dimensions
    "height": tf.io.FixedLenFeature([], tf.int64),
    "width": tf.io.FixedLenFeature([], tf.int64),
    "depth": tf.io.FixedLenFeature([], tf.int64),
    # Image filename
    "filename": tf.io.FixedLenFeature([], tf.int64),
    # The image extension
    "format": tf.io.FixedLenFeature([], tf.string),
    # Encoded image bytes
    "image_bytes": tf.io.FixedLenFeature([], tf.string),
    # Class label string
    "label": tf.io.FixedLenFeature([], tf.string, default_value=""),
}

For unlabeled samples, the TFRecords do not contain label features.

Note

See TFImageClassificationDatasetImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from an image classification dataset stored as a directory of TFRecords in the above format as follows:

Note

You can provide the tf_records_path argument instead of dataset_dir in the examples above to directly specify the path to the TFRecord(s) to load. See TFImageClassificationDatasetImporter for details.

FiftyOneImageDetectionDataset

The fiftyone.types.FiftyOneImageDetectionDataset type represents a labeled dataset consisting of images and their associated object detections stored in a simple JSON format.

Datasets of this type are read in the following format:

<dataset_dir>/
    data/
        <uuid1>.<ext>
        <uuid2>.<ext>
        ...
    labels.json

where labels.json is a JSON file in the following format:

{
    "classes": [\
        <labelA>,\
        <labelB>,\
        ...\
    ],
    "labels": {
        <uuid1>: [\
            {\
                "label": <target>,\
                "bounding_box": [\
                    <top-left-x>, <top-left-y>, <width>, <height>\
                ],\
                "confidence": <optional-confidence>,\
                "attributes": {\
                    <optional-name>: <optional-value>,\
                    ...\
                }\
            },\
            ...\
        ],
        <uuid2>: [\
            ...\
        ],
        ...
    }
}

and where the bounding box coordinates are expressed as relative values in [0, 1] x [0, 1].

If the classes field is provided, the target values are class IDs that are mapped to class label strings via classes[target]. If no classes field is provided, then the target values directly store the label strings.

The target value in labels for unlabeled images is None (or missing).

The UUIDs can also be relative paths like path/to/uuid, in which case the images in data/ should be arranged in nested subfolders with the corresponding names, or they can be absolute paths, in which case the images may or may not be in data/.

Note

See FiftyOneImageDetectionDatasetImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from an image detection dataset stored in the above format as follows:

You can also independently specify the locations of the labels and the root directory containing the corresponding media files by providing the labels_path and data_path parameters rather than dataset_dir:

Note

If the UUIDs in your labels are absolute paths to the source media, then you can omit the data_path parameter from the example above.

FiftyOneTemporalDetectionDataset

The fiftyone.types.FiftyOneTemporalDetectionDataset type represents a labeled dataset consisting of videos and their associated temporal detections stored in a simple JSON format.

Datasets of this type are read in the following format:

<dataset_dir>/
    data/
        <uuid1>.<ext>
        <uuid2>.<ext>
        ...
    labels.json

where labels.json is a JSON file in the following format:

{
    "classes": [\
        "<labelA>",\
        "<labelB>",\
        ...\
    ],
    "labels": {
        "<uuid1>": [\
            {\
                "label": <target>,\
                "support": [<first-frame>, <last-frame>],\
                "confidence": <optional-confidence>,\
                "attributes": {\
                    <optional-name>: <optional-value>,\
                    ...\
                }\
            },\
            {\
                "label": <target>,\
                "support": [<first-frame>, <last-frame>],\
                "confidence": <optional-confidence>,\
                "attributes": {\
                    <optional-name>: <optional-value>,\
                    ...\
                }\
            },\
            ...\
        ],
        "<uuid2>": [\
            {\
                "label": <target>,\
                "timestamps": [<start-timestamp>, <stop-timestamp>],\
                "confidence": <optional-confidence>,\
                "attributes": {\
                    <optional-name>: <optional-value>,\
                    ...\
                }\
            },\
            {\
                "label": <target>,\
                "timestamps": [<start-timestamp>, <stop-timestamp>],\
                "confidence": <optional-confidence>,\
                "attributes": {\
                    <optional-name>: <optional-value>,\
                    ...\
                }\
            },\
        ],
        ...
    }
}

The temporal range of each detection can be specified either via the support key, which should contain the [first, last] frame numbers of the detection, or the timestamps key, which should contain the [start, stop] timestamps of the detection in seconds.

If the classes field is provided, the target values are class IDs that are mapped to class label strings via classes[target]. If no classes field is provided, then the target values directly store the label strings.

Unlabeled videos can have a None (or missing) key in labels.

The UUIDs can also be relative paths like path/to/uuid, in which case the images in data/ should be arranged in nested subfolders with the corresponding names, or they can be absolute paths, in which case the images may or may not be in data/.

Note

See FiftyOneTemporalDetectionDatasetImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from a temporal detection dataset stored in the above format as follows:

You can also independently specify the locations of the labels and the root directory containing the corresponding media files by providing the labels_path and data_path parameters rather than dataset_dir:

Note

If the UUIDs in your labels are absolute paths to the source media, then you can omit the data_path parameter from the example above.

COCODetectionDataset

The fiftyone.types.COCODetectionDataset type represents a labeled dataset consisting of images and their associated object detections saved in COCO Object Detection Format.

Datasets of this type are read in the following format:

<dataset_dir>/
    data/
        <filename0>.<ext>
        <filename1>.<ext>
        ...
    labels.json

where labels.json is a JSON file in the following format:

{
    "info": {...},
    "licenses": [\
        {\
            "id": 1,\
            "name": "Attribution-NonCommercial-ShareAlike License",\
            "url": "http://creativecommons.org/licenses/by-nc-sa/2.0/",\
        },\
        ...\
    ],
    "categories": [\
        {\
            "id": 1,\
            "name": "cat",\
            "supercategory": "animal",\
            "keypoints": ["nose", "head", ...],\
            "skeleton": [[12, 14], [14, 16], ...]\
        },\
        ...\
    ],
    "images": [\
        {\
            "id": 1,\
            "license": 1,\
            "file_name": "<filename0>.<ext>",\
            "height": 480,\
            "width": 640,\
            "date_captured": null\
        },\
        ...\
    ],
    "annotations": [\
        {\
            "id": 1,\
            "image_id": 1,\
            "category_id": 1,\
            "bbox": [260, 177, 231, 199],\
            "segmentation": [...],\
            "keypoints": [224, 226, 2, ...],\
            "num_keypoints": 10,\
            "score": 0.95,\
            "area": 45969,\
            "iscrowd": 0\
        },\
        ...\
    ]
}

See this page for a full specification of the segmentation field.

For unlabeled datasets, labels.json does not contain an annotations field.

The file_name attribute of the labels file encodes the location of the corresponding images, which can be any of the following:

  • The filename of an image in the data/ folder

  • A relative path like data/sub/folder/filename.ext specifying the relative path to the image in a nested subfolder of data/

  • An absolute path to an image, which may or may not be in the data/ folder

Note

See COCODetectionDatasetImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from a COCO detection dataset stored in the above format as follows:

Note

By default, all supported label types are loaded (detections, segmentations, and keypoints). However, you can choose specific type(s) to load by passing the optional label_types argument to methods like Dataset.from_dir():

# Only load bounding boxes
dataset = fo.Dataset.from_dir(
    dataset_type=fo.types.COCODetectionDataset,
    label_types=["detections"],
    ...
)

See COCODetectionDatasetImporter for complete documentation of the available COCO import options.

You can also independently specify the locations of the labels and the root directory containing the corresponding media files by providing the labels_path and data_path parameters rather than dataset_dir:

Note

If the file_name key of your labels contains absolute paths to the source media, then you can omit the data_path parameter from the example above.

If you have an existing dataset and corresponding model predictions stored in COCO format, then you can use add_coco_labels() to conveniently add the labels to the dataset. The example below demonstrates a round-trip export and then re-import of both images-and-labels and labels-only data in COCO format:

import fiftyone as fo
import fiftyone.zoo as foz
import fiftyone.utils.coco as fouc

dataset = foz.load_zoo_dataset("quickstart")
classes = dataset.distinct("predictions.detections.label")

# Export images and ground truth labels to disk
dataset.export(
    export_dir="/tmp/coco",
    dataset_type=fo.types.COCODetectionDataset,
    label_field="ground_truth",
    classes=classes,
)

# Export predictions
dataset.export(
    dataset_type=fo.types.COCODetectionDataset,
    labels_path="/tmp/coco/predictions.json",
    label_field="predictions",
    classes=classes,
)

# Now load ground truth labels into a new dataset
dataset2 = fo.Dataset.from_dir(
    dataset_dir="/tmp/coco",
    dataset_type=fo.types.COCODetectionDataset,
    label_field="ground_truth",
)

# And add model predictions
fouc.add_coco_labels(
    dataset2,
    "predictions",
    "/tmp/coco/predictions.json",
    classes,
)

# Verify that ground truth and predictions were imported as expected
print(dataset.count("ground_truth.detections"))
print(dataset2.count("ground_truth.detections"))
print(dataset.count("predictions.detections"))
print(dataset2.count("predictions.detections"))

Note

See add_coco_labels() for a complete description of the available syntaxes for loading COCO-formatted predictions to an existing dataset.

VOCDetectionDataset

The fiftyone.types.VOCDetectionDataset type represents a labeled dataset consisting of images and their associated object detections saved in VOC format.

Datasets of this type are read in the following format:

<dataset_dir>/
    data/
        <uuid1>.<ext>
        <uuid2>.<ext>
        ...
    labels/
        <uuid1>.xml
        <uuid2>.xml
        ...

where the labels XML files are in the following format:

<annotation>
    <folder></folder>
    <filename>image.ext</filename>
    <path>/path/to/dataset-dir/data/image.ext</path>
    <source>
        <database></database>
    </source>
    <size>
        <width>640</width>
        <height>480</height>
        <depth>3</depth>
    </size>
    <segmented></segmented>
    <object>
        <name>cat</name>
        <pose></pose>
        <truncated>0</truncated>
        <difficult>0</difficult>
        <occluded>0</occluded>
        <bndbox>
            <xmin>256</xmin>
            <ymin>200</ymin>
            <xmax>450</xmax>
            <ymax>400</ymax>
        </bndbox>
    </object>
    <object>
        <name>dog</name>
        <pose></pose>
        <truncated>1</truncated>
        <difficult>1</difficult>
        <occluded>1</occluded>
        <bndbox>
            <xmin>128</xmin>
            <ymin>100</ymin>
            <xmax>350</xmax>
            <ymax>300</ymax>
        </bndbox>
    </object>
    ...
</annotation>

where either the <filename> and/or <path> field of the annotations may be populated to specify the corresponding source image.

Unlabeled images have no corresponding file in labels/.

The data/ and labels/ files may contain nested subfolders of parallelly organized images and masks.

Note

See VOCDetectionDatasetImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from a VOC detection dataset stored in the above format as follows:

You can also independently specify the locations of the labels and the root directory containing the corresponding media files by providing the labels_path and data_path parameters rather than dataset_dir:

Note

If the <path> field of your labels are populated with the absolute paths to the source media, then you can omit the data_path parameter from the example above.

KITTIDetectionDataset

The fiftyone.types.KITTIDetectionDataset type represents a labeled dataset consisting of images and their associated object detections saved in KITTI format.

Datasets of this type are read in the following format:

<dataset_dir>/
    data/
        <uuid1>.<ext>
        <uuid2>.<ext>
        ...
    labels/
        <uuid1>.txt
        <uuid2>.txt
        ...

where the labels TXT files are space-delimited files where each row corresponds to an object and the 15 (and optional 16th score) columns have the following meanings:

# of
columns
Name Description Default
1 type The object label
1 truncated A float in [0, 1], where 0 is non-truncated and
1 is fully truncated. Here, truncation refers to the object
leaving image boundaries
0
1 occluded An int in (0, 1, 2, 3) indicating occlusion state,
where:- 0 = fully visible- 1 = partly occluded- 2 =
largely occluded- 3 = unknown
0
1 alpha Observation angle of the object, in [-pi, pi] 0
4 bbox 2D bounding box of object in the image in pixels, in the
format [xtl, ytl, xbr, ybr]
1 dimensions 3D object dimensions, in meters, in the format
[height, width, length]
0
1 location 3D object location (x, y, z) in camera coordinates
(in meters)
0
1 rotation_y Rotation around the y-axis in camera coordinates, in
[-pi, pi]
0
1 score (optional) A float confidence for the detection

When reading datasets of this type, all columns after the four bbox columns are optional.

Unlabeled images have no corresponding file in labels/.

The data/ and labels/ files may contain nested subfolders of parallelly organized images and masks.

Note

See KITTIDetectionDatasetImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from a KITTI detection dataset stored in the above format as follows:

You can also independently specify the locations of the labels and the root directory containing the corresponding media files by providing the labels_path and data_path parameters rather than dataset_dir:

YOLOv4Dataset

The fiftyone.types.YOLOv4Dataset type represents a labeled dataset consisting of images and their associated object detections saved in YOLOv4 format.

Datasets of this type are read in the following format:

<dataset_dir>/
    obj.names
    images.txt
    data/
        <uuid1>.<ext>
        <uuid1>.txt
        <uuid2>.<ext>
        <uuid2>.txt
        ...

where obj.names contains the object class labels:

<label-0>
<label-1>
...

and images.txt contains the list of images in data/:

data/<uuid1>.<ext>
data/<uuid2>.<ext>
...

The image paths in images.txt can be specified as either relative (to the location of file) or as absolute paths. Alternatively, this file can be omitted, in which case the data/ directory is listed to determine the available images.

The TXT files in data/ are space-delimited files where each row corresponds to an object in the image of the same name, in one of the following formats:

# Detections
<target> <x-center> <y-center> <width> <height>
<target> <x-center> <y-center> <width> <height> <confidence>

# Polygons
<target> <x1> <y1> <x2> <y2> <x3> <y3> ...

where <target> is the zero-based integer index of the object class label from obj.names, all coordinates are expressed as relative values in [0, 1] x [0, 1], and <confidence> is an optional confidence in [0, 1].

Unlabeled images have no corresponding TXT file in data/.

The data/ folder may contain nested subfolders.

Note

By default, all annotations are loaded as Detections, converting any polylines to tight bounding boxes if necessary. However, you can choose to load YOLO annotations as Polylines by passing the optional label_type argument to methods like Dataset.from_dir():

# Load annotations as polygons
dataset = fo.Dataset.from_dir(
    dataset_type=fo.types.YOLOv4Dataset,
    label_type="polylines",
    ...
)

See YOLOv4DatasetImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from a YOLOv4 dataset stored in the above format as follows:

You can also independently specify the locations of the labels and the root directory containing the corresponding media files by providing the labels_path and data_path parameters rather than dataset_dir:

If you have an existing dataset and corresponding model predictions stored in YOLO format, then you can use add_yolo_labels() to conveniently add the labels to the dataset.

The example below demonstrates a round-trip export and then re-import of both images-and-labels and labels-only data in YOLO format:

import fiftyone as fo
import fiftyone.zoo as foz
import fiftyone.utils.yolo as fouy

dataset = foz.load_zoo_dataset("quickstart")
classes = dataset.distinct("predictions.detections.label")

# Export images and ground truth labels to disk
dataset.export(
    export_dir="/tmp/yolov4",
    dataset_type=fo.types.YOLOv4Dataset,
    label_field="ground_truth",
    classes=classes,
)

# Export predictions
dataset.export(
    dataset_type=fo.types.YOLOv4Dataset,
    labels_path="/tmp/yolov4/predictions",
    label_field="predictions",
    classes=classes,
)

# Now load ground truth labels into a new dataset
dataset2 = fo.Dataset.from_dir(
    dataset_dir="/tmp/yolov4",
    dataset_type=fo.types.YOLOv4Dataset,
    label_field="ground_truth",
)

# And add model predictions
fouy.add_yolo_labels(
    dataset2,
    "predictions",
    "/tmp/yolov4/predictions",
    classes,
)

# Verify that ground truth and predictions were imported as expected
print(dataset.count("ground_truth.detections"))
print(dataset2.count("ground_truth.detections"))
print(dataset.count("predictions.detections"))
print(dataset2.count("predictions.detections"))

Note

See add_yolo_labels() for a complete description of the available syntaxes for loading YOLO-formatted predictions to an existing dataset.

YOLOv5Dataset

The fiftyone.types.YOLOv5Dataset type represents a labeled dataset consisting of images and their associated object detections saved in YOLOv5 format.

Datasets of this type are read in the following format:

<dataset_dir>/
    dataset.yaml
    images/
        train/
            <uuid1>.<ext>
            <uuid2>.<ext>
            ...
        val/
            <uuid3>.<ext>
            <uuid4>.<ext>
            ...
    labels/
        train/
            <uuid1>.txt
            <uuid2>.txt
            ...
        val/
            <uuid3>.txt
            <uuid4>.txt
            ...

where dataset.yaml contains the following information:

path: <dataset_dir>  # optional
train: ./images/train/
val: ./images/val/

names:
  0: list
  1: of
  2: classes
  ...

See this page for a full description of the possible format of dataset.yaml. In particular, the dataset may contain one or more splits with arbitrary names, as the specific split being imported or exported is specified by the split argument to fiftyone.utils.yolo.YOLOv5DatasetImporter. Also, dataset.yaml can be located outside of <dataset_dir> as long as the optional path is provided.

Note

Any relative paths in dataset.yaml or per-split TXT files are interpreted relative to the directory containing these files, not your current working directory.

The TXT files in labels/ are space-delimited files where each row corresponds to an object in the image of the same name, in one of the following formats:

# Detections
<target> <x-center> <y-center> <width> <height>
<target> <x-center> <y-center> <width> <height> <confidence>

# Polygons
<target> <x1> <y1> <x2> <y2> <x3> <y3> ...

where <target> is the zero-based integer index of the object class label from names, all coordinates are expressed as relative values in [0, 1] x [0, 1], and <confidence> is an optional confidence in [0, 1].

Unlabeled images have no corresponding TXT file in labels/. The label file path for each image is obtained by replacing images/ with labels/ in the respective image path.

The image and labels directories for a given split may contain nested subfolders of parallelly organized images and labels.

Note

By default, all annotations are loaded as Detections, converting any polylines to tight bounding boxes if necessary. However, you can choose to load YOLO annotations as Polylines by passing the optional label_type argument to methods like Dataset.from_dir():

# Load annotations as polygons
dataset = fo.Dataset.from_dir(
    dataset_type=fo.types.YOLOv5Dataset,
    label_type="polylines",
    ...
)

See YOLOv5DatasetImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from a YOLOv5 dataset stored in the above format as follows:

import fiftyone as fo

name = "my-dataset"
dataset_dir = "/path/to/yolov5-dataset"

# The splits to load
splits = ["train", "val"]

# Load the dataset, using tags to mark the samples in each split
dataset = fo.Dataset(name)
for split in splits:
    dataset.add_dir(
        dataset_dir=dataset_dir,
        dataset_type=fo.types.YOLOv5Dataset,
        split=split,
        tags=split,
)

# View summary info about the dataset
print(dataset)

# Print the first few samples in the dataset
print(dataset.head())

If you have an existing dataset and corresponding model predictions stored in YOLO format, then you can use add_yolo_labels() to conveniently add the labels to the dataset.

The example below demonstrates a round-trip export and then re-import of both images-and-labels and labels-only data in YOLO format:

import fiftyone as fo
import fiftyone.zoo as foz
import fiftyone.utils.yolo as fouy

dataset = foz.load_zoo_dataset("quickstart")
classes = dataset.distinct("predictions.detections.label")

# YOLOv5 format supports splits, so let's grab only the `validation` split
view = dataset.match_tags("validation")

# Export images and ground truth labels to disk
view.export(
    export_dir="/tmp/yolov5",
    dataset_type=fo.types.YOLOv5Dataset,
    split="validation",
    label_field="ground_truth",
    classes=classes,
)

# Export predictions
view.export(
    dataset_type=fo.types.YOLOv5Dataset,
    labels_path="/tmp/yolov5/predictions/validation",
    label_field="predictions",
    classes=classes,
)

# Now load ground truth labels into a new dataset
dataset2 = fo.Dataset.from_dir(
    dataset_dir="/tmp/yolov5",
    dataset_type=fo.types.YOLOv5Dataset,
    split="validation",
    label_field="ground_truth",
)

# And add model predictions
fouy.add_yolo_labels(
    dataset2,
    "predictions",
    "/tmp/yolov5/predictions/validation",
    classes,
)

# Verify that ground truth and predictions were imported as expected
print(view.count("ground_truth.detections"))
print(dataset2.count("ground_truth.detections"))
print(view.count("predictions.detections"))
print(dataset2.count("predictions.detections"))

Note

See add_yolo_labels() for a complete description of the available syntaxes for loading YOLO-formatted predictions to an existing dataset.

TFObjectDetectionDataset

The fiftyone.types.TFObjectDetectionDataset type represents a labeled dataset consisting of images and their associated object detections stored as TFRecords in TF Object Detection API format.

Datasets of this type are read in the following format:

<dataset_dir>/
    tf.records-?????-of-?????

where the features of the (possibly sharded) TFRecords are stored in the following format:

{
    # Image dimensions
    "image/height": tf.io.FixedLenFeature([], tf.int64),
    "image/width": tf.io.FixedLenFeature([], tf.int64),

    # Image filename is used for both of these when writing
    "image/filename": tf.io.FixedLenFeature([], tf.string),
    "image/source_id": tf.io.FixedLenFeature([], tf.string),

    # Encoded image bytes
    "image/encoded": tf.io.FixedLenFeature([], tf.string),

    # Image format, either `jpeg` or `png`
    "image/format": tf.io.FixedLenFeature([], tf.string),

    # Normalized bounding box coordinates in `[0, 1]`
    "image/object/bbox/xmin": tf.io.FixedLenSequenceFeature(
        [], tf.float32, allow_missing=True
    ),
    "image/object/bbox/xmax": tf.io.FixedLenSequenceFeature(
        [], tf.float32, allow_missing=True
    ),
    "image/object/bbox/ymin": tf.io.FixedLenSequenceFeature(
        [], tf.float32, allow_missing=True
    ),
    "image/object/bbox/ymax": tf.io.FixedLenSequenceFeature(
        [], tf.float32, allow_missing=True
    ),

    # Class label string
    "image/object/class/text": tf.io.FixedLenSequenceFeature(
        [], tf.string, allow_missing=True
    ),

    # Integer class ID
    "image/object/class/label": tf.io.FixedLenSequenceFeature(
        [], tf.int64, allow_missing=True
    ),
}

The TFRecords for unlabeled samples do not contain image/object/* features.

Note

See TFObjectDetectionDatasetImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from an object detection dataset stored as a directory of TFRecords in the above format as follows:

Note

You can provide the tf_records_path argument instead of dataset_dir in the examples above to directly specify the path to the TFRecord(s) to load. See TFObjectDetectionDatasetImporter for details.

ImageSegmentationDirectory

The fiftyone.types.ImageSegmentationDirectory type represents a labeled dataset consisting of images and their associated semantic segmentations stored as images on disk.

Datasets of this type are read in the following format:

<dataset_dir>/
    data/
        <filename1>.<ext>
        <filename2>.<ext>
        ...
    labels/
        <filename1>.<ext>
        <filename2>.<ext>
        ...

where labels/ contains the semantic segmentations stored as images.

Unlabeled images have no corresponding file in labels/.

The data/ and labels/ files may contain nested subfolders of parallelly organized images and masks.

Note

See ImageSegmentationDirectoryImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from an image segmentation dataset stored in the above format as follows:

You can also independently specify the locations of the masks and the root directory containing the corresponding media files by providing the labels_path and data_path parameters rather than dataset_dir:

CVATImageDataset

The fiftyone.types.CVATImageDataset type represents a labeled dataset consisting of images and their associated tags and object detections stored in CVAT image format.

Datasets of this type are read in the following format:

<dataset_dir>/
    data/
        <uuid1>.<ext>
        <uuid2>.<ext>
        ...
    labels.xml

where labels.xml is an XML file in the following format:

<?xml version="1.0" encoding="utf-8"?>
<annotations>
    <version>1.1</version>
    <meta>
        <task>
            <id>0</id>
            <name>task-name</name>
            <size>51</size>
            <mode>annotation</mode>
            <overlap></overlap>
            <bugtracker></bugtracker>
            <flipped>False</flipped>
            <created>2017-11-20 11:51:51.000000+00:00</created>
            <updated>2017-11-20 11:51:51.000000+00:00</updated>
            <labels>
                <label>
                    <name>car</name>
                    <attributes>
                        <attribute>
                            <name>type</name>
                            <values>coupe\\nsedan\\ntruck</values>
                        </attribute>
                        ...
                    </attributes>
                </label>
                <label>
                    <name>traffic_line</name>
                    <attributes>
                        <attribute>
                            <name>color</name>
                            <values>white\\nyellow</values>
                        </attribute>
                        ...
                    </attributes>
                </label>
                ...
            </labels>
        </task>
        <segments>
            <segment>
                <id>0</id>
                <start>0</start>
                <stop>50</stop>
                <url></url>
            </segment>
        </segments>
        <owner>
            <username></username>
            <email></email>
        </owner>
        <dumped>2017-11-20 11:51:51.000000+00:00</dumped>
    </meta>
    <image id="0" name="<uuid1>.<ext>" width="640" height="480">
        <tag label="urban"></tag>
        ...
        <box label="car" xtl="100" ytl="50" xbr="325" ybr="190" occluded="0">
            <attribute name="type">sedan</attribute>
            ...
        </box>
        ...
        <polygon label="car" points="561.30,916.23;561.30,842.77;...;560.20,966.67" occluded="0">
            <attribute name="make">Honda</attribute>
            ...
        </polygon>
        ...
        <polyline label="traffic_line" points="462.10,0.00;126.80,1200.00" occluded="0">
            <attribute name="color">yellow</attribute>
            ...
        </polyline>
        ...
        <points label="wheel" points="574.90,939.48;1170.16,907.90;...;600.16,459.48" occluded="0">
            <attribute name="location">front_driver_side</attribute>
            ...
        </points>
        ...
    </image>
    ...
    <image id="50" name="<uuid51>.<ext>" width="640" height="480">
        ...
    </image>
</annotations>

Unlabeled images have no corresponding image tag in labels.xml.

The name field of the <image> tags in the labels file encodes the location of the corresponding images, which can be any of the following:

  • The filename of an image in the data/ folder

  • A relative path like data/sub/folder/filename.ext specifying the relative path to the image in a nested subfolder of data/

  • An absolute path to an image, which may or may not be in the data/ folder

Note

See CVATImageDatasetImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from a CVAT image dataset stored in the above format as follows:

You can also independently specify the locations of the labels and the root directory containing the corresponding media files by providing the labels_path and data_path parameters rather than dataset_dir:

Note

If the name key of your labels contains absolute paths to the source media, then you can omit the data_path parameter from the example above.

CVATVideoDataset

The fiftyone.types.CVATVideoDataset type represents a labeled dataset consisting of videos and their associated object detections stored in CVAT video format.

Datasets of this type are read in the following format:

<dataset_dir>/
    data/
        <uuid1>.<ext>
        <uuid2>.<ext>
        ...
    labels/
        <uuid1>.xml
        <uuid2>.xml
        ...

where the labels XML files are stored in the following format:

<?xml version="1.0" encoding="utf-8"?>
<annotations>
    <version>1.1</version>
    <meta>
        <task>
            <id>task-id</id>
            <name>task-name</name>
            <size>51</size>
            <mode>interpolation</mode>
            <overlap></overlap>
            <bugtracker></bugtracker>
            <flipped>False</flipped>
            <created>2017-11-20 11:51:51.000000+00:00</created>
            <updated>2017-11-20 11:51:51.000000+00:00</updated>
            <labels>
                <label>
                    <name>car</name>
                    <attributes>
                        <attribute>
                            <name>type</name>
                            <values>coupe\\nsedan\\ntruck</values>
                        </attribute>
                        ...
                    </attributes>
                </label>
                <label>
                    <name>traffic_line</name>
                    <attributes>
                        <attribute>
                            <name>color</name>
                            <values>white\\nyellow</values>
                        </attribute>
                        ...
                    </attributes>
                </label>
                ...
            </labels>
        </task>
        <segments>
            <segment>
                <id>0</id>
                <start>0</start>
                <stop>50</stop>
                <url></url>
            </segment>
        </segments>
        <owner>
            <username></username>
            <email></email>
        </owner>
        <original_size>
            <width>640</width>
            <height>480</height>
        </original_size>
        <dumped>2017-11-20 11:51:51.000000+00:00</dumped>
    </meta>
    <track id="0" label="car">
        <box frame="0" xtl="100" ytl="50" xbr="325" ybr="190" outside="0" occluded="0" keyframe="1">
            <attribute name="type">sedan</attribute>
            ...
        </box>
        ...
    </track>
    <track id="1" label="car">
        <polygon frame="0" points="561.30,916.23;561.30,842.77;...;560.20,966.67" outside="0" occluded="0" keyframe="1">
            <attribute name="make">Honda</attribute>
            ...
        </polygon>
        ...
    </track>
    ...
    <track id="10" label="traffic_line">
        <polyline frame="10" points="462.10,0.00;126.80,1200.00" outside="0" occluded="0" keyframe="1">
            <attribute name="color">yellow</attribute>
            ...
        </polyline>
        ...
    </track>
    ...
    <track id="88" label="wheel">
        <points frame="176" points="574.90,939.48;1170.16,907.90;...;600.16,459.48" outside="0" occluded="0" keyframe="1">
            <attribute name="location">front_driver_side</attribute>
            ...
        </points>
        ...
    </track>
</annotations>

Unlabeled videos have no corresponding file in labels/.

The data/ and labels/ files may contain nested subfolders of parallelly organized images and labels.

Note

See CVATVideoDatasetImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from a CVAT video dataset stored in the above format as follows:

You can also independently specify the locations of the labels and the root directory containing the corresponding media files by providing the labels_path and data_path parameters rather than dataset_dir:

OpenLABELImageDataset

The fiftyone.types.OpenLABELImageDataset type represents a labeled dataset consisting of images and their associated multitask predictions stored = in OpenLABEL format.

OpenLABEL is a flexible format which allows labels to be stored in a variety of different ways with respect to the corresponding media files. The following enumerates the possible structures in which media data and OpenLABEL formatted label files can be stored in ways that is understood by FiftyOne:

  1. One label file per image. Each label contains only the metadata and labels associated with the image of the same name. In this case, the labels_path argument is expected to be a directory, if provided:
<dataset_dir>/
    data/
        <uuid1>.<ext>
        <uuid2>.<ext>
        ...
    labels/
        <uuid1>.json
        <uuid2>.json
        ...
  1. One label file for all images. The label file contains all of the metadata and labels associated with every image. In this case, there needs to be additional information provided in the label file to match labels to images. Specifically, the image filepath corresponding to a label must be stored as a stream:
<dataset_dir>/
    data/
        <uuid1>.<ext>
        <uuid2>.<ext>
        ...
    labels.json
  1. Multiple label files, each corresponding to one or more images. This case is similar to when there is a single label file, except that the label information may be spread out over multiple files. Since the filenames cannot be used to match labels to images, the image filepaths must again be stored as streams in the labels files:
<dataset_dir>/
    data/
        <uuid1>.<ext>
        <uuid2>.<ext>
        ...
    labels/
        <labels-filename1>.json
        <labels-filename2>.json
        ...

As for the actual structure of the labels files themselves, labels are stored in one or more JSON files and can follow a variety of formats. In general following this format:

Note

All object information stored in the frames key is applied to the corresponding image.

{
    "openlabel": {
        "metadata": {
            "schema_version": "1.0.0",
            "uri": "/path/to/<uuid>.<ext>",
        },
        "objects": {
            "object_uuid1": {
                "name": "instance1",
                "type": "label1",
                "object_data": {
                    "bbox": [\
                        {\
                            "name": "shape",\
                            "val": [\
                                center-x,\
                                center-y,\
                                width,\
                                height\
                            ]\
                        }\
                    ]
                }
            },
            "object_uuid2": {
                "name": "instance1",
                "type": "label2",
                "object_data": {},  # DEFINED IN FRAMES
            }
        },
        "frames": {
            "0": {
               "frame_properties": {
                  "streams": {
                     "Camera1": {
                        "uri": "<uuid>.<ext>"
                     }
                  }
               },
               "objects": {
                  "object_uuid2": {
                     "object_data": {
                        "poly2d": [\
                           {\
                              "attributes": {\
                                 "boolean": [\
                                    {\
                                       "name": "is_hole",\
                                       "val": false\
                                    }\
                                 ],\
                                 "text": [\
                                    {  # IF NOT PROVIDED OTHERWISE\
                                       "name": "stream",\
                                       "val": "Camera1"\
                                    }\
                                 ]\
                              },\
                              "closed": true,\
                              "mode": "MODE_POLY2D_ABSOLUTE",\
                              "name": "polygon_name",\
                              "stream": "Camera1",  # IF NOT IN ATTRIBUTES\
                              "val": [\
                                 point1-x,\
                                 point1-y,\
                                 point2-x,\
                                 point2-y,\
                                 ...\
                              ]\
                           }\
                        ]
                     }
                  }
              }
           }
        },
        "streams": {
           "Camera1": {
              "description": "",
              "stream_properties": {
                 "height": 480,
                 "width": 640
              },
              "type": "camera"
           }
        },
        "ontologies": ... # NOT PARSED
        "relations": ... # NOT PARSED
        "resources": ... # NOT PARSED
        "tags": ... # NOT PARSED
    }
}

Note

See OpenLABELImageDatasetImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

If loading Keypoints related to a given KeypointSkeleton, then you can provide a skeleton and skeleton_key argument to the OpenLABELImageDatasetImporter allowing you to match points in your annotations file to labels in the KeypointSkeleton and load the points and their attributes in the correct order.

You can create a FiftyOne dataset from a OpenLABEL image dataset stored in the above format as follows:

You can also independently specify the locations of the labels and the root directory containing the corresponding media files by providing the labels_path and data_path parameters rather than dataset_dir:

Note

OpenLABEL is a flexible format that allows for many user-specific decisions about how to represent labels and metadata. If you have OpenLABEL-compliant data in a format not understood by the current importers, please make an issue or contribute a pull request!

OpenLABELVideoDataset

The fiftyone.types.OpenLABELVideoDataset type represents a labeled dataset consisting of videos and their associated multitask predictions stored in OpenLABEL format.

OpenLABEL is a flexible format which allows labels to be stored in a variety of different ways with respect to the corresponding media files. The following enumerates the possible structures in which media data and OpenLABEL formatted label files can be stored in ways that is understood by FiftyOne:

  1. One label file per video. Each label contains only the metadata and labels associated with the video of the same name. In this case, the labels_path argument is expected to be a directory, if provided:
<dataset_dir>/
    data/
        <uuid1>.<ext>
        <uuid2>.<ext>
        ...
    labels/
        <uuid1>.json
        <uuid2>.json
        ...
  1. One label file for all videos. The label file contains all of the metadata and labels associated with every video. In this case, there needs to be additional information provided in the label file to match labels to videos. Specifically, the video filepath corresponding to a label must be stored as a stream:
<dataset_dir>/
    data/
        <uuid1>.<ext>
        <uuid2>.<ext>
        ...
    labels.json
  1. Multiple label files, each corresponding to one or more videos. This case is similar to when there is a single label file, except that the label information may be spread out over multiple files. Since the filenames cannot be used to match labels to videos, the video filepaths must again be stored as streams in the labels files:
<dataset_dir>/
    data/
        <uuid1>.<ext>
        <uuid2>.<ext>
        ...
    labels/
        <labaels-filename1>.json
        <labaels-filename2>.json
        ...

As for the actual structure of the labels files themselves, labels are stored in one or more JSON files and can follow a variety of formats. In general following this format:

{
    "openlabel": {
        "metadata": {
            "schema_version": "1.0.0",
            "uri": "/path/to/<uuid>.<ext>",
        },
        "objects": {
            "object_uuid1": {
                "name": "instance1",
                "type": "label1",
                "object_data": {
                    "bbox": [\
                        {\
                            "name": "shape",\
                            "val": [\
                                center-x,\
                                center-y,\
                                width,\
                                height\
                            ]\
                        }\
                    ]
                }
                "frame_intervals": [{"frame_start": 0, "frame_end": 10}],
            },
            "object_uuid2": {
                "name": "instance1",
                "type": "label2",
                "object_data": {},  # DEFINED IN FRAMES
            }
        },
        "frames": {
            "0": {
               "frame_properties": {
                  "streams": {
                     "Camera1": {
                        "uri":"<uuid>.<ext>"
                     }
                  }
               },
               "objects": {
                  "object_uuid2": {
                     "object_data": {
                        "poly2d": [\
                           {\
                              "attributes": {\
                                 "boolean": [\
                                    {\
                                       "name": "is_hole",\
                                       "val": false\
                                    }\
                                 ],\
                                 "text": [\
                                    {  # IF NOT PROVIDED OTHERWISE\
                                       "name": "stream",\
                                       "val": "Camera1"\
                                    }\
                                 ]\
                              },\
                              "closed": true,\
                              "mode": "MODE_POLY2D_ABSOLUTE",\
                              "name": "polygon_name",\
                              "stream": "Camera1",  # IF NOT IN ATTRIBUTES\
                              "val": [\
                                 point1-x,\
                                 point1-y,\
                                 point2-x,\
                                 point2-y,\
                                 ...\
                              ]\
                           }\
                        ]
                     }
                  }
              },
              ...
           }
        },
        "streams": {
           "Camera1": {
              "description": "",
              "stream_properties": {
                 "height": 480,
                 "width": 640
              },
              "type": "camera"
           }
        },
        "ontologies": ...  # NOT PARSED
        "relations" ...  # NOT PARSED
        "resources" ...  # NOT PARSED
        "tags": ...  # NOT PARSED
    }
}

Note

See OpenLABELVideoDatasetImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

If loading Keypoints related to a given KeypointSkeleton, then you can provide a skeleton and skeleton_key argument to the OpenLABELVideoDatasetImporter allowing you to match points in your annotations file to labels in the KeypointSkeleton and load the points and their attributes in the correct order.

You can create a FiftyOne dataset from a OpenLABEL video dataset stored in the above format as follows:

You can also independently specify the locations of the labels and the root directory containing the corresponding media files by providing the labels_path and data_path parameters rather than dataset_dir:

Note

OpenLABEL is a flexible format that allows for many user-specific decisions about how to represent labels and metadata. If you have OpenLABEL-compliant data in a format not understood by the current importers, please make an issue or contribute a pull request!

FiftyOneImageLabelsDataset

The fiftyone.types.FiftyOneImageLabelsDataset type represents a labeled dataset consisting of images and their associated multitask predictions stored in ETA ImageLabels format.

Datasets of this type are read in the following format:

<dataset_dir>/
    data/
        <uuid1>.<ext>
        <uuid2>.<ext>
        ...
    labels/
        <uuid1>.json
        <uuid2>.json
        ...
    manifest.json

where manifest.json is a JSON file in the following format:

{
    "type": "eta.core.datasets.LabeledImageDataset",
    "description": "",
    "index": [\
        {\
            "data": "data/<uuid1>.<ext>",\
            "labels": "labels/<uuid1>.json"\
        },\
        {\
            "data": "data/<uuid2>.<ext>",\
            "labels": "labels/<uuid2>.json"\
        },\
        ...\
    ]
}

and where each labels JSON file is stored in ETA ImageLabels format.

For unlabeled images, an empty eta.core.image.ImageLabels file is stored.

Note

See FiftyOneImageLabelsDatasetImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from an image labels dataset stored in the above format as follows:

FiftyOneVideoLabelsDataset

The fiftyone.types.FiftyOneVideoLabelsDataset type represents a labeled dataset consisting of videos and their associated labels stored in ETA VideoLabels format.

Datasets of this type are read in the following format:

<dataset_dir>/
    data/
        <uuid1>.<ext>
        <uuid2>.<ext>
        ...
    labels/
        <uuid1>.json
        <uuid2>.json
        ...
    manifest.json

where manifest.json is a JSON file in the following format:

{
    "type": "eta.core.datasets.LabeledVideoDataset",
    "description": "",
    "index": [\
        {\
            "data": "data/<uuid1>.<ext>",\
            "labels": "labels/<uuid1>.json"\
        },\
        {\
            "data": "data/<uuid2>.<ext>",\
            "labels": "labels/<uuid2>.json"\
        },\
        ...\
    ]
}

and where each labels JSON file is stored in ETA VideoLabels format.

For unlabeled videos, an empty eta.core.video.VideoLabels file is written.

Note

See FiftyOneVideoLabelsDatasetImporter for parameters that can be passed to methods like Dataset.from_dir() to customize the import of datasets of this type.

You can create a FiftyOne dataset from a video labels dataset stored in the above format as follows:

BDDDataset

The fiftyone.types.BDDDataset type represents a labeled dataset consisting of images and their associated multitask predictions saved in Berkeley DeepDrive (BDD) format.

Datasets of this type are read in the following format:

<dataset_dir>/
    data/
        <filename0>.<ext>
        <filename1>.<ext>
        ...
    labels.json

where labels.json is a JSON file in the following format:

python [\ {\ "name": "<filename0>.<ext>",\ "attributes": {\ "scene": "city street",\ "timeofday": "daytime",\ "weather": "overcast"\ },\ "labels": [\ {\ "id": 0,\ "category": "traffic sign",\ "manualAttributes": true,\ "manualShape": true,\ "attributes": {\ "occluded": false,\ "trafficLightColor": "none",\ "truncated": false\ },\ "box2d": {\ "x1": 1000.698742,\ "x2": 1040.626872,\ "y1": 281.992415,\ "y2": 326.91156\ },\ "score": 0.95\ },\ ...\ {\ "id": 34,\ "category": "drivable area",\ "manualAttributes": true,\ "manualShape": true,\ "attributes": {\ "areaType": "direct"\ },\ "poly2d": [\ {\ "types": "LLLLCCC",\ "closed": true,\ "vertices": [\ [241.143645, 697.923453],\ [541.525255, 380.564983],\ ...\ ]\ }\ ],\ "score": 0.87\ },\ ...\ {\ "id": 109356,\ "category": "lane",\ "attributes": {\ "laneDirection": "parallel",\ "laneStyle": "dashed",\ "laneType": "single white"\ },\ "manualShape": true,\ "manualAttributes": true,\ "poly2d": [\ {\ "types": "LL",\ "closed": false,\ "vertices": [\ [492.879546, 331.939543],\ [0, 471.076658],\ ...\ ]\ }\ ],\ "score": 0.98\ },\ ...\ }\ }\ ...\ ]\ \\ \ Unlabeled images have no corresponding entry in labels.json.\ \ The name attribute of the labels file encodes the location of the\ corresponding images, which can be any of the following:\ \ - The filename of an image in the data/ folder\ \ - A relative path like data/sub/folder/filename.ext specifying the relative\ path to the image in a nested subfolder of data/\ \ - An absolute path to an image, which may or may not be in the data/ folder\ \ \ Note\ \ See BDDDatasetImporter\ for parameters that can be passed to methods like\ Dataset.from_dir() to\ customize the import of datasets of this type.\ \ You can create a FiftyOne dataset from a BDD dataset stored in the above format\ as follows:\ \ You can also independently specify the locations of the labels and the root\ directory containing the corresponding media files by providing the\ labels_path and data_path parameters rather than dataset_dir:\ \ Note\ \ If the name key of your labels contains absolute paths to the source\ media, then you can omit the data_path parameter from the example above.\ \ ## CSVDataset \ \ The fiftyone.types.CSVDataset type represents a dataset consisting\ of images or videos and their associated field values stored as columns of a\ CSV file.\ \ Datasets of this type are read in the following format:\ \ \ <dataset_dir>/\ data/\ <filename1>.<ext>\ <filename2>.<ext>\ ...\ labels.csv\ \\ \ where labels.csv is a CSV file in the following format:\ \ \ field1,field2,field3,...\ value1,value2,value3,...\ value1,value2,value3,...\ ...\ \\ \ One sample will be generated per row in the CSV file (excluding the header\ row).\ \ One column of the CSV file must contain media paths, which may be either:\ \ - filenames or relative paths to media files in data/\ \ - absolute paths to media files\ \ \ By default it is assumed that a filepath column exists and contains the\ media paths, but you can customize this via the optional media_field\ parameter.\ \ By default all columns are loaded as string fields, but you can provide the\ optional fields parameter to select a subset of columns to load or provide\ custom parsing functions for each field, as demonstrated below.\ \ Note\ \ See CSVDatasetImporter\ for parameters that can be passed to methods like\ Dataset.from_dir() to\ customize the import of datasets of this type.\ \ You can create a FiftyOne dataset from a CSV dataset stored in the above\ format as follows:\ \ If your CSV file contains absolute media paths, then you can directly specify\ the path to the CSV file itself by providing the labels_path parameter.\ \ Additionally, you can use the fields parameter to customize how each field is\ parsed, as demonstrated below:\ \ ## DICOMDataset \ \ The fiftyone.types.DICOMDataset type represents a dataset consisting\ of images and their associated properties stored in\ DICOM format.\ \ Note\ \ You must have pydicom<3 installed\ in order to load DICOM datasets.\ \ The standard format for datasets of this type is the following:\ \ \ <dataset_dir>/\ <filename1>.dcm\ <filename2>.dcm\ \\ \ where each .dcm file is a DICOM file that can be read via\ pydicom.dcmread.\ \ Alternatively, rather than providing a dataset_dir, you can provide the\ dicom_path argument, which can directly specify a glob pattern of DICOM\ files or the path to a\ DICOMDIR\ file.\ \ By default, all attributes in the DICOM files discoverable via\ pydicom.dataset.Dataset.dir() with supported types are loaded\ into sample-level fields, but you can select only specific attributes by\ passing the optional keywords argument.\ \ Note\ \ When importing DICOM datasets, the pixel data are converted to 8-bit\ images, using the SmallestImagePixelValue and\ LargestImagePixelValue attributes (if present), to inform the\ conversion.\ \ The images are written to a backing directory that you can configure by\ passing the images_dir argument. By default, the images are written to\ dataset_dir.\ \ Currently, only single frame images are supported, but a community\ contribution to support 3D or 4D image types (e.g., CT scans) is welcomed!\ \ Note\ \ See DICOMDatasetImporter\ for parameters that can be passed to methods like\ Dataset.from_dir() to\ customize the import of datasets of this type.\ \ You can create a FiftyOne dataset from a DICOM dataset stored in standard\ format as follows:\ \ You can create a FiftyOne dataset from a glob pattern of DICOM files or the\ path to a DICOMDIR file as follows:\ \ ## GeoJSONDataset \ \ The fiftyone.types.GeoJSONDataset type represents a dataset consisting\ of images or videos and their associated geolocation data and optional\ properties stored in GeoJSON format.\ \ Datasets of this type are read in the following format:\ \ \ <dataset_dir>/\ data/\ <filename1>.<ext>\ <filename2>.<ext>\ ...\ labels.json\ \\ \ where labels.json is a GeoJSON file containing a FeatureCollection in the\ following format:\ \ \ {\ "type": "FeatureCollection",\ "features": [\ {\ "type": "Feature",\ "geometry": {\ "type": "Point",\ "coordinates": [\ -73.99496451958454,\ 40.66338032487842\ ]\ },\ "properties": {\ "filename": <filename1>.<ext>,\ ...\ }\ },\ {\ "type": "Feature",\ "geometry": {\ "type": "Point",\ "coordinates": [\ -73.80992143421788,\ 40.65611832778962\ ]\ },\ "properties": {\ "filename": <filename2>.<ext>,\ ...\ }\ },\ ...\ ]\ }\ \\ \ where the geometry field may contain any valid GeoJSON geometry object, and\ the filename property encodes the name of the corresponding media in the\ data/ folder. The filename property can also be an absolute path, which\ may or may not be in the data/ folder.\ \ Samples with no location data will have a null geometry field.\ \ The properties field of each feature can contain additional labels that\ can be imported.\ \ Note\ \ See GeoJSONDatasetImporter\ for parameters that can be passed to methods like\ Dataset.from_dir() to\ customize the import of datasets of this type.\ \ You can create a FiftyOne dataset from a GeoJSON dataset stored in the above\ format as follows:\ \ You can also independently specify the locations of the labels and the root\ directory containing the corresponding media files by providing the\ labels_path and data_path parameters rather than dataset_dir:\ \ Note\ \ If the filename key of your labels contains absolute paths to the source\ media, then you can omit the data_path parameter from the example above.\ \ ## GeoTIFFDataset \ \ The fiftyone.types.GeoTIFFDataset type represents a dataset consisting\ of images and their associated geolocation data stored in\ GeoTIFF format.\ \ Note\ \ You must have rasterio installed in\ order to load GeoTIFF datasets.\ \ The standard format for datasets of this type is the following:\ \ \ <dataset_dir>/\ <filename1>.tif\ <filename2>.tif\ \\ \ where each .tif file is a GeoTIFF image that can be read via\ rasterio.open.\ \ Alternatively, rather than providing a dataset_dir, you can provide the\ image_path argument, which can directly specify a list or glob pattern of\ GeoTIFF images to load.\ \ The dataset will contain a GeoLocation field whose\ point attribute contains the\ (longitude, latitude) coordinates of each image center and whose\ polygon attribute contains\ the (longitude, latitude) coordinates of the corners of the image (clockwise,\ starting from the top-left corner).\ \ Note\ \ See GeoTIFFDatasetImporter\ for parameters that can be passed to methods like\ Dataset.from_dir() to\ customize the import of datasets of this type.\ \ You can create a FiftyOne dataset from a GeoTIFF dataset stored in standard\ format as follows:\ \ You can create a FiftyOne dataset from a list or glob pattern of GeoTIFF images\ as follows:\ \ ## FiftyOneDataset \ \ The fiftyone.types.FiftyOneDataset provides a disk representation of\ an entire Dataset in a serialized JSON format along with its source media.\ \ Datasets of this type are read in the following format:\ \ \ <dataset_dir>/\ metadata.json\ samples.json\ data/\ <filename1>.<ext>\ <filename2>.<ext>\ ...\ annotations/\ <anno_key1>.json\ <anno_key2>.json\ ...\ brain/\ <brain_key1>.json\ <brain_key2>.json\ ...\ evaluations/\ <eval_key1>.json\ <eval_key2>.json\ ...\ \\ \ where metadata.json is a JSON file containing metadata associated with the\ dataset, samples.json is a JSON file containing a serialized representation\ of the samples in the dataset, annotations/ contains any serialized\ AnnotationResults, brain/ contains any serialized BrainResults, and\ evaluations/ contains any serialized EvaluationResults.\ \ The contents of the data/ directory may also be organized in nested\ subfolders, depending on how the dataset was exported, in which case the\ filepaths in samples.json should contain corerspondingly nested paths.\ \ Video datasets have an additional frames.json file that contains a serialized\ representation of the frame labels for each video in the dataset.\ \ Note\ \ See FiftyOneDatasetImporter\ for parameters that can be passed to methods like\ Dataset.from_dir() to\ customize the import of datasets of this type.\ \ You can create a FiftyOne dataset from a directory in the above format as\ follows:\ \ If you performed a FiftyOneDataset export\ using the rel_dir parameter to strip a common prefix from the media filepaths\ in the dataset, then simply include the rel_dir parameter when importing back\ into FiftyOne to prepend the appropriate prefix to each media path:\ \ Note\ \ Exporting in FiftyOneDataset format using\ the export_media=False and rel_dir parameters is a convenient way to\ transfer datasets between work environments, since this enables you to\ store the media files wherever you wish in each environment and then simply\ provide the appropriate rel_dir value as shown above when importing the\ dataset into FiftyOne in a new environment.\ \ ## Custom formats \ \ If your data does not follow one of the previous formats, then the simplest and\ most flexible approach to loading your data into FiftyOne is to iterate over\ your data in a Python loop and add it to a Dataset.\ \ Alternatively, the Dataset class provides a\ Dataset.from_importer()\ factory method that can be used to import a dataset using any DatasetImporter\ instance.\ \ This means that you can define your own DatasetImporter class and then import\ a dataset from disk in your custom format using the following recipe:\ \ \ import fiftyone as fo\ \ # Create an instance of your custom dataset importer\ importer = CustomDatasetImporter(...)\ \ # Import the dataset\ dataset = fo.Dataset.from_importer(importer)\ \\ \ You can also define a custom Dataset type, which enables you to import\ datasets in your custom format using the\ Dataset.from_dir() factory\ method:\ \ \ import fiftyone as fo\ \ # The `fiftyone.types.Dataset` subclass for your custom dataset\ dataset_type = CustomDataset\ \ # Import the dataset\ dataset = fo.Dataset.from_dir(dataset_type=dataset_type, ...)\ \\ \ ### Writing a custom DatasetImporter \ \ DatasetImporter is an abstract interface; the concrete interface that you\ should implement is determined by the type of dataset that you are importing.\ \ ### Importing dataset-level information \ \ The\ has_dataset_info\ property of the importer allows it to declare whether its\ get_dataset_info()\ method should be called after all samples have been imported to retrieve a dict\ of dataset-level information to store in the\ info property of the dataset.\ \ As a special case, if the info dict contains any of the keys listed below,\ these items are popped and stored in the corresponding dedicated dataset field:\ \ - "classes" key:\ Dataset.classes\ \ - "default_classes" key:\ Dataset.default_classes\ \ - "mask_targets" key:\ Dataset.mask_targets\ \ - "default_mask_targets" key:\ Dataset.default_mask_targets\ \ - "skeletons" key:\ Dataset.skeletons\ \ - "default_skeleton" key:\ Dataset.default_skeleton\ \ - "app_config" key:\ Dataset.app_config\ \ \ ### Writing a custom Dataset type \ \ FiftyOne provides the Dataset type system so that dataset formats can be\ conveniently referenced by their type when reading/writing datasets on disk.\ \ The primary function of the Dataset subclasses is to define the\ DatasetImporter that should be used to read instances of the dataset from\ disk and the DatasetExporter that should be used to write instances of the\ dataset to disk.\ \ See this page for more information\ about defining custom DatasetExporter classes.\ \ Custom dataset types can be declared by implementing the Dataset subclass\ corresponding to the type of dataset that you are working with.\ \