In [221]:
import numpy as np

In [222]:
import matplotlib.pyplot as plt

In [223]:
from PIL import Image

In [225]:
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img

In [226]:
img =  load_img('/usr/not-backed-up/temp/NYU/images/0000.png')

In [227]:
npimg = img_to_array(img)

In [228]:
npimg = npimg.reshape((1,) + npimg.shape)

In [231]:
datagen = ImageDataGenerator(
    channel_shift_range=10,
    horizontal_flip=True,
    preprocessing_function=augment
    )

In [232]:
i = 0;
nrows = 6;
ncols = 3;
fig, axes = plt.subplots(nrows, ncols,figsize=(20,20))
for batch in datagen.flow(npimg, batch_size=1):
    i += 1;
    plt.subplot(nrows,ncols,i)
    plt.imshow(array_to_img(batch[0]))
    if i == nrows*ncols:
        break
plt.show()


---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-232-095a869f2360> in <module>()
      3 ncols = 3;
      4 fig, axes = plt.subplots(nrows, ncols,figsize=(20,20))
----> 5 for batch in datagen.flow(npimg, batch_size=1):
      6     i += 1;
      7     plt.subplot(nrows,ncols,i)

/usr/not-backed-up/anaconda/lib/python3.6/site-packages/keras/preprocessing/image.py in __next__(self, *args, **kwargs)
    735 
    736     def __next__(self, *args, **kwargs):
--> 737         return self.next(*args, **kwargs)
    738 
    739 

/usr/not-backed-up/anaconda/lib/python3.6/site-packages/keras/preprocessing/image.py in next(self)
    814             x = self.image_data_generator.random_transform(x.astype(K.floatx()))
    815             x = self.image_data_generator.standardize(x)
--> 816             batch_x[i] = x
    817         if self.save_to_dir:
    818             for i in range(current_batch_size):

ValueError: could not broadcast input array from shape (240,320,3) into shape (427,561,3)

In [16]:
import scipy.ndimage as ndi

def random_rotation(x, rg, row_axis=0, col_axis=1, channel_axis=2,
                    fill_mode='nearest', cval=0., order=3):
    """Performs a random rotation of a Numpy image tensor.
    # Arguments
        x: Input tensor. Must be 3D.
        rg: Rotation range, in degrees.
        row_axis: Index of axis for rows in the input tensor.
        col_axis: Index of axis for columns in the input tensor.
        channel_axis: Index of axis for channels in the input tensor.
        fill_mode: Points outside the boundaries of the input
            are filled according to the given mode
            (one of `{'constant', 'nearest', 'reflect', 'wrap'}`).
        cval: Value used for points outside the boundaries
            of the input if `mode='constant'`.
        order: The order of the spline interpolation, default is 3. 
            The order has to be in the range 0-5.
    # Returns
        Rotated Numpy image tensor.
    """
    theta = np.pi / 180 * np.random.uniform(-rg, rg)
    rotation_matrix = np.array([[np.cos(theta), -np.sin(theta), 0],
                                [np.sin(theta), np.cos(theta), 0],
                                [0, 0, 1]])

    h, w = x.shape[row_axis], x.shape[col_axis]
    transform_matrix = transform_matrix_offset_center(rotation_matrix, h, w)
    x = apply_transform(x, transform_matrix, channel_axis, fill_mode, cval, order)
    return x

def transform_matrix_offset_center(matrix, x, y):
    o_x = float(x) / 2 + 0.5
    o_y = float(y) / 2 + 0.5
    offset_matrix = np.array([[1, 0, o_x], [0, 1, o_y], [0, 0, 1]])
    reset_matrix = np.array([[1, 0, -o_x], [0, 1, -o_y], [0, 0, 1]])
    transform_matrix = np.dot(np.dot(offset_matrix, matrix), reset_matrix)
    return transform_matrix

def apply_transform(x,
                    transform_matrix,
                    channel_axis=0,
                    fill_mode='nearest',
                    cval=0.,
                    order = 3):
    """Apply the image transformation specified by a matrix.
    # Arguments
        x: 2D numpy array, single image.
        transform_matrix: Numpy array specifying the geometric transformation.
        channel_axis: Index of axis for channels in the input tensor.
        fill_mode: Points outside the boundaries of the input
            are filled according to the given mode
            (one of `{'constant', 'nearest', 'reflect', 'wrap'}`).
        cval: Value used for points outside the boundaries
            of the input if `mode='constant'`.
        order: The order of the spline interpolation, default is 3. 
            The order has to be in the range 0-5.
    # Returns
        The transformed version of the input.
    """
    x = np.rollaxis(x, channel_axis, 0)
    final_affine_matrix = transform_matrix[:2, :2]
    final_offset = transform_matrix[:2, 2]
    channel_images = [ndi.interpolation.affine_transform(
        x_channel,
        final_affine_matrix,
        final_offset,
        order=order,
        mode=fill_mode,
        cval=cval) for x_channel in x]
    x = np.stack(channel_images, axis=0)
    x = np.rollaxis(x, 0, channel_axis + 1)
    return x

In [129]:
from math import ceil
def random_resize(npimg, minwidth=320, minheight=240, resample=Image.BICUBIC):
    """Returns a random resized copy of a Numpy image tensor.
    # Arguments
        npimg: Input tensor. Must be 3D.
        minwidth: Minimum width of resized image.
        minheight: Minimum height of resized image.
        resample: An optional resampling filter. 
            This can be one of PIL.Image.NEAREST, PIL.Image.BOX, PIL.Image.BILINEAR,
            PIL.Image.HAMMING, PIL.Image.BICUBIC or PIL.Image.LANCZOS. 
            If omitted, it is set PIL.Image.BICUBIC.
    # Returns
        Resized Numpy image tensor.
    """
    img = array_to_img(npimg)
    smallestResizeFactor = max(ceil((minwidth / img.size[0])*100) , ceil((minheight / img.size[1])*100))
    resizeFactor = 0.01 * np.random.randint(smallestResizeFactor,140) # In range of [Min_Width_Height, 1.4*original_size] 
    img = img.resize((int(img.size[0]*resizeFactor),int(img.size[1]*resizeFactor)),resample=resample)
    return img_to_array(img)

In [128]:
from keras import backend as K

def random_crop(npimg, width=320, height=240, data_format=None):
    """Returns a random cropped copy of a Numpy image tensor.
    # Arguments
        npimg: Input tensor. Must be 3D.
        width: width of crop region.
        height: height of crop region.
        data_format: Image data format. One of "channels_first" or "channels_last"
    # Returns
        Cropped Numpy image tensor.
    """
    if npimg.ndim != 3:
        raise ValueError('Expected image array to have rank 3 (single image). '
                         'Got array with shape:', npimg.shape)

    if data_format is None:
        data_format = K.image_data_format()
    if data_format not in {'channels_first', 'channels_last'}:
        raise ValueError('Invalid data_format:', data_format)

    # Original Numpy array x has format (height, width, channel)
    # or (channel, height, width)
    if data_format == 'channels_first':
        npimg = npimg.transpose(1, 2, 0)
    
    maxHeightIndex = npimg.shape[0] - height
    heightIndex = np.random.randint(0,maxHeightIndex)
    
    maxWidthIndex = npimg.shape[1] - width
    widthIndex = np.random.randint(0,maxWidthIndex)
    
    crop = npimg[heightIndex:heightIndex+height,widthIndex:widthIndex+width,:]
    
    if data_format == 'channels_first':
        crop = crop.transpose(2, 0, 1)
    
    return crop

In [255]:
np.random.seed(2)
array_to_img(augment(npimg[0]))


Out[255]:

In [67]:
from PIL import ImageEnhance as IE

In [88]:
IE.Sharpness(img).enhance(2)


Out[88]:

In [206]:
def augment(npimg):
    return random_crop((random_rotation(random_resize(npimg),5)))

In [ ]: