How to Augmentate Data Using Keras | by Ravindu Senaratne | Towards Data Science

Data Augmentation is very useful if you would like to augment your data or increase the amount of training or validation data. For example, If you have 2000 images and you would like to get 5000 or 10000 of those then this can be very useful.
But if you have 5 or 10 images, don’t expect to get 2000 or 10000 images from data augmentation and still be able to get a decent result out of your deep learning model. Because the deep learning model will be highly biased towards these 5 or 10 images.
If you have less than 100 images I would recommend using traditional machine learning
from keras.preprocessing.image import ImageDataGeneratorfrom skimage import iodatagen = ImageDataGenerator(                    rotation_range=45,            width_shift_range=0.2,              height_shift_range=0.2,                shear_range=0.2,                    zoom_range=0.2,                    horizontal_flip=True,                     fill_mode='constant', cval=125)x = io.imread('test_image/test.jpg')x = x.reshape((1, ) + x.shape)i = 0for batch in datagen.flow(x, batch_size=16,                          save_to_dir='augmented',                          save_prefix='aug',                          save_format='png'):      i += 1      if i > 20:             break
The library we need for data augmentation is ImageDataGenerator of Keras. To read a single image I’ve also imported io from skimage. First, we need to create an instance for the data generator. The way you do that is creating a variable called datagen (you can put any name you like) and equal it to ImageDataGenerator with internal arguments.
rotation_range=45 means I want to randomly rotate my image between 0 and 45 degrees. width_shift_range=0.2 and height_shift_range=0.2 means shift the image along X-axis by 20% and Y-axis by 20%. shear_range=0.2 means shear the image by 20%. zoom_range means zoom-in and zoom-out by 20%. For mirror reflection, I have given horizontal_flip=True. The most important argument of ImageDataGenerator is fill_mode. When your image shift by 20% there is some space left over. You can select a few types of methods to fill the area,
constant — Which will fill the area in black color. You can change the color by giving a value for cval
nearest — Which will fill the area with the nearest pixel and stretching it.
reflect — Which will fill the area with the reflection of the image.
wrap — Which will fill the area by wrapping the image around it.
After that using, io.read we can read an image. After reading the image you can see that the image is (256, 256, 3) after reshaping it you can see the image as (1, 256, 256, 3) because when we go into convolutional layers input size is typically the first one is the number of images. Secondly the dimension and lastly the color scheme.
The way we apply the instancedatagen is using datagen.flow. Here we are using .flow because there is only one image. batch_size=16 means it’s generating or augmenting 16 images and save the images in augmented folder. Since the datagen is in a finite loop we need to use a for-loop and break it once it reaches 20 images. ( Similar toepochs)
Now we know how it works let’s look at examples of different fill_mode,
from keras.preprocessing.image import ImageDataGeneratorfrom skimage import iodatagen = ImageDataGenerator(                    rotation_range=45,            width_shift_range=0.2,              height_shift_range=0.2,                shear_range=0.2,                    zoom_range=0.2,                    horizontal_flip=True,                     fill_mode='reflect')import numpy as npimport osfrom PIL import Imageimage_directory = 'test_folder/'SIZE = 128dataset = []my_images = os.listdir(image_directory)for i, image_name in enumerate(my_images):       if (image_name.split('.')[1] == 'jpg'):               image = io.imread(image_directory + image_name)               image = Image.fromarray(image, 'RGB')               image = image.resize((SIZE,SIZE))        dataset.append(np.array(image))x = np.array(dataset)i = 0for batch in datagen.flow(x, batch_size=16,                          save_to_dir='augmented',                          save_prefix='aug',                          save_format='png'):      i += 1      if i > 20:             break
I have to define SIZE = 128 because no matter what your image size is we can resize it to a common size. To read all the images I’m going to enumerate it using a for-loop. For each image, we have to split it at .jpg. Finally, the resized images will be added to the array. We can do the rest as we have done above. Now we have both test1.jpg and test2.jpg.
Multi-class is what you would expect in most classes. Now I’ve put each image according to their classes because that’s how this data would represent in a dataset. Using datagen.flow_from_directory is going to read images inside sub-folders separately. For example, If you have classes like cats, dogs, cars, etc. then put all those images in their corresponding folders.
i = 0for batch in datagen.flow_from_directory(directory='test_folder/',                                          batch_size=16,                                          target_size=(256, 256),                                             color_mode="rgb",                                               save_to_dir='augmented',                                             save_prefix='aug',                                              save_format='png'):       i += 1       if i > 31:             break
That is it for the article. I hope you learn something new. Thank you and stay safe!