Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for label field dicts when importing labeled datasets #1864

Merged
merged 3 commits into from
Jun 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions docs/source/user_guide/dataset_creation/datasets.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5164,14 +5164,20 @@ should implement is determined by the type of dataset that you are importing.
importer = CustomLabeledImageDatasetImporter(...)
label_field = ...

if isinstance(label_field, dict):
label_key = lambda k: label_field.get(k, k)
elif label_field is not None:
label_key = lambda k: label_field + "_" + k
else:
label_field = "ground_truth"
label_key = lambda k: k

with importer:
for image_path, image_metadata, label in importer:
sample = fo.Sample(filepath=image_path, metadata=image_metadata)

if isinstance(label, dict):
sample.update_fields(
{label_field + "_" + k: v for k, v in label.items()}
)
sample.update_fields({label_key(k): v for k, v in label.items()})
elif label is not None:
sample[label_field] = label

Expand Down Expand Up @@ -5566,14 +5572,20 @@ should implement is determined by the type of dataset that you are importing.
importer = CustomLabeledVideoDatasetImporter(...)
label_field = ...

if isinstance(label_field, dict):
label_key = lambda k: label_field.get(k, k)
elif label_field is not None:
label_key = lambda k: label_field + "_" + k
else:
label_field = "ground_truth"
label_key = lambda k: k

with importer:
for video_path, video_metadata, label, frames in importer:
sample = fo.Sample(filepath=video_path, metadata=video_metadata)

if isinstance(label, dict):
sample.update_fields(
{label_field + "_" + k: v for k, v in label.items()}
)
sample.update_fields({label_key(k): v for k, v in label.items()})
elif label is not None:
sample[label_field] = label

Expand All @@ -5583,8 +5595,7 @@ should implement is determined by the type of dataset that you are importing.
for frame_number, _label in frames.items():
if isinstance(_label, dict):
frame_labels[frame_number] = {
label_field + "_" + field_name: label
for field_name, label in _label.items()
label_key(k): v for k, v in _label.items()
}
elif _label is not None:
frame_labels[frame_number] = {label_field: _label}
Expand Down
27 changes: 19 additions & 8 deletions docs/source/user_guide/dataset_creation/samples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,14 @@ classification or object detections) associated with the image.
sample_parser = CustomLabeledImageSampleParser(...)
label_field = ...

if isinstance(label_field, dict):
label_key = lambda k: label_field.get(k, k)
elif label_field is not None:
label_key = lambda k: label_field + "_" + k
else:
label_field = "ground_truth"
label_key = lambda k: k

for sample in samples:
sample_parser.with_sample(sample)

Expand All @@ -947,9 +955,7 @@ classification or object detections) associated with the image.
sample = fo.Sample(filepath=image_path, metadata=metadata)

if isinstance(label, dict):
sample.update_fields(
{label_field + "_" + k: v for k, v in label.items()}
)
sample.update_fields({label_key(k): v for k, v in label.items()})
elif label is not None:
sample[label_field] = label

Expand Down Expand Up @@ -1191,6 +1197,14 @@ classification or object detections) associated with the image.
sample_parser = CustomLabeledVideoSampleParser(...)
label_field = ...

if isinstance(label_field, dict):
label_key = lambda k: label_field.get(k, k)
elif label_field is not None:
label_key = lambda k: label_field + "_" + k
else:
label_field = "ground_truth"
label_key = lambda k: k

for sample in samples:
sample_parser.with_sample(sample)

Expand All @@ -1207,9 +1221,7 @@ classification or object detections) associated with the image.
sample = fo.Sample(filepath=video_path, metadata=metadata)

if isinstance(label, dict):
sample.update_fields(
{label_field + "_" + k: v for k, v in label.items()}
)
sample.update_fields({label_key(k): v for k, v in label.items()})
elif label is not None:
sample[label_field] = label

Expand All @@ -1219,8 +1231,7 @@ classification or object detections) associated with the image.
for frame_number, _label in frames.items():
if isinstance(_label, dict):
frame_labels[frame_number] = {
label_field + "_" + field_name: label
for field_name, label in _label.items()
label_key(k): v for k, v in _label.items()
}
elif _label is not None:
frame_labels[frame_number] = {label_field: _label}
Expand Down
28 changes: 19 additions & 9 deletions docs/source/user_guide/model_zoo/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ All models in the FiftyOne Model Zoo are instances of the |Model| class, which
defines a common interface for loading models and generating predictions with
defined input and output data formats.

.. note:
.. note::

The following sections describe the interface that all models in the Model
Zoo implement. If you write a wrapper for your custom model that implements
Expand Down Expand Up @@ -357,7 +357,7 @@ and the output ``labels`` can be any of the following:

# Multiple sample-level labels
for key, value in labels.items():
sample[label_field + "_" + key] = value
sample[label_key(key)] = value

- A dict mapping frame numbers to |Label| instances. In this case, the
provided labels are interpreted as frame-level labels that should be added
Expand All @@ -384,27 +384,37 @@ and the output ``labels`` can be any of the following:
# Multiple per-frame labels
sample.frames.merge(
{
frame_number: {
label_field + "_" + name: label
for name, label in frame_dict.items()
}
frame_number: {label_key(k): v for k, v in frame_dict.items()}
for frame_number, frame_dict in labels.items()
}
)

In the above snippets, the ``label_key`` function maps label dict keys to field
names, and is defined from ``label_field`` as follows::

.. code-block:: python
:linenos:

if isinstance(label_field, dict):
label_key = lambda k: label_field.get(k, k)
elif label_field is not None:
label_key = lambda k: label_field + "_" + k
else:
label_key = lambda k: k

For models that support batching, the |Model| interface also provides a
:meth:`predict_all() <fiftyone.core.models.Model.predict_all>` method that can
provide an efficient implementation of predicting on a batch of data.

.. note:
.. note::

Builtin methods like
:meth:`apply_model() <fiftyone.core.collections.SampleCollection.apply_model>`
provide a ``batch_size`` parameter that can be used to control the batch
size used when performing inference with models that support efficient
batching.

.. note:
.. note::

PyTorch models can implement the |TorchModelMixin| mixin, in which case
`DataLoaders <https://pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader>`_
Expand Down Expand Up @@ -440,7 +450,7 @@ By convention,
:meth:`Model.embed() <fiftyone.core.models.EmbeddingsMixin.embed>` should
return a numpy array containing the embedding.

.. note:
.. note::

Sample embeddings are typically 1D vectors, but this is not strictly
required.
Expand Down
Loading