keras-preprocessing icon indicating copy to clipboard operation
keras-preprocessing copied to clipboard

channel_shift_range not affecting images?

Open Mahi-Mai opened this issue 5 years ago • 10 comments

So, I've decided adding random channel shift would be an important image augmentation for my training set. But when I test the output, I'm not seeing any changes no matter if I set channel_shift_range to 0.1 or 0.9. Am I misunderstanding how this augmentation works? I thought it was supposed to shift the colors around so the model would be robust to variances in color?

Here's my code:

from keras.preprocessing.image import ImageDataGenerator

import cv2
import matplotlib.pyplot as plt
%matplotlib inline

path = '/mnt/Project/Imaging/samples'

datagen = ImageDataGenerator(brightness_range=(0.25,1.35), channel_shift_range=0.9)

genObject = datagen.flow_from_directory(path,
                                        batch_size=1)

augs = []
i = 0

for batch in genObject:
    augs.append(batch)
    i += 1
    if i > 10:
        break
        
for item in augs:
    plt.imshow(item[0][0].astype('uint8'))
    plt.show()

Environment: Jupyter Lab Python 3.6.6 Keras==2.2.4 Keras-Applications==1.0.7 Keras-Preprocessing==1.0.9 tensorboard==1.9.0 tensorflow-gpu==1.9.0

Thanks in advance for the help!

Mahi-Mai avatar Jul 01 '19 16:07 Mahi-Mai

I think there was a mistake with the code. If you input some large value like 200.0, it will produce real channel shifts like mentioned here under "Old Channel_Shift Images(cifar10)": https://github.com/keras-team/keras-preprocessing/issues/17

However, it should be using a float between 0 and 1 rather than a large absolute value.

jingprism avatar Aug 22 '19 21:08 jingprism

Actually it used to work with that workaround in a previous version of keras, but not anymore. I looked through the code: https://github.com/keras-team/keras-preprocessing/blob/095aea9a029d52af618f3b1e8a4f93ef83f51d91/keras_preprocessing/image/image_data_generator.py#L872 https://github.com/keras-team/keras-preprocessing/blob/095aea9a029d52af618f3b1e8a4f93ef83f51d91/keras_preprocessing/image/affine_transformations.py#L159

And tried using the apply_channel_shift on two different simple arrays:

arr = np.array([[[50,100,200],[50,100,200]], [[50,100,200],[50,100,200]]])
arr = np.array([[[50,50], [50,50]], [[100,100], [100,100]], [[200,200], [200,200]]])
apply_channel_shift(arr, 50.0, 0)

which results in:

array([[[100., 150., 200.],
        [100., 150., 200.]],
       [[100., 150., 200.],
        [100., 150., 200.]]])

or

array([[[100., 100.],
        [100., 100.]],
       [[150., 150.],
        [150., 150.]],
       [[200., 200.],
        [200., 200.]]])

No matter what channel_axis I use as a parameter

jingprism avatar Aug 23 '19 20:08 jingprism

This will be added to the list of issues needed to be fixed when we will work on the refactoring. (See https://github.com/keras-team/governance/pull/10 for updates)

Dref360 avatar Sep 20 '19 15:09 Dref360

It looks like 'channel_shift_range` adds/subtracts the same intensity from all channels in the image. So because of that the image just becomes brighter or darker instead of changing color. I imagine the expected behavior would be to change color too, no? In that case, we need to add different intensity to different channels.

    x = np.rollaxis(x, channel_axis, 0)
    min_x, max_x = np.min(x), np.max(x)
    channel_images = [
        np.clip(x_channel + intensity,
                min_x,
                max_x)
        for x_channel in x]
    x = np.stack(channel_images, axis=0)
    x = np.rollaxis(x, 0, channel_axis + 1)
    return x

mazatov avatar Dec 13 '19 19:12 mazatov

I am still observing the same behavior. https://github.com/keras-team/governance/pull/10 is merged. Is someone looking into this?

For reference: The code mazatov cited is found here https://github.com/keras-team/keras-preprocessing/blob/0494094a3ba341a67fdb9960e326fe6b9f582708/keras_preprocessing/image/affine_transformations.py#L159-L180

I am not familiar with some of the numpy methods, but I could look into finding a fix.

BSVogler avatar Jan 07 '20 17:01 BSVogler

A fix should probably also address issue #170.

BSVogler avatar Jan 09 '20 17:01 BSVogler

It works in a [0.0,255.0] range but instead of random channel shift i.e. r+20, g-10, b+3, it just applies random brightness: r+5, g+5,b+5 (shifting all channels by the same value).

apatsekin avatar Jan 18 '20 01:01 apatsekin

I put a fix on a fork. Still needs to be tested before I add a pull request. There is also some clipping to the min and max values contained in the channel. I do not understand the point of clipping to these min and max values. As noted in #170 is should probably clip to maximum allowed range for that data type. Further discussion about that in #170.

BSVogler avatar Jan 18 '20 11:01 BSVogler

Has this problem solved yet? I checked @BSVogler 's fork mentioned before, but there's error about the np.random.uniform() function in the code (Line 206 in affine_transformations.py). Seems there's no parameters named channel anymore now.

Have you re-wrote the np.random.uniform function? how you write it?

nina-weng avatar May 17 '21 21:05 nina-weng

I am sorry, I kinda forgot about this one. My fork needs to resolve the conflicts and probably update the usage of numpy since it has been more than a year.

BSVogler avatar May 18 '21 14:05 BSVogler