albumentations icon indicating copy to clipboard operation
albumentations copied to clipboard

Error when using replay with Lambda

Open ColaWithIce opened this issue 3 years ago • 5 comments

Here is my code:

def toGray(image, **params):
    gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
    return gray

transform_A = A.ReplayCompose([
    A.Lambda(name='togray',image=toGray),
    A.Resize(256,256),
    A.HorizontalFlip(p=0.5),
    A.ShiftScaleRotate(shift_limit=0.1, scale_limit=0.2, rotate_limit=30, p=0.5, border_mode=cv2.BORDER_CONSTANT),
    A.RandomBrightnessContrast(p=0.5),
    A.Normalize((0.5,),(0.5,), always_apply=True),
    ToTensorV2()
])

re_param = transform_A(image=image)['replay']
transform_A.replay(re_param,image=image)

The error occured,

Traceback (most recent call last):
  File "/home//pycharm-community-2021.2.1/plugins/python-ce/helpers/pydev/_pydevd_bundle/pydevd_exec2.py", line 3, in Exec
    exec(exp, global_vars, local_vars)
  File "<input>", line 1, in <module>
  File "/home//miniconda3/envs/pytorch/lib/python3.6/site-packages/albumentations/core/composition.py", line 400, in replay
    augs = ReplayCompose._restore_for_replay(saved_augmentations)
  File "/home//miniconda3/envs/pytorch/lib/python3.6/site-packages/albumentations/core/composition.py", line 427, in _restore_for_replay
    for t in args["transforms"]
  File "/home//miniconda3/envs/pytorch/lib/python3.6/site-packages/albumentations/core/composition.py", line 427, in <listcomp>
    for t in args["transforms"]
  File "/home//miniconda3/envs/pytorch/lib/python3.6/site-packages/albumentations/core/composition.py", line 417, in _restore_for_replay
    lmbd = instantiate_lambda(transform, lambda_transforms)
  File "/home//miniconda3/envs/pytorch/lib/python3.6/site-packages/albumentations/core/serialization.py", line 88, in instantiate_lambda
    "as the `lambda_transforms` argument".format(name=name)
ValueError: To deserialize a Lambda transform with name togray you need to pass a dict with this transform as the `lambda_transforms` argument

Dose anyone have any suggestions?

ColaWithIce avatar Nov 19 '21 17:11 ColaWithIce

I'm not familiar with the ReplayCompose, but judging from the source code and the error message, I think a workaround is to use the _restore_for_replay method.

re_param = transform_A(image=image)['replay']
lambda_transforms = {lam.name : lam for lam in transform_A if isinstance(lam, A.Lambda)}
augs = transform_A._restore_for_replay(re_param, lambda_transforms=lambda_transforms)
augs(force_apply=True, image=image)

The replay(...) method is a simple wrapper of the _restore_for_replay(...), and the workaround code is almost the same as replay(), but the differences are the lambda_transforms is prepared from the original transform pipeline and pass it to the _restore_for_replay(...).

https://github.com/albumentations-team/albumentations/blob/6de7dd01410a666c23c70cf69c548f171c94a1a7/albumentations/core/composition.py#L432-L435

i-aki-y avatar Nov 24 '21 07:11 i-aki-y

Thanks for reporting this bug. Yes, looks like now ReplayCompose works incorrectly with Lambda.

Dipet avatar Nov 24 '21 07:11 Dipet

I'm having the same issue as @ColaWithIce [and the workaround suggested by @i-aki-y is not working]. Any news regarding this bug? Thanks.

lilianabrandao avatar Mar 13 '23 12:03 lilianabrandao

@lilianabrandao My workaround looks to be working in Colab. What pipeline did you use? The code I tried is here

import torch
import numpy as np
import albumentations as A
from albumentations.pytorch.transforms import ToTensorV2
import cv2

def toGray(image, **params):
    gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
    return gray

transform_A = A.ReplayCompose([
    A.Lambda(name='togray',image=toGray),
    A.Resize(256,256),
    A.HorizontalFlip(p=0.5),
    A.ShiftScaleRotate(shift_limit=0.1, scale_limit=0.2, rotate_limit=30, p=0.5, border_mode=cv2.BORDER_CONSTANT),
    A.RandomBrightnessContrast(p=0.5),
    A.Normalize((0.5,),(0.5,), always_apply=True),
    ToTensorV2()
])

image = np.random.randint(0, 256, size=(100, 100, 3), dtype=np.uint8)

re_param = transform_A(image=image)['replay']
lambda_transforms = {lam.name : lam for lam in transform_A if isinstance(lam, A.Lambda)}
augs = transform_A._restore_for_replay(re_param, lambda_transforms=lambda_transforms)
augs(force_apply=True, image=image)

# re_param = transform_A(image=image)['replay']
# transform_A.replay(re_param,image=image)

i-aki-y avatar Mar 15 '23 13:03 i-aki-y

Is there a way to use replay_param for lambda transform?

Devoe-97 avatar Apr 07 '24 08:04 Devoe-97