使用ImageDataGenerator是Keras中图像数据预处理的常用方法

一、作用

ImageDataGenerator()是keras.preprocessing.image模块中的图片生成器,同时也可以在batch中对数据进行增强,扩充数据集大小,增强模型的泛化能力。比如进行旋转,变形,归一化等等。还可以自动为训练数据生成标签。
总结起来就是三个点:
(1)图片生成器,负责生成一个批次一个批次的图片,以生成器的形式给模型训练;
(2)对每一个批次的训练图片,适时地进行数据增强处理(data augmentation);
(3)自动为训练数据生成标签。

二、ImageDataGenerator简单介绍

1. 常用参数

  • rotation_range(): 旋转范围
  • width_shift_range(): 水平平移范围
  • height_shift_range(): 垂直平移范围
  • shear_range(): float, 透视变换的范围
  • zoom_range(): 缩放范围
  • horizontal_flip(): 水平反转
  • vertical_flip(): 垂直翻转
  • validation_split(): 多少数据用于验证集
  • featurewise_center: 布尔值。将输入数据的均值设置为 0,逐特征进行,对输入的图片每个通道减去每个通道对应均值。
  • samplewise_center: 布尔值。将每个样本的均值设置为 0,每张图片减去样本均值, 使得每个样本均值为0
  • featurewise_std_normalization: Boolean. 布尔值。将每个输入(即每张图片)除以数据集(dataset)标准差,逐特征进行。
  • samplewise_std_normalization: 布尔值。将每个输入(即每张图片)除以其自身(图片本身)的标准差。
  • 2. 常用函数

  • fit(x, augment=False, rounds=1, seed=None): 将生成器用于数据x,从数据x中获得样本的统计参数, 只有featurewise_center, featurewise_std_normalization或者zca_whitening为True才需要。
  • flow(x, y=None, batch_size=32, shuffle=True, sample_weight=None, seed=None, save_to_dir=None, save_prefix='', save_format='png', subset=None) ): 按batch_size大小从x,y生成增强数据。
  • flow_from_directory():从图片所在目录生成增强数据,和flow方法相比最大的优点在于不用一次将所有的数据读入内存当中,这样减小内存压力,这样不会发生OOM。
  • 3. 使用的一般流程

    第一步:构造ImageDataGenerator对象,可在其参数中设置是否使用数据增强以及使用哪些数据增强方式。

    第二步:对样本数据进行data augmentation处理,通过fit方法。注意:如果不需要原始图形的统计信息,比如均值、方差等等,则不要进行此步骤。

    第三步:使用flow()或flow_from_directory()生成成批的数据,用于训练或保存起来。

    三、使用中的理解

    假设进行数据增强,构造ImageDataGenerator对象如下:

        data_gen = ImageDataGenerator(rescale=1/255.0,
                                      rotation_range=15,
                                      width_shift_range=0.2,
                                      height_shift_range=0.2,
                                      horizontal_flip=True,
                                      vertical_flip=True)

    1. flow_from_directory()

    flow_from_directory()函数的常用参数如下:

        data = data_gen.flow_from_directory(directory='test_data',
                                            target_size=(IMSIZE,IMSIZE)
                                            batch_size=bs,  
                                            save_prefix='trans_',
                                            save_to_dir=save_path
                                            class_mode='categorical')

    其生成数据的过程为:每次从文件夹中取batch_size张图片进行处理。对其中每张图片按照data_gen中的定义均除以255并实施全部5种增强操作,然后将大小变为(IMSIZE,IMSIZE),最后为生成的这张图片命名前缀加上trans_并保存到保存目录中;对于其标签,则按图片所在子目录认定为所属标签并转换为one-hot编码。当执行多次后,如果中间某一次文件夹中剩余的图片数小于batch_size,则此次取实际剩下的图片数目,也就是生成的图片数小于batch_size; 而从下一次开始,再次从文件夹中从头开始取batch_size张图片,如此反复。这可能会导致生成的总图片数小于batch_size * 生成次数。如目录中有4张图片,batch_size=3,则生成三次的结果分别为3,1,3张,共计7张,而不是9张。

    实验过程如下:

    test_data中有四张图片如下

    代码:

    def data_pre_processing():
        '''
        该函数用于对图片进行归一化、随机旋转15度、水平平移幅度0.2、垂直平移幅度0.2,
        并随机水平翻转和垂直翻转
        '''
        path = '../test_data/LAG'
        save_path = '../save_data'
        IMSIZE = (400, 600)  # width, height
        bs = 3
    
        data_gen = ImageDataGenerator(rescale=1/255.0,
                                      rotation_range=15,
                                      width_shift_range=0.2,
                                      height_shift_range=0.2,
                                      horizontal_flip=True,
                                      vertical_flip=True)
    
         data = data_gen.flow_from_directory(directory='../test_data',
                                            target_size=IMSIZE,
                                             batch_size=bs,
                                             save_prefix='trans_',
                                             save_to_dir=save_path)
    
        i = 0
        for img, label in data:
            print(img.shape)
            i += 1
            if i>=3:
                break
    
    
    if __name__ == '__main__':
        data_pre_processing()
        print('原图像个数:', len(os.listdir('../test_data/LAG')))
        print('增强后图像个数:', len(os.listdir('../save_data')))

    运行结果:

    查看产生的图像

     2. flow()

    flow函数的常用方法如下:

    datagen.flow(x 
                 y, 
                 batch_size=bs,
                 save_prefix='trans_',
                 save_to_dir=save_path)

    其生成数据的过程为:从数据集x中每次取batch_size条数据进行处理,生成的图片前缀加trans_然后保存到目录中。

    四、 图片增强实践

    给定某个目录中有一些图片,现在需要对这些图片进行增强处理,增强处理后的图片保存到另一个目录,具体要求为:(1) 增强后的图像尺寸必须和原图像尺寸一致;(2) 保存图象时图像名前缀为"trans_";(3) 保存的图像数量应该为原图像数量的5倍。

    1. 采用flow_from_directory()实现

    由前面对此方法的理解可知,设定的batch_size必须要能被原目录图片个数(设为total_num)整除,然后进行total_num / batch_size * 5次生成即可。注意:此方法由于有target_size参数,故而所有生成的图片大小都是一样的。如果原目录中图片大小都一致,则将targets_size设置为原目录中图片的大小即可;如果原目录中图片大小不一,则无解。

    2. 采用flow()实现

    从原目录中每次读取一张图片,经过处理生成(1, H, W, 3)的形状,作为flow()中的x,然后使用flow()生成5次(也就是对这张图片进行5次增强)。注意:此方法可能会导致某张(或某几张)原始图片无法生成5次,原因是生成的图片是使用随机数命名的,这可能会导数保存到同一个目录时,某次生成的图片的名字和原来已存在的图片名重名而造成保存不成功(或覆盖了原来同名图片),无论哪种情况,都会导致生成的图片数量可能会少于原图像数量的5倍。

    物联沃分享整理
    物联沃-IOTWORD物联网 » 使用ImageDataGenerator是Keras中图像数据预处理的常用方法

    发表评论