sudo-paras-shah's picture
Remove async limitations
e916c8e
import math
from random import shuffle
import cv2
import tensorflow as tf
import numpy as np
from keras.utils import to_categorical
from PIL import Image
from .utils import cvtColor, preprocess_input
class ClsDatasets(keras.utils.Sequence):
def __init__(self, annotation_lines, input_shape, batch_size, num_classes, train, **kwargs):
super().__init__()
self.annotation_lines = annotation_lines
self.length = len(self.annotation_lines)
self.input_shape = input_shape
self.batch_size = batch_size
self.num_classes = num_classes
self.train = train
def __len__(self):
return int(math.ceil(self.length / float(self.batch_size)))
def __getitem__(self, index):
X_train = []
Y_train = []
start = index * self.batch_size
end = min((index + 1) * self.batch_size, self.length)
for i in range(start, end):
annotation_path = self.annotation_lines[i].split(';')[1].split()[0]
image = Image.open(annotation_path)
image = self.get_random_data(image, self.input_shape, random=self.train)
image = preprocess_input(np.array(image).astype(np.float32))
X_train.append(image)
Y_train.append(int(self.annotation_lines[i].split(';')[0]))
X_train = np.array(X_train)
Y_train = to_categorical(np.array(Y_train), num_classes = self.num_classes)
return X_train, Y_train
def on_epoch_end(self):
if self.train:
np.random.shuffle(self.annotation_lines)
def rand(self, a=0, b=1):
return np.random.rand()*(b-a) + a
def get_random_data(self, image, input_shape, jitter=.3, hue=.1, sat=1.5, val=1.5, random=True):
# Read and convert images to RGB
image = cvtColor(image)
iw, ih = image.size
h, w = input_shape
if not random:
scale = min(w/iw, h/ih)
nw = int(iw*scale)
nh = int(ih*scale)
dx = (w-nw)//2
dy = (h-nh)//2
image = image.resize((nw,nh), Image.BICUBIC)
new_image = Image.new('RGB', (w,h), (128,128,128))
new_image.paste(image, (dx, dy))
image_data = np.array(new_image, np.float32)
return image_data
new_ar = w/h * self.rand(1-jitter,1+jitter)/self.rand(1-jitter,1+jitter)
scale = self.rand(.75, 1.25)
if new_ar < 1:
nh = int(scale*h)
nw = int(nh*new_ar)
else:
nw = int(scale*w)
nh = int(nw/new_ar)
image = image.resize((nw,nh), Image.BICUBIC)
dx = int(self.rand(0, w-nw))
dy = int(self.rand(0, h-nh))
new_image = Image.new('RGB', (w,h), (128,128,128))
new_image.paste(image, (dx, dy))
image = new_image
flip = self.rand()<.5
if flip: image = image.transpose(Image.FLIP_LEFT_RIGHT)
rotate = self.rand()<.5
if rotate:
angle = np.random.randint(-15,15)
a,b = w/2,h/2
M = cv2.getRotationMatrix2D((a,b),angle,1)
image = cv2.warpAffine(np.array(image), M, (w,h), borderValue=[128,128,128])
hue = self.rand(-hue, hue)
sat = self.rand(1, sat) if self.rand()<.5 else 1/self.rand(1, sat)
val = self.rand(1, val) if self.rand()<.5 else 1/self.rand(1, val)
x = cv2.cvtColor(np.array(image,np.float32)/255, cv2.COLOR_RGB2HSV)
x[..., 1] *= sat
x[..., 2] *= val
x[x[:,:, 0]>360, 0] = 360
x[:, :, 1:][x[:, :, 1:]>1] = 1
x[x<0] = 0
image_data = cv2.cvtColor(x, cv2.COLOR_HSV2RGB)*255
return image_data