Skip to content

Commit

Permalink
add keep_aspect_ratio flag to flow_from_directory
Browse files Browse the repository at this point in the history
  • Loading branch information
qdbp committed Jan 12, 2017
1 parent 875bc59 commit 9c9923f
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 7 deletions.
42 changes: 35 additions & 7 deletions keras/preprocessing/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,20 @@ def img_to_array(img, dim_ordering='default'):
return x


def load_img(path, grayscale=False, target_size=None):
def load_img(path, grayscale=False, target_size=None,
keep_aspect_ratio=False, cval=0):
"""Load an image into PIL format.
# Arguments
path: path to image file
grayscale: boolean
target_size: None (default to original size)
or (img_height, img_width)
keep_aspect_ratio: if `True`, the resized image will have the
same aspect ratio as the original, centered and padded
with `cval` to respect `target_size`
cval: integer in [0, 255]. value to pad the output image with if
`keep_aspect_ratio` is `True`
"""
from PIL import Image
img = Image.open(path)
Expand All @@ -190,7 +196,19 @@ def load_img(path, grayscale=False, target_size=None):
else: # Ensure 3 channel even when loaded image is grayscale
img = img.convert('RGB')
if target_size:
img = img.resize((target_size[1], target_size[0]))
size = (target_size[1], target_size[0])
if not keep_aspect_ratio:
img = img.resize(size)
else:
# PIL doesn't seem to like floats in new despite the docs...
img.thumbnail(size, Image.ANTIALIAS)
bcg = Image.new(('L' if grayscale else 'RGB'), size,
(cval if grayscale else (cval, cval, cval)))
bcg.paste(img,
((size[0] - img.size[0]) // 2,
(size[1] - img.size[1]) // 2))
return bcg

return img


Expand Down Expand Up @@ -302,10 +320,12 @@ def flow_from_directory(self, directory,
classes=None, class_mode='categorical',
batch_size=32, shuffle=True, seed=None,
save_to_dir=None, save_prefix='', save_format='jpeg',
follow_links=False):
follow_links=False,
keep_aspect_ratio=False, cval=0):
return DirectoryIterator(
directory, self,
target_size=target_size, color_mode=color_mode,
target_size=target_size, keep_aspect_ratio=keep_aspect_ratio,
cval=cval, color_mode=color_mode,
classes=classes, class_mode=class_mode,
dim_ordering=self.dim_ordering,
batch_size=batch_size, shuffle=shuffle, seed=seed,
Expand Down Expand Up @@ -591,8 +611,8 @@ def next(self):
class DirectoryIterator(Iterator):

def __init__(self, directory, image_data_generator,
target_size=(256, 256), color_mode='rgb',
dim_ordering='default',
target_size=(256, 256), keep_aspect_ratio=False, cval=0,
color_mode='rgb', dim_ordering='default',
classes=None, class_mode='categorical',
batch_size=32, shuffle=True, seed=None,
save_to_dir=None, save_prefix='', save_format='jpeg',
Expand All @@ -602,6 +622,12 @@ def __init__(self, directory, image_data_generator,
self.directory = directory
self.image_data_generator = image_data_generator
self.target_size = tuple(target_size)
self.keep_aspect_ratio = keep_aspect_ratio
if not (0 <= cval < 255):
raise ValueError('cval {} not valid, must be in [0, 255]'
.format(cval))
self.cval = cval

if color_mode not in {'rgb', 'grayscale'}:
raise ValueError('Invalid color mode:', color_mode,
'; expected "rgb" or "grayscale".')
Expand Down Expand Up @@ -688,7 +714,9 @@ def next(self):
fname = self.filenames[j]
img = load_img(os.path.join(self.directory, fname),
grayscale=grayscale,
target_size=self.target_size)
target_size=self.target_size,
keep_aspect_ratio=self.keep_aspect_ratio,
cval=self.cval)
x = img_to_array(img, dim_ordering=self.dim_ordering)
x = self.image_data_generator.random_transform(x)
x = self.image_data_generator.standardize(x)
Expand Down
15 changes: 15 additions & 0 deletions tests/keras/preprocessing/test_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,21 @@ def test_directory_iterator(self):
assert(sorted(dir_iterator.filenames) == sorted(filenames))
shutil.rmtree(tmp_folder)

def test_load_img(self):
td = tempfile.mkdtemp(prefix='test_images')
fn = os.path.join(td, 'test_load_image.jpg')
Image.new(mode='RGB', size=(10, 10), color=(255, 255, 255)).save(fn)

i1 = image.load_img(fn, target_size=(5, 7), keep_aspect_ratio=True)
i2 = image.load_img(fn, target_size=(10, 5), keep_aspect_ratio=True,
cval=0, grayscale=True)

assert i1.size == (7, 5)
assert i2.size == (5, 10)
i2arr = np.array(i2)
assert i2arr.shape == (10, 5)
assert 120 < np.mean(i2arr) < 140

def test_img_utils(self):
height, width = 10, 8

Expand Down

0 comments on commit 9c9923f

Please sign in to comment.