У меня есть прямоугольные angular изображения произвольного размера, которые я хочу обрезать до квадрата по самой короткой стороне, изменить их размер во входную форму и передать в нейронную сеть. Я знаю, что в keras.preprocessing.image.ImageDataGenerator
поддерживается множество методов увеличения изображения, но я не видел никаких методов обрезки квадратных изображений.
Существует ли для этого функция keras? Если нет, можно ли использовать внешнюю функцию обрезки и подключить ее где-нибудь между методами ImageDataGenerator
и flow_from_directory
?.
Я также пробовал создать свой собственный генератор, но это занимает значительно больше времени, чем предыдущие испытания с методом flow_from_directory
.
Мой текущий рабочий процесс:
image_shape = (224, 224, 3)
def im_crop(image):
dim = image.size
shortest = min(dim[0:2])
longest = max(dim[0:2])
lv = np.array(range(0, shortest)) + floor((longest - shortest) / 2)
if dim[0] == shortest:
im_cropped = np.asarray(image)[lv, :, :]
else:
im_cropped = np.asarray(image)[:, lv, :]
im_cropped = Image.fromarray(im_cropped)
return im_cropped
def im_rescale(image, shape):
im_resized = image.resize((shape[0], shape[1]))
im_array_resized = np.array(im_resized)
return im_array_resized
def getFilesLabels(path):
paths = list()
files = list()
labels = list()
for (dirpath, dirnames, filenames) in os.walk(path):
paths += [os.path.join(dirpath, file) for file in filenames]
files += [file for file in filenames]
labels += [os.path.basename(dirpath) for file in filenames]
df = pd.DataFrame()
df['path'] = paths
df['fname'] = files
df['label'] = labels
df = df[~df['fname'].str.contains(".DS_Store")]
classes = list(set(df['label']))
num_label = [classes.index(l) for l in df['label']]
df['num_label'] = num_label
return df
def get_input(path):
img = Image.open(path)
return img
def get_output(path, label_file=None):
labels = label_file['num_label'][label_file['path'] == path].iloc[0]
return labels
def val_preprocess_input(image, shape):
image1 = im_crop(image)
image2 = im_rescale(image1, shape)
return image2
def train_preprocess_input(image, shape):
image1 = im_crop(image)
image2 = im_rescale(image1, shape)
return image2
def image_generator(df, shape, batch_size=32):
while True:
# Select files (paths/indices) for the batch
batch_paths = np.random.choice(a=df['path'],
size=batch_size)
batch_input = []
batch_output = []
# Read in each input, perform preprocessing and get labels
for input_path in batch_paths:
input = get_input(input_path)
output = get_output(input_path, label_file=df)
input = train_preprocess_input(image=input, shape=shape)
batch_input += [input]
batch_output += [output]
# Return a tuple of (input, output) to feed the network
batch_x = np.array(batch_input)
batch_y = np.array(batch_output)
yield (batch_x, batch_y)
train_set = getFilesLabels(os.path.join(output_path, "Images/Network Input/train"))
val_set = getFilesLabels(os.path.join(output_path, "Images/Network Input/val"))
train_generator = image_generator(train_set, image_shape)
val_generator = image_generator(val_set, image_shape)
# Generators are then fed to keras.model instance