Giter Site home page Giter Site logo

fiftyone-albumentations-plugin's Introduction

Albumentations Data Augmentation Plugin for FiftyOne

apply_from_saved

Traditionally, data augmentation is performed on-the-fly during training. This is great... if you know exactly what augmentations you want to apply to your dataset.

However, if you're just getting started with a new dataset, you may not know what augmentations are appropriate for your data. In this case, it can be helpful to apply a wide range of augmentations to your dataset and then manually inspect the results to see which augmentations are appropriate for your data.

This plugin provides a simple interface to apply, test, compose, and save augmentation transformations to your dataset using the Albumentations library and the FiftyOne library for data curation and visualization. Both libraries are open-source and easy to use!

Supported Data Types

The plugin currently supports image media types. For images, it has support for the following label types:

Installation

fiftyone plugins download https://github.com/jacobmarks/fiftyone-albumentations-plugin

You will also need to make sure that Albumentations is installed:

pip install albumentations

Usage

Setup

To get started, launch the FiftyOne App and load in your dataset. If you don't have a dataset yet, you can use the FiftyOne Dataset Zoo to load in a sample dataset.

πŸ’‘ To load the quickstart dataset from the zoo, press the backtick key (`) to open the operators list, and select load_zoo_dataset from the list. Then, select quickstart from the dropdown and press Enter.

Applying Augmentations

apply_transforms

Once you have a dataset loaded, you can apply augmentations to your dataset using the augment_with_albumentations operator.

Configuration Options

You will have a few options to configure:

  • Number of Augmentations per Sample: The number of augmentations to apply to each sample. This will create a new sample for each augmentation. The default is 1.

  • Number of Transformations per Augmentation: The number of transformations to compose into each augmentation. The default is 1. The input form will dynamically update to allow you to specify the parameters for each transformation.

  • Target View: The view to apply the augmentations to. The default is None, which will apply the augmentations to the entire dataset. Here are the options you will be able to choose between, depending on what you are viewing and/or have selected:

    • Dataset: Apply the augmentations to the entire dataset.
    • Current View: Apply the augmentations to the samples in the current view.
    • Selected Samples: Apply the augmentations to the selected samples.
  • Execution Mode: The execution mode to use when applying the augmentations. If you select delegated=True, the operation will be queued as a job, which you can then launch in the background from your terminal. The default is delegated=False, which will apply the augmentations immediately. For more information on FiftyOne's delegated operations, see here.

Choosing Transformations

Each of the transforms that is composed into the augmentation transformation can be selected from one of two sources:

  • Albumentations Primitives: These are the transformations that are provided by the Albumentations library. You can find the full list of available transformations here. All but a few of the transformations are supported by this plugin. When you select a transformation from this list, the input form will dynamically update to allow you to specify the parameters for the transformation. πŸ’‘ If you're curious, this is achieved through utilization of Python's inspect module, which provides access to docstrings and function signatures.
  • Saved Transformations: You can also select from a list of your saved transformations. This is useful if you find a set of hyperparameters that you like and want to save them for later use. For more information on saving transformations, see here.

Get Info About Last Transformation

get_last_run_info

When you apply an augmentation to your dataset with augment_with_albumentations, the operation will store a serialized version of the transformation in a custom run on your dataset. You can view the last transformation that was applied to your dataset by using the get_last_albumentations_run_info operator. This will open an output modal with a formatted snapshot of the last transformation that was applied to your dataset.

View Last Augmentation

view_last_augmentation

In addition to storing the last transformation that was applied to your dataset, the augment_with_albumentations operation will retain a reference list of all of the samples that were created by the last augmentation that was applied to your dataset. You can view the last augmentation that was applied to your dataset by using the view_last_albumentations_run operator.

Saving Transformations

save_transform

If you find a set of hyperparameters that you like and want to save them for later use, you can save the transformation that was applied to your dataset by using the save_albumentations_transform operator. You will be prompted to enter a name for the transformation β€” choose something that will help you remember what the transformation does.

Once you have saved the transformation, it will then be available to select from the Saved Transformations dropdown when you apply augmentations to your dataset.

πŸ’‘ You can only save the last transformation that was applied to your dataset. If you want to save a transformation that you applied to your dataset in the past, you will need to re-apply the transformation to your dataset and then save it.

Saving Augmentations

By default, each time a new augmentation is applied to your dataset, all of the samples that were created by the previous augmentation are removed from your dataset, and the temporary files that were created to store the samples are deleted.

If you find a set of augmentations that you like, you can persist them to your dataset by using the save_albumentations_augmentations operator.

Get Info About Saved Transformations

get_saved_info

You can view the transformations that have been saved to your dataset by using the get_albumentations_run_info operator and selecting the name of the transformation that you want info about from the dropdown.

Delete Saved Transformations

You can delete a saved transformation from your dataset by using the delete_albumentations_run operator and selecting the name of the transformation that you want to delete from the dropdown.

Cleanup Temporary Files

You can explicitly cleanup the temporary files that were created to store the samples that were created by the last augmentation that was applied to your dataset by using the cleanup_last_albumentations_run operator.

fiftyone-albumentations-plugin's People

Contributors

jacobmarks avatar

Stargazers

Harpreet Sahota avatar Andrei Popovici avatar Sergio Martinez avatar siddhant gulia avatar Haochen Miao avatar Jake Senior avatar Muhammad Ali avatar Vladimir Iglovikov avatar  avatar Brian Moore avatar  avatar

Watchers

 avatar Kostas Georgiou avatar  avatar siddhant gulia avatar

Forkers

npesc

fiftyone-albumentations-plugin's Issues

Can't enter more than one value for parameters that can take tuples

For MultiplicativeNoise it says:
If single float image will be multiplied to this number. If tuple of float multiplier will be in range [multiplier[0], multiplier[1]). Default (0.9, 1.1) but in the Multiplier Parameter I can only enter a number and therefore cannot provide a tuple for a custom range. This is the same for other parameters that use more than one value such as GaussNoise and CLAHE.

Found sample missing group field 'group'

Hi,

When trying out augmentations on samples that belong to a group, I stumbled upon this error:

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/fiftyone/operators/executor.py", line 277, in execute_or_delegate_operator
    result = await do_execute_operator(operator, ctx, exhaust=exhaust)
  File "/usr/local/lib/python3.10/dist-packages/fiftyone/operators/executor.py", line 319, in do_execute_operator
    result = await (
  File "/usr/local/lib/python3.10/dist-packages/fiftyone/core/utils.py", line 2343, in run_sync_task
    return await loop.run_in_executor(_get_sync_task_executor(), func, *args)
  File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/driveblocks/fiftyone/__plugins__/@jacobmarks/albumentations_augmentation/__init__.py", line 1106, in execute
    new_sample_id = transform_sample(sample, transforms, label_fields)
  File "/home/driveblocks/fiftyone/__plugins__/@jacobmarks/albumentations_augmentation/__init__.py", line 453, in transform_sample
    sample._dataset.add_sample(new_sample)
  File "/usr/local/lib/python3.10/dist-packages/fiftyone/core/dataset.py", line 2524, in add_sample
    ids = self._add_samples_batch(
  File "/usr/local/lib/python3.10/dist-packages/fiftyone/core/dataset.py", line 2646, in _add_samples_batch
    self._validate_samples(samples)
  File "/usr/local/lib/python3.10/dist-packages/fiftyone/core/dataset.py", line 7203, in _validate_samples
    raise ValueError(
ValueError: Found sample missing group field 'group'

This occurs when samples have a group field and we try to augment them. I think the error is raised because the group is not ported through the augmentation and that we would be adding a sample without group to a grouped dataset.

For this I have implemented at first, a fix that adds the group of the original sample to the augmented sample, with this the error doesn't occur anymore. However, after augmentation we can see both samples in the view but we cannot click on the augmented sample to view it separately. For this I have added a tickbox that when ticked, allows the user to "transform" the group, i.e., add a _augmented suffix to the group name on the augmented sample.

With this we can now augment grouped datasets and view augmented samples side by side with the original ones.

image

I have tested the changes locally and made a PR for this.

Thanks

Augment or View Albumentations is not applying/displaying transformation samples

Using most recent version:

Test Case: a custom dataset with object detection data and image classification, tried a few single transformations, including flip, blur, randomrotate etc.

After applying the transformation on 3 samples and setting the number of augmentations per sample (1-3), there are not transformation viewable in the dataset.

Additionally, executed the view_last_albumentations_run operator command and there are no samples.

conda list

Version info:

Name Version Build Channel

libopencv 4.9.0 headless_py311h18d748c_12 conda-forge
opencv 4.9.0 headless_py311h5151cf2_12 conda-forge
opencv-python 4.9.0.80 pypi_0 pypi
py-opencv 4.9.0 headless_py311h7e6d3fa_12 conda-forge
numpy 1.26.4 pypi_0 pypi

(tf_2.12) (base) leopimentel@XRXC65LQ69s-MacBook-Pro% pip show fiftyone
Name: fiftyone
Version: 0.23.8
Summary: FiftyOne: the open-source tool for building high-quality datasets and computer vision models
Home-page: https://github.com/voxel51/fiftyone
Author: Voxel51, Inc.
Author-email: info@voxel

Fiftyone exits after completing augmentations

I have been applying an augmentation to a dataset, and when the augmentation run completes the screen reloads to include the augmented images in the UI, the console says 'Process finished with exit code 0' and the browser page redirects and says that no session is running.

I am launching fiftyone with:
session = fo.launch_app(dataset, port=5151)
session.wait()

Version numbers:
Fifityone = 0.23.8
Plugin installed as per the readme instructions.

Performing an augmentation yields an error on cleanup

Steps to ### Recreate @jacobmarks

  1. Launch Augmentation operator in FiftyOne web app
  2. Select an augmentation e.g. emboss, equalize,
  3. Execute the augmentation on a sample set

Version info

In [6]: print(fo.version)
0.23.8

(tf_2.15) leopimentel@XRXC65LQ69s-MBP ~ % fiftyone plugins list
plugin version enabled directory


@voxel51/plugins 1.0.0 βœ“ /Users/leopimentel/fiftyone/plugins/@voxel51/plugins
@voxel51/delegated 1.0.0 βœ“ /Users/leopimentel/fiftyone/plugins/@voxel51/delegated
@voxel51/io 1.0.0 βœ“ /Users/leopimentel/fiftyone/plugins/@voxel51/io
@voxel51/annotation 1.0.0 βœ“ /Users/leopimentel/fiftyone/plugins/@voxel51/annotation
@voxel51/utils 1.0.0 βœ“ /Users/leopimentel/fiftyone/plugins/@voxel51/utils
@voxel51/hello-world 1.0.0 βœ“ /Users/leopimentel/fiftyone/plugins/@voxel51/hello-world
@voxel51/zoo 1.0.0 βœ“ /Users/leopimentel/fiftyone/plugins/@voxel51/zoo
@voxel51/examples 1.0.0 βœ“ /Users/leopimentel/fiftyone/plugins/@voxel51/examples
@voxel51/evaluation 1.0.0 βœ“ /Users/leopimentel/fiftyone/plugins/@voxel51/evaluation
@voxel51/brain 1.0.0 βœ“ /Users/leopimentel/fiftyone/plugins/@voxel51/brain
@voxel51/python-view 1.0.0 βœ“ /Users/leopimentel/fiftyone/plugins/@voxel51/python-view
@voxel51/runs 1.0.0 βœ“ /Users/leopimentel/fiftyone/plugins/@voxel51/runs
@voxel51/indexes 1.0.0 βœ“ /Users/leopimentel/fiftyone/plugins/@voxel51/indexes
@jacobmarks/albumentations_augmentation 1.0.7 βœ“ /Users/leopimentel/fiftyone/plugins/@jacobmarks/albumentations_augmentation

Error:

β–ΌError occurred during operator execution

Traceback (most recent call last):
File "/Users/leopimentel/mambaforge/envs/apple_tensorflow/envs/tf_2.15/lib/python3.11/site-packages/fiftyone/operators/executor.py", line 277, in execute_or_delegate_operator
result = await do_execute_operator(operator, ctx, exhaust=exhaust)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/leopimentel/mambaforge/envs/apple_tensorflow/envs/tf_2.15/lib/python3.11/site-packages/fiftyone/operators/executor.py", line 319, in do_execute_operator
result = await (
^^^^^^^
File "/Users/leopimentel/mambaforge/envs/apple_tensorflow/envs/tf_2.15/lib/python3.11/site-packages/fiftyone/core/utils.py", line 2317, in run_sync_task
return await loop.run_in_executor(_get_sync_task_executor(), func, *args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/leopimentel/mambaforge/envs/apple_tensorflow/envs/tf_2.15/lib/python3.11/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/leopimentel/fiftyone/plugins/@jacobmarks/albumentations_augmentation/init.py", line 1044, in execute
_cleanup_last_transform(ctx.dataset)
File "/Users/leopimentel/fiftyone/plugins/@jacobmarks/albumentations_augmentation/init.py", line 788, in _cleanup_last_transform
os.remove(fp)
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/dad5fc1ad2.jpg'

ValueError: Key keypoint_labels is not in available keys.

Hi Jacob,

I've encountered an issue trying to use ZoomBlur on my object detection dataset. This same error also shows up for RandomBBoxSafeCrop.

β–ΌError occurred during operator execution

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/dist-packages/fiftyone/operators/executor.py", line 277, in execute_or_delegate_operator
    result = await do_execute_operator(operator, ctx, exhaust=exhaust)
  File "/usr/local/lib/python3.8/dist-packages/fiftyone/operators/executor.py", line 319, in do_execute_operator
    result = await (
  File "/usr/local/lib/python3.8/dist-packages/fiftyone/core/utils.py", line 2317, in run_sync_task
    return await loop.run_in_executor(_get_sync_task_executor(), func, *args)
  File "/usr/lib/python3.8/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/root/fiftyone/__plugins__/@jacobmarks/albumentations_augmentation/__init__.py", line 1100, in execute
    new_sample_id = transform_sample(sample, transforms, label_fields)
  File "/root/fiftyone/__plugins__/@jacobmarks/albumentations_augmentation/__init__.py", line 387, in transform_sample
    transformed = transform(**kwargs)
  File "/usr/local/lib/python3.8/dist-packages/albumentations/core/composition.py", line 528, in __call__
    result = super().__call__(force_apply=force_apply, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/albumentations/core/composition.py", line 247, in __call__
    self._check_args(**data)
  File "/usr/local/lib/python3.8/dist-packages/albumentations/core/composition.py", line 316, in _check_args
    raise ValueError(msg)
ValueError: Key keypoint_labels is not in available keys.

Ability to Apply Crop Augmentation on selected classes

Hi there,
Thanks for this amazing plugin.

Recently, I came across the problem of under-represented classes in an instance segmentation dataset. And it posed such problem, eg if I am labeling house objects, and stairs-bannisters , wall-painting are classes. Now, if I simply increase images, bannisters also increase exponentially,
But on the otherhand, if I can augment the dataset with flixibilty of Cropping only around the wall-painting class, I can reduce this data-imbalance by some extent..

So, can we do this currently,

Thanks

Keypoint conversion to albumentations out of bounds

Hi,

When experimenting with the plugin for keypoints augmentation I came across a value error, here is the full trace:

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/fiftyone/operators/executor.py", line 277, in execute_or_delegate_operator
    result = await do_execute_operator(operator, ctx, exhaust=exhaust)
  File "/usr/local/lib/python3.10/dist-packages/fiftyone/operators/executor.py", line 319, in do_execute_operator
    result = await (
  File "/usr/local/lib/python3.10/dist-packages/fiftyone/core/utils.py", line 2343, in run_sync_task
    return await loop.run_in_executor(_get_sync_task_executor(), func, *args)
  File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/driveblocks/fiftyone/__plugins__/@jacobmarks/albumentations_augmentation/__init__.py", line 1106, in execute
    new_sample_id = transform_sample(sample, transforms, label_fields)
  File "/home/driveblocks/fiftyone/__plugins__/@jacobmarks/albumentations_augmentation/__init__.py", line 388, in transform_sample
    transformed = transform(**kwargs)
  File "/home/driveblocks/.local/lib/python3.10/site-packages/albumentations/core/composition.py", line 578, in __call__
    result = super().__call__(force_apply=force_apply, **kwargs)
  File "/home/driveblocks/.local/lib/python3.10/site-packages/albumentations/core/composition.py", line 304, in __call__
    self.preprocess(data)
  File "/home/driveblocks/.local/lib/python3.10/site-packages/albumentations/core/composition.py", line 338, in preprocess
    p.preprocess(data)
  File "/home/driveblocks/.local/lib/python3.10/site-packages/albumentations/core/utils.py", line 90, in preprocess
    data[data_name] = self.check_and_convert(data[data_name], rows, cols, direction="to")
  File "/home/driveblocks/.local/lib/python3.10/site-packages/albumentations/core/utils.py", line 104, in check_and_convert
    return self.convert_to_albumentations(data, rows, cols)
  File "/home/driveblocks/.local/lib/python3.10/site-packages/albumentations/core/keypoints_utils.py", line 130, in convert_to_albumentations
    return convert_keypoints_to_albumentations(
  File "/home/driveblocks/.local/lib/python3.10/site-packages/albumentations/core/keypoints_utils.py", line 260, in convert_keypoints_to_albumentations
    return [
  File "/home/driveblocks/.local/lib/python3.10/site-packages/albumentations/core/keypoints_utils.py", line 261, in <listcomp>
    convert_keypoint_to_albumentations(kp, source_format, rows, cols, check_validity, angle_in_degrees)
  File "/home/driveblocks/.local/lib/python3.10/site-packages/albumentations/core/keypoints_utils.py", line 214, in convert_keypoint_to_albumentations
    check_keypoint(keypoint, rows, cols)
  File "/home/driveblocks/.local/lib/python3.10/site-packages/albumentations/core/keypoints_utils.py", line 144, in check_keypoint
    raise ValueError(f"Expected {name} for keypoint {kp} to be in the range [0.0, {size}], got {value}.")
ValueError: Expected y for keypoint (3036, 2168, 0.0, 0.0, '66bca79a1cb1b8b86ba45936_2') to be in the range [0.0, 2168], got 2168.

The check is done in this function github/albumentations/core/keypoints_utils.py. It expects a value in the range of [0, size of image[.

With the current implementation fiftyone-albumentations-plugin/utils.py it is possible that the converted value lands outside of the range, this happens when the keypoint has one coordinate that is equal to 1.0.

To mitigate this, instead of multiplying by the size of the image, we can multiply by the size minus one.

I have forked the repo, added and tested the fix locally.

Thanks

How can I specify the border mode for Padifneeded?

Hi Jacob,

Thanks for your work on these plugins and your fix for Padifneeded. I was hoping to use the padding mode of cv2.BORDER_CONSTANT, but it seems like even if I set the pad value = 0, it will still apply the default border mode cv2.BORDER_REFLECT_101. Is there a way to explicitly set the border_mode from the UI fields?

Would also be great if we could set the position parameter in the albumentations function.

keypoints_params must be specified error

I can't seem to get this plugin to work without getting this error. I copied this code from the getting started section and accessed the albumentations plugin from the web ui. Am I doing something wrong?

import fiftyone as fo
import fiftyone.zoo as foz

dataset = foz.load_zoo_dataset("quickstart", max_samples=5)

# only keep the ground truth labels
dataset.select_fields("ground_truth").keep_fields()

session = fo.launch_app(dataset)
session.wait()

Error:

Traceback (most recent call last):
  File "/usr/local/lib/python3.12/site-packages/fiftyone/operators/executor.py", line 277, in execute_or_delegate_operator
    result = await do_execute_operator(operator, ctx, exhaust=exhaust)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/fiftyone/operators/executor.py", line 319, in do_execute_operator
    result = await (
             ^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/fiftyone/core/utils.py", line 2317, in run_sync_task
    return await loop.run_in_executor(_get_sync_task_executor(), func, *args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/fiftyone/__plugins__/@jacobmarks/albumentations_augmentation/__init__.py", line 1032, in execute
    new_sample_id = transform_sample(sample, transforms, label_fields)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/fiftyone/__plugins__/@jacobmarks/albumentations_augmentation/__init__.py", line 357, in transform_sample
    transformed = transform(**kwargs)
                  ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/albumentations/core/composition.py", line 499, in __call__
    result = super().__call__(force_apply=force_apply, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/albumentations/core/composition.py", line 215, in __call__
    self._check_args(**data)
  File "/usr/local/lib/python3.12/site-packages/albumentations/core/composition.py", line 304, in _check_args
    raise ValueError(msg)
ValueError: keypoints_params must be specified for keypoint transformations

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.