Keras - 如何在不改变纵横比的情况下使用ImageDataGenerator

15

我有一个存储了不同尺寸图片的文件夹。我尝试使用ImageDataGenerator和flow_from_directory进行批量加载/数据增强。

是否有方法可以保持我的图像的纵横比?似乎这些图像被拉伸到目标尺寸:我希望“填充”我的图像而不是使它们变形(用常数值填充空白区域)

以下是我的代码:

datagen = ImageDataGenerator(
    rescale = 1./255,
    fill_mode='constant')

generator = datagen.flow_from_directory(
    'data/images',
    target_size=(256,256),
    color_mode = 'grayscale',
    batch_size=99,
    class_mode=None,
    shuffle=False)

图像正在被拉伸至(256,256)。

2个回答

13

我找到了对我的问题的答案。

目前使用ImageDataGenerator / flow_from_directory时无法保持纵横比,但在Github上已经提交了一个 pull request 来添加此功能。pull request


这仍然是一个开放的拉取请求:https://github.com/keras-team/keras-preprocessing/pull/81 - Rick
仍然是一个开放的拉取请求。 - Jivan
2
在我看来,这太荒谬了!更愚蠢的是,预处理钩子在原始调整大小之后运行,因此您甚至无法使用它将图像变为正方形。 - satnhak

0
根据这篇文章,您可以使用此代码为图像添加填充而不拉伸它:
使用PIL
from PIL import Image, ImageOps

desired_size = 224
im_pth = "/home/jdhao/test.jpg"

im = Image.open(im_pth)
old_size = im.size  # old_size[0] is in (width, height) format

ratio = float(desired_size) / max(old_size)
new_size = tuple([int(x * ratio) for x in old_size])
# use thumbnail() or resize() method to resize the input image

# thumbnail is a in-place operation

# im.thumbnail(new_size, Image.ANTIALIAS)

im = im.resize(new_size, Image.ANTIALIAS)
# create a new image and paste the resized on it

new_im = Image.new("RGB", (desired_size, desired_size))
new_im.paste(im, ((desired_size - new_size[0]) // 2,
                  (desired_size - new_size[1]) // 2))

new_im.show()

使用opencv

import cv2
desired_size = 224
im_pth = "data_cropped/ges_cropped_0/001019180113990401104712_frame_150.jpg"

im = cv2.imread(im_pth)
old_size = im.shape[:2]  # old_size is in (height, width) format

ratio = float(desired_size) / max(old_size)
new_size = tuple([int(x * ratio) for x in old_size])

# new_size should be in (width, height) format

im = cv2.resize(im, (new_size[1], new_size[0]))

delta_w = desired_size - new_size[1]
delta_h = desired_size - new_size[0]
top, bottom = delta_h // 2, delta_h - (delta_h // 2)
left, right = delta_w // 2, delta_w - (delta_w // 2)

color = [0, 0, 0]
new_im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT,
                            value=color)

print(new_im.shape)
cv2.imshow("image", new_im)
cv2.waitKey(0)
cv2.destroyAllWindows()

ImageDataGenerator中,您可以使用preprocessing_function参数在生成数据之前进行上述预处理。我知道这个答案有点晚了,但我希望其他开发人员能够使用这段代码。

2
我不确定是否有意义进行任何形式的调整和增强,因为在文档中,它说“该函数将在图像被调整大小和增强之后运行。因此,在您的情况下,预处理函数将应用于其纵横比已经被破坏的图像。” - Kevin Südmersen
@KevinSüdmersen 完全正确。我在发布这个答案后意识到了这个错误,但是忘记更新答案了。 - Masoud Masoumi Moghadam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接