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

Posted

技术标签:

【中文标题】Keras - 如何在不改变纵横比的情况下使用 ImageDataGenerator【英文标题】:Keras - How to use ImageDataGenerator without deforming aspect ratio 【发布时间】:2017-07-17 00:04:11 【问题描述】:

我有一个包含不同大小图像的文件夹。我尝试使用 ImageDataGenerator 和 flow_from_directory 进行批量加载/数据增强。

有没有办法保持图像的纵横比?似乎图像被拉伸到 target_size :我想“填充”我的图像而不使它们变形(用恒定值填充间隙)

这是我的代码:

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)。

【问题讨论】:

【参考方案1】:

我找到了问题的答案。

目前在使用 ImageDataGenerator / flow_from_directory 时无法保持纵横比,但在 Github 上打开了一个pull request 以添加此功能。

【讨论】:

它仍然是一个开放的拉取请求:github.com/keras-team/keras-preprocessing/pull/81 仍然是一个开放的拉取请求 在我看来这太荒谬了!更愚蠢的是,预处理钩子在原始调整大小之后运行,所以你甚至不能使用它来使图像成为正方形。【参考方案2】:

根据this post,您可以使用此代码为图像添加填充而不拉伸它:

使用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 参数在生成数据之前进行上述预处理。我知道答案已经晚了,但我希望其他开发人员可以使用此代码。

【讨论】:

我不确定进行任何类型的调整大小和扩充是否有意义,因为在文档中,它说“函数将在图像调整大小后运行 和增强。因此,在您的情况下, preprocessing_function 将应用于纵横比已被破坏的图像 @KevinSüdmersen 完全正确。发布此答案后,我意识到了这个错误,但我忘了更新答案。

以上是关于Keras - 如何在不改变纵横比的情况下使用 ImageDataGenerator的主要内容,如果未能解决你的问题,请参考以下文章

在不改变原始纵横比的情况下将位图大小调整为 512x512

使用 Python - 如何在不超过原始图像大小的情况下调整裁剪图像的大小以满足纵横比

在不保持纵横比的情况下使用 mogrify 调整图像大小

在不丢失纵横比的情况下将图像放入特定大小的盒子中?

如何在不破坏图像纵横比的情况下调整 QImage 或 QML 图像的大小以适应父容器

如何在不影响纵横比的情况下将纵向和横向图像显示为网格上的正方形?