【keras】数据增强之---ImageDataGenerator

every blog every motto: You can do more than you think.

0. 前言

记录使用keras进行数据增强中遇到的有关问题

1. 正文

1.1 基本介绍

我们可以使用keras.preprocessing.image.ImageDataGenerator对数据进行“线上”或“线下”增强

1.1.1 生成对象

如下代码所示:
我们可以生成一个可迭代对象,并对其指定数据增强的具体方式(如:旋转、翻转等)

from keras.preprocessing.image import ImageDataGenerator
datagen = ImageDataGenerator(
        rotation_range=40,
        width_shift_range=0.2,
        height_shift_range=0.2,
        rescale=1./255,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True,
        fill_mode='nearest')

参数:

  • rotation_range是一个0~180的度数,用来指定随机选择图片的角度。
  • width_shift和height_shift用来指定水平和竖直方向随机移动的程度,这是两个0~1之间的比例。
  • rescale值将在执行其他处理前乘到整个图像上,我们的图像在RGB通道都是0255的整数,这样的操作可能使图像的值过高或过低,所以我们将这个值定为01之间的数。
  • shear_range是用来进行剪切变换的程度,参考剪切变换。 zoom_range用来进行随机的放大。
  • horizontal_flip随机的对图片进行水平翻转,这个参数适用于水平翻转不影响图片语义的时候。
  • fill_mode用来指定当需要进行像素填充,如旋转,水平和竖直位移时,如何填充新出现的像素。

下面是生成器的两种方法,可以用next访问,也可以for循环遍历,下面以next为例。


1.1.2 flow

对读取图片后的数组进行变换,即参数为数组
因为是生成器,我们可以用next获取生成器的下一个值。

import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import tensorflow as tf
from keras.preprocessing.image import ImageDataGenerator
import cv2 as cv
import numpy as np

# 读取图片
img = cv.imread('./input/u=1819216937,2118754409&fm=26&gp=0.jpg')
img = np.expand_dims(img, axis=0)
# 实例化对象
agu = ImageDataGenerator(rotation_range=40)  # 随机旋转0-40度之间
# print(type(agu))
# 变换并保存
next(agu.flow(img, save_to_dir='./output', save_format='jpg'))

说明: flow中接受的是4维数组,即含有btach维度,如:(batch,Height , Width , channel),上面代码中添加了一维。下同。
在这里插入图片描述

1.1.3 flow_from_directory

“对图片所在的文件夹进行变换”,即参数为文件夹
注意: 参数为文件夹,其中要含子文件夹!!!
在这里插入图片描述

import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import tensorflow as tf
from keras.preprocessing.image import ImageDataGenerator
import cv2 as cv
import numpy as np

# 输入文件夹
path = r'./input'
# 实例化对象
agu = ImageDataGenerator(rotation_range=40)  # 随机旋转0-40度之间
# print(type(agu))
# 变换并保存
next(agu.flow_from_directory(path,batch_size=1, save_to_dir='./output', save_format='jpg'))

1.2 问题

基本代码同1.1.2,只是实例化对象不同,故,只贴出实例化对象部分

1.2.1 问题1

报错如下:

UserWarning: This ImageDataGenerator specifies `zca_whitening`, which overrides setting of `featurewise_center`.
  warnings.warn('This ImageDataGenerator specifies '

部分代码:

# 实例化对象
agu = ImageDataGenerator(rotation_range=40,zca_whitening=True)

只是在其中增加了zca_whitening参数,出现如上警告。
解释: zca_whitening=True时,会将feature_center设为True,尽管我们没有设置,所有会出现警告。
源码:
在这里插入图片描述
解决方法,增加feature_center=True即可。

# 实例化对象
agu = ImageDataGenerator(rotation_range=40,zca_whitening=True,featurewise_center=True)

1.2.2 问题2

对图片白化遇到的相关问题:

UserWarning: This ImageDataGenerator specifies `featurewise_center`, but it hasn't been fit on any training data. Fit it first by calling `.fit(numpy_data)`.
  warnings.warn('This ImageDataGenerator specifies '

实例化对象代码

# 实例化对象
agu = ImageDataGenerator(rotation_range=40,zca_whitening=True,featurewise_center=True)

原因: 参数中我们使用了feature_center=True,但是没有使用fit方法
官方解释:
在这里插入图片描述
解决办法: 使用flowflow_from_directory 方法前调用fit方法
代码:
在这里插入图片描述
另: 当使用fit方法时,会计算统计信息(均值方差),这个过程是非常慢的,若图片较大时,会出现下面一个错误

1.2.3 问题3

报错如下:

MemoryError: Unable to allocate 857. GiB for an array with shape (479700, 479700) and data type float32

原因: 要计算相关统计信息,会计算SVD,其中的数值较大,所以出现了如上错误。
一种尝试:
将fit方法替换为如下,手动计算:

agu.mean = np.mean(img,axis=0)

完整代码:
在这里插入图片描述
但是结果不一定对:
在这里插入图片描述
这仅仅是一种尝试,结果不一定对

1.2.4 问题4

仅增加旋转参数,保存图片的颜色发生变化
在这里插入图片描述
代码:
在这里插入图片描述
原因: 我们使用cv读取图片,读取的是BRG,写入时与原先的RGB正好相反,所以出现错误。
方法一:调整BGR顺序

在这里插入图片描述
结果:
在这里插入图片描述
方法二: 转换
在这里插入图片描述
方法三:PIL读取

在这里插入图片描述

1.2.5 问题5

说明: 这个准确来说,不能算问题,而是好奇,如下:
设置多个参数时,每次仅使用一个,还是同时使用。

测试,同时使用旋转和垂直翻转这两个参数。
代码:
在这里插入图片描述
测试两次,结果如下:
在这里插入图片描述
结论: 我们发现,两个参数是随机起作用的,有时候只旋转,不翻转;有时候两个都起作用,等。
又进行一次测试,结果如下:
在这里插入图片描述
我们发现,其分别朝左和右进行了旋转,这也就推翻了我们之前所说,或是注释里面所注的:“旋转朝0-40度(设定的值)进行旋转”,而应该是,-40-40度之间,源码中我们发现确实是这样。
上面代码中的注释是错的,不是0-40度之间旋转,我就不回去修改了,大家注意!!!
在这里插入图片描述

1.3 两种使用方式

1.3.1 普通使用

这是官方的一个例子,通过循环,不断的获取数据

(x_train, y_train), (x_test, y_test) = cifar10.load_data()
y_train = np_utils.to_categorical(y_train, num_classes)
y_test = np_utils.to_categorical(y_test, num_classes)

datagen = ImageDataGenerator(
    featurewise_center=True,
    featurewise_std_normalization=True,
    rotation_range=20,
    width_shift_range=0.2,
    height_shift_range=0.2,
    horizontal_flip=True)

# compute quantities required for featurewise normalization
# (std, mean, and principal components if ZCA whitening is applied)
datagen.fit(x_train)

# fits the model on batches with real-time data augmentation:
model.fit_generator(datagen.flow(x_train, y_train, batch_size=32),
                    steps_per_epoch=len(x_train), epochs=epochs)

# here's a more "manual" example
for e in range(epochs):
    print 'Epoch', e
    batches = 0
    for x_batch, y_batch in datagen.flow(x_train, y_train, batch_size=32):
        loss = model.train(x_batch, y_batch)
        batches += 1
        if batches >= len(x_train) / 32:
            # we need to break the loop by hand because
            # the generator loops indefinitely
            break

1.3.2 和keras.utils.Sequence结合使用

keras.utils.Sequence的使用参考之前的文章,文后附。
说明:
使用起来也很简单,

  • 初始化时,生成数据增强对象
  • __getitem __ 返回next,不断调用生成即可。
import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import tensorflow as tf
from keras.preprocessing.image import ImageDataGenerator, load_img
import cv2 as cv
import numpy as np


class Date(tf.keras.utils.Sequence):

    def __init__(self):
        self.input = r'./data'
        self.file = os.listdir(self.input)
        print(self.file)
        self.batch = 2
        self.agu = ImageDataGenerator(
            # 增强的项目。翻转,缩放,平移,旋转,颜色等。
            rotation_range=40,
            width_shift_range=0.2,
            height_shift_range=0.2,
            shear_range=0.2,  # 比例平移
            zoom_range=0.2,
            fill_mode='nearest',
            horizontal_flip=True,
            vertical_flip=True,
            zca_whitening=True,
            featurewise_center=True,
            rescale=1. / 255
        )

    def __len__(self):
        """
        此方法要实现,否则会报错
        正常程序中返回1个epoch迭代的次数
        :return:
        """
        return len(self.file)

    def generate_batch(self):
        x_batch = np.zeros((3, 256, 256, 3))
        for i, file in enumerate(self.file):
            path = os.path.join(self.input, file)
            # print(path)
            img = cv.imread(path)
            x_batch[i,] = img
        x_batch = np.array(x_batch)

        return x_batch

    def __getitem__(self, index):
        """生成一个batch的数据"""

        x_batch = self.generate_batch()
        # self.agu.fit(x_batch)
        return next(self.agu.flow(x_batch,batch_size=1,save_to_dir='./output',save_format='jpg'))
        # return next((self.agu.flow_from_directory(self.input,save_to_dir='./output',save_format='jpg')))
        # return x_batch


# 实例化数据
date = Date()

for batch_number, x in enumerate(date):
    print('正在进行第{} batch'.format(batch_number))

参考文献

[1] https://blog.csdn.net/weixin_39190382/article/details/109195031
[2] https://blog.csdn.net/xijuezhu8128/article/details/79895856
[3] https://blog.csdn.net/wang263334857/article/details/88749379
[4] https://blog.csdn.net/qq_36537768/article/details/103066394
[5] https://www.cnblogs.com/hutao722/p/10075150.html
[6] https://blog.csdn.net/jacke121/article/details/79245732
[7] https://blog.csdn.net/qq_27825451/article/details/90172030
[8] https://blog.csdn.net/dugudaibo/article/details/87719078
[9] https://tensorflow.google.cn/versions/r2.0/api_docs/python/tf/keras/preprocessing/image/ImageDataGenerator
[10] https://keras-cn.readthedocs.io/en/latest/preprocessing/image/#imagedatagenerator

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胡侃有料

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值