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

Chance of no augmentation being applied #109

Open
CMCDragonkai opened this issue Mar 20, 2018 · 5 comments
Open

Chance of no augmentation being applied #109

CMCDragonkai opened this issue Mar 20, 2018 · 5 comments

Comments

@CMCDragonkai
Copy link

CMCDragonkai commented Mar 20, 2018

It seems there's always a chance of no augmentation applied. Is it possible to make sure that at least 1 random augmentation is applied?

@aleju
Copy link
Owner

aleju commented Mar 20, 2018

iaa.SomeOf((1, 3), [iaa.Dropout(...), iaa.Affine(...), iaa.AdditiveGaussianNoise()])

would always apply 1 to 3 of the 3 augmenters (i.e. at least one).

iaa.OneOf([iaa.Dropout(...), iaa.Affine(...), iaa.AdditiveGaussianNoise()])

always applies exactly 1 of the 3 augmenters.

iaa.Sequential([iaa.Dropout(...), iaa.Affine(...), iaa.AdditiveGaussianNoise()])

always apply 3 of the 3 augmenters.

If you use Sometimes or augmenters with probabilities (e.g. Invert), there is always a small chance that none of them will be applied. This can currently only be avoided if you add some other augmenters of which at least one is always applied (using above methods).

@CMCDragonkai
Copy link
Author

CMCDragonkai commented Mar 4, 2019

I've taken your advice, but I've detected that no augmentation can still happen with:

iaa.SomeOf((1, None) ...)

Everything else works, except after checking the output augmentations, I found no augmentation was applied to one specific image. This image is nothing special. Testing in isolation allowed me to augment the image normally. It's just as I used it a batch of many images, a single image kept not being augmented.

I created an "augmentation schema" which I apply:

{
  "augs": [{
      "type": "Fliplr",
      "args": [1.0]
    },
    {
      "type": "Flipud",
      "args": [1.0]
    },
    {
      "type": "CropAndPad",
      "kwargs": {
        "percent": [-0.25, 0.25],
        "pad_mode": "constant"
      }
    },
    {
      "type": "Multiply",
      "args": [
        [0.9, 1.1]
      ],
      "kwargs": {
        "per_channel": 0.5,
        "name": "Multiply"
      }
    },
    {
      "type": "GaussianBlur",
      "kwargs": {
        "sigma": [0, 0.1],
        "name": "GaussianBlur"
      }
    },
    {
      "type": "AdditiveGaussianNoise",
      "kwargs": {
        "scale": [0, 5.1],
        "per_channel": true,
        "name": "AdditiveGaussianNoise"
      }
    },
    {
      "type": "Affine",
      "kwargs": {
        "scale": {
          "x": [0.8, 1.2],
          "y": [0.8, 1.2]
        },
        "translate_percent": {
          "x": [-0.2, 0.2],
          "y": [-0.2, 0.2]
        },
        "rotate": [-50, 50],
        "shear": [-8, 8],
        "order": 3,
        "mode": "constant"
      }
    }
  ],
  "mask_filter": ["Multiply", "GaussianBlur", "AdditiveGaussianNoise"]
}
def parse_aug_config(config_file):
    aug_config = json.load(config_file, cls=AugmentationDecoder)
    augs = []
    for aug in aug_config['augs']:
        aug_constructor = getattr(iaa, aug['type'])
        aug_args = aug.get('args', [])
        aug_kwargs = aug.get('kwargs', {})
        augs.append(aug_constructor(*aug_args, **aug_kwargs))
    augs_mask_filter = aug_config['mask_filter']
    aug_pipeline_template = iaa.SomeOf((1, None), augs, random_order=True)

    def masks_activator(images, augmenter, parents, default):
        if augmenter.name in augs_mask_filter:
            return False
        else:
            return default

    masks_hook = ia.HooksImages(activator=masks_activator)
    return (aug_pipeline_template, masks_hook)
def augment_image_mask(image, mask, aug_pipeline_template, masks_hook):
    aug_pipeline = aug_pipeline_template.to_deterministic()
    if mask is not None:
        (image_aug, *_) = aug_pipeline.augment_images(np.array([image]))
        (mask_aug, *_) = aug_pipeline.augment_images(
            np.array([mask]), hooks=masks_hook)
    else:
        (image_aug, *_) = aug_pipeline.augment_images(np.array([image]))
        mask_aug = None
    return (image_aug, mask_aug)

I'm running imgaug 0.2.6.

Are you sure there's no way that iaa.SomeOf especially with the augmentations that I'm using that 0 augmentations may be applied?

@aleju
Copy link
Owner

aleju commented Mar 4, 2019

Your json code contains a lot of lists for parameter ranges, e.g. "sigma": [0, 0.1]. These are parsed by json.load as lists and provided to the augmenter constructors without changes. The augmenters then interpret these parameters as lists of allowed values and pick randomly from these lists. So for the above sigma example you would get either 0 or 0.1 sampled, but not anything in between. To get a uniform distribution, you have to provide either (0, 0.1) (i.e. a tuple) or imgaug.parameters.Uniform(0, 0.1) as a parameter.
There is of course also a chance that a uniform distribution randomly sampled 0 or 0.1.

btw

(image_aug, *_) = aug_pipeline.augment_images(np.array([image]))

can probably be replaced by

image_aug = aug_pipeline.augment_image(np.array([image]))

@CMCDragonkai
Copy link
Author

Oh... well JSON only has lists, I wonder what's a good way to integrate the difference between lists and tuples in our augmentation schema.

@CMCDragonkai
Copy link
Author

I think the best way for now is always interpret the lists as tuples, as that was what I originally was doing before I extracted the code into a JSON schema.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants