keras图像预处理_keras 图像预处理 - CSDN
精华内容
参与话题
  • 前言:前面已经详细介绍了keras整个图像预处理模块的详细流程,参见下面两篇文章: keras图像预处理全攻略(二)—— ImageDataGenerator 类 keras图像预处理全攻略(三)—— ImageDataGenerator 类的辅助类 ...

    前言:前面已经详细介绍了keras整个图像预处理模块的详细流程,参见下面两篇文章:

    keras的图像预处理全攻略(二)—— ImageDataGenerator 类

    keras的图像预处理全攻略(三)—— ImageDataGenerator 类的辅助类

    本文结合实际案例来说说明到底该怎么应用 ImageDataGenerator 类以及需要注意的一些事项

    一、图像分类问题中ImageDataGenerator 类的flow方法的应用

    二、图像分类问题中ImageDataGenerator 类的flow_from_directory方法应用

    三、对于分割数据集使用ImageDataGenerator类

    一、图像分类问题中ImageDataGenerator 类的flow方法的应用

    我们经常遇见一些分类问题,往往由于数据量较小的原因,导致模型很容易过拟合,所以需要进行数据增强,本文以最简单的mnist手写字为例子来加以说明ImageDataGenerator 类的简单应用。再说明之前,我们学要结合系列文章的第二篇的相关知识点,ImageDataGenerator 类的使用分为“四步走”策略。

    1.1 第一步:数据集的划分,得到x_train,y_train,x_test,y_test;

    from keras.preprocessing.image import ImageDataGenerator
    
    from keras.datasets import mnist
    from keras.datasets import cifar10
    from keras.utils import np_utils
    
    import numpy as np
    import matplotlib.pyplot as plt
    
    
    # 第一步:划分数据集。得到x_train,y_train,x_test,y_test;
    num_classes = 10
    (x_train, y_train), (x_test, y_test) = mnist.load_data()
    
    x_train = np.expand_dims(x_train, axis = 3)
    y_train = np_utils.to_categorical(y_train, num_classes)
    y_test = np_utils.to_categorical(y_test, num_classes)
    
    print(np.shape(x_train))  #返回(60000, 28, 28, 1)
    print(np.shape(x_test))   #返回(10000, 28, 28),因为这里没有对测试数据进行维度扩充,这里不需要使用到测试数据,所以没管它
    print(np.shape(y_train))  #返回(60000, 10)
    print(np.shape(y_test))   #返回(10000, 10)
    print("======================================================")

    注意:由于mnist.npz会默认没有的,需要下载,但是国内下载实在是太慢,所以我是已经下载好了并且保存在了用户文件夹之下的.keras/datasets里面了。所以不需要下载的,网上有很多的下载资源,也可以找我要数据,大改10M。

    1.2 第二步:构造ImageDataGenerator对象

    其中要进行某一些操作是通过在构造函数中的参数指定的,datagen = ImageDataGenerator(......)

    #第二步骤:构造ImageDataGenerator类的对象,通过参数指定要进行处理项目
    #对数据进行预处理,注意这里不是一次性要将所有的数据进行处理完,而是在后面的代码中进行逐批次处理
    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)

    1.3 第三步:对样本数据进行data augmentation处理,通过fit方法

    #第三步:对需要处理的数据进行fit
    datagen.fit(x_train)

    1.4 产生迭代对象,通过flow方法,并且查看每一次迭代对象的信息

    #第四步:使用.flow方法构造Iterator, 
    data_iter = datagen.flow(x_train, y_train, batch_size=8,save_to_dir="save_data")  #返回的是一个“生成器对象”
    print(type(data_iter))    #返回的是一个NumpyArrayIterator对象
    
     
    # 通过循环迭代每一次的数据,并进行查看
    for x_batch,y_batch in data_iter:
        for i in range(8):
            plt.subplot(2,4,i+1)
            plt.imshow(x_batch[i].reshape(28,28), cmap='gray')
        plt.show()

    这里是核心点,有几个需要注意的地方:

    (1)迭代器的数据格式

    我们通过ImageDataGenerator类来对训练数据做处理,目的是产生一个迭代器,然后将每一次迭代产生的数据放进model.fit_generator()里面进行训练,而迭代器的数据格式如下:

    • 一个 (inputs, targets) 元组
    • 一个 (inputs, targets, sample_weights) 元组。

    (2)flow函数save_to_dir参数

    这个参数会将没一个批次所进行data augmentation之后的图像保存在指定的文件夹,它的作用是方便对于处理之后的图像进行查看。比如我上面保存到了当前文件之下的save_data文件夹里面。

    (3)迭代器可以通过for进行循环我也可以直接通过next()方法来进行迭代,上面的第四步等价与下面的代码:

    while True:
        x_batch, y_batch = data_iter.next()
        for i in range(8):
            plt.subplot(2,4,i+1)
            plt.imshow(x_batch[i].reshape(28,28), cmap='gray')
        plt.show()

    (4)flow是无限迭代的。也就是说每一次迭代8组样本,等一个轮回迭代完之后依然会继续重新迭代,不会自己停止。

    记住:flow()、flow_from_dataframe()、flow_from_directory()都是无限迭代的。

    但是这个地方一直有一个问题,我还没找到答案,望大神告知!

    如果总的样本数samples能够被batch_size整除,那么恰好可以每一次都恰好对batch_size个样本进行处理,这样当所有的样本都处理完之后,又会进入下一次循环迭代,即迭代不会终止;但是如果样本数samples不能够被batch_size整除,那么最后一个batch_size会少几个样本,这样在所有的样本数迭代完成一次之后就不再循环迭代了,也就是所有的样本只迭代一次,这倒是怎么回事,我还不太清楚,我是在实验中尝试得出的结果,网友大神告知,谢谢!

    1.5 运行结果展示

    由于图片很多,每一次仅仅只处理8张图片,所以每次要查看很多次才能将所有的样本数据完全看完,本文在运行了三次迭代器之后就停止了程序的运行,得到的运行结果,和保存的数据展示如下:

    这是三次迭代,每一次迭代产生的8张图片,我自己保存的sav_data文件夹之下的24张图片如下:

    二、图像分类问题中ImageDataGenerator 类的flow_from_directory方法应用

    为了演示flow_from_dirctory()方法的效果,本文没有使用其它的训练数据集,自己随便找几张图片做实验就可以了。

    本试验依然是以分类问题为背景,自己选择了15张约翰逊斯嘉丽的图片作为训练数据集,15张图片分为三类,分别是happy、smile、silent,另外下载了5张图片作为测试集,类别是一样的这三类,文件夹的组织结构如下所示:

    ├─Scarlett_Johansson_test
    │  ├─happy
    │  │      2001.jpg
    │  │
    │  ├─silent
    │  │      2002.jpg
    │  │      2003.jpg
    │  │
    │  └─smile
    │          2004.jpg
    │          2005.jpg

    └─Scarlett_Johansson_train
        ├─happy
        │      1006.jpg
        │      1007.jpg
        │      1008.jpg
        │      1009.jpg
        │      1010.jpg
        │
        ├─silent
        │      1011.jpg
        │      1012.jpg
        │      1013.jpg
        │      1014.jpg
        │      1015.jpg
        │
        └─smile
                1001.jpg
                1002.jpg
                1003.jpg
                1004.jpg
                1005.jpg

    即Scarlett_Johansson_data数据文件夹之下分为Scarlett_Johansson_test和Scarlett_Johansson_train两个文件夹,这两个文件夹之下没一个里面都包含smile、happy、silent三个类别的子文件夹,每一个字文件夹之下都保存着相应的样本数据。

    下面开始写代码:

    2.1 第一步:构建ImageDataGenerator类的对象

    from keras.preprocessing.image import ImageDataGenerator
    import numpy as np
    import matplotlib.pyplot as plt
    
    #第一步:对测试数据和训练数据分别构造一个ImageDataGenerator对象
    train_datagen = ImageDataGenerator(
            rescale=1./255,
            shear_range=0.2,
            zoom_range=0.2,
            horizontal_flip=True)
    
    test_datagen = ImageDataGenerator(rescale=1./255)

    2.2 第二步:调用flow_from_directory方法

    
    #第二步:分别对训练数据和测试数据使用flow_from_directory方法
    train_generator = train_datagen.flow_from_directory(
            'Scarlett_Johansson_data/Scarlett_Johansson_train',
            target_size=(150, 150),    #将图片大小转化为150x150
            batch_size=5,              #每一次处理6张图片
            class_mode='categorical',  #对类别进行独热编码
            save_to_dir="Scarlett_Johansson_data_augmentation", #将augmentation之后的图片保存
            save_prefix="sjl_")        #将augmentation之后的图片添加sjl_前缀
    
    validation_generator = test_datagen.flow_from_directory(
            'Scarlett_Johansson_data/Scarlett_Johansson_test',
            target_size=(150, 150),
            batch_size=2,    
            class_mode='binary')
    
    print('##############################################################')

    注意:本例子中一共有三个类别,及三个不同的文件夹smile、happy、silent,程序会自动判别一共有3各类型,这里有一个很重要的参数class_mode

    如果class_mode==“binary”,则输出的类别是0,1,2,来分别表示三个类,

    如果是class_mode==“'categorical”,则这三个类别会用独热编码的方式来表示,即【0,0,1】、【0,1,0】、【1,0,0】.

    2.3 第三步:迭代训练数据

    这里只对训练数据train_generator进行迭代,由于一共只有15组训练样本,所以每一次迭代5组样本,恰好可以除尽,这样可以循环迭代而不终止。本文选择迭代9次,即每个样本共产生3个数据增强的样本,共产生15*3=45组样本。代码如下:

    
    #第三步:迭代查看,这里只查看训练数据集的,测试数据集的就不管了
    count=1
    for x_batch,y_batch in train_generator:
        print(F"------------开始第{count}次迭代-----------------------------")
        print(F"------------x_batch、y_batch的形状如下----------------------")
        print(np.shape(x_batch),np.shape(y_batch))
        print('-------------y_batch打印结果如下-----------------------------')
        print(y_batch)
        print('============================================================')
    
        #将每次augmentation之后的5幅图像显示出来
        for i in range(5):
            plt.subplot(1,5,i+1)
            plt.imshow(x_batch[i].reshape(150,150,3))
            plt.savefig("Scarlett_Johansson_data_iter_time/iter_time_"+str(count)+".png",format="png")
        plt.show()
        count+=1

    程序运行的结果如下:

    '''
    Using TensorFlow backend.
    Found 15 images belonging to 3 classes. #这是调用train_datagen.flow_from_directory()后打印的
    Found 5 images belonging to 3 classes. ##这是调用test_datagen.flow_from_directory()后打印的
    ##############################################################
    ------------开始第1次迭代-----------------------------
    ------------x_batch、y_batch的形状如下----------------------
    (5, 150, 150, 3) (5, 3)
    -------------y_batch打印结果如下-----------------------------
    [[0. 0. 1.]
     [0. 1. 0.]
     [0. 1. 0.]
     [0. 0. 1.]
     [0. 1. 0.]]
    ============================================================
    .
    .
    .  中间的省略了,一共迭代了9次
    .
    .
    ------------开始第9次迭代-----------------------------
    ------------x_batch、y_batch的形状如下----------------------
    (5, 150, 150, 3) (5, 3)
    -------------y_batch打印结果如下-----------------------------
    [[0. 1. 0.]
     [0. 0. 1.]
     [0. 1. 0.]
     [1. 0. 0.]
     [1. 0. 0.]]
    ============================================================
    '''

    2.4 程序运行的结果查看

    (1)Scarlett_Johansson_data_iter_time文件夹——即每次迭代后使用plt预览的6张图片的文件夹

    (2)Scarlett_Johansson_data_augmentation文件夹——即迭代6次,共产生了9x5=45张增强图片的效果

    从上面可以看出,对15张样本数据分别都进行了三次增强,每挨着的3张图片对比可以发现,图像是不一样的,有的经过了翻转即flip操作、有的经过了缩放即zoom操作、有的经过了错切即shear操作,这其实都是来源于ImageDataGenerator中构造函数参数的指定来实现的。

    三、对于分割数据集使用ImageDataGenerator类

    由于只是做实验,本次是自己在voc2012数据集中只选择了15张样本数据来进行试验,只选择了三种类型,分别是飞机airplane、人person、火车car(因为火车的单词train与训练的train相同,这里就暂时使用car代替一下),文件目录的组织方式同上面的案例是一样的,如下:

    ├─mask_data
    │  └─train
    │      ├─airplane
    │      │      2007_000032.png
    │      │      2007_000033.png
    │      │      2007_000256.png
    │      │      2007_001288.png
    │      │      2007_001568.png
    │      │
    │      ├─car
    │      │      2007_000042.png
    │      │      2007_000123.png
    │      │      2007_000629.png
    │      │      2007_000636.png
    │      │      2007_004951.png
    │      │
    │      └─person
    │              2007_000129.png
    │              2007_000170.png
    │              2007_000323.png
    │              2007_000346.png
    │              2007_000999.png

    └─source_data
        └─train
            ├─airplane
            │      2007_000032.jpg
            │      2007_000033.jpg
            │      2007_000256.jpg
            │      2007_001288.jpg
            │      2007_001568.jpg
            │
            ├─car
            │      2007_000042.jpg
            │      2007_000123.jpg
            │      2007_000629.jpg
            │      2007_000636.jpg
            │      2007_004951.jpg
            │
            └─person
                    2007_000129.jpg
                    2007_000170.jpg
                    2007_000323.jpg
                    2007_000346.jpg
                    2007_000999.jpg

    注意:为什么针对分割模型这里单独拿出来,主要是因为分割模型的特殊性,它不仅有原始图像,还有与原始图像相对应的的分割标签图像,这里称之为mask图形,我对原始图形使用了某一种变换,必须给相对应的mask图形使用相同的变换进行变换,这才能保证训练数据与mask之间的一一对应关系不变。具体的实现如下:

    3.1 第一步:构造ImageDataGenerator类的对象,

    由于是需要对image和mask构造相同的变换,所以这里通过一个字典来构造该类的参数,如下:

    from keras.preprocessing.image import ImageDataGenerator
    import numpy as np
    import matplotlib.pyplot as plt
    
    #第一步:对测试数据和训练数据分别构造一个ImageDataGenerator对象
    #注意:由于原始训练数据和分割数据是绑定的,有对应关系,这里要创建两个相同参数的实例
    data_gen_args = dict(featurewise_center=True,
                         featurewise_std_normalization=True,
                         rescale=1./255,
                         rotation_range=90,
                         width_shift_range=0.1,
                         height_shift_range=0.1,
                         zoom_range=0.2)
    image_datagen = ImageDataGenerator(**data_gen_args) #构造训练数据image的对象
    mask_datagen = ImageDataGenerator(**data_gen_args)  #构造分割数据mask的对象

    3.2 第二步:同时对image和mask调用flow_from_directory方法

    这个地方需要注意的是,由于flow_from_directory方法会从训练数据中随机选择一个批次的图片进行变换,为了保持原始图像与分割图像mask之间的一一对应关系,需要指定一个随机数种子seed。(备注:需要懂得到底什么是伪随机数,什么时随机数种子哦?

    另外,由于这个地方只考虑如何将训练的image和分割的mask进行统一的变换,类别就先不做讨论了,所以设置

    class_mode=None.

    另外这里没有设置save_to_dir参数,就不保存变换之后的原始图像image和变换之后的mask图像了,后面预览一下即可

    #第二步:分别对训练数据和测试数据使用flow_from_directory方法,由于伪随机性的特质,这里需要
    #为原始数据和mask标注数据提供相同的种子
    seed = 1
    
    image_generator = image_datagen.flow_from_directory(
        'segment_data/source_data/train',
        batch_size=5,
        target_size=(150, 150),
        class_mode=None,  #这个地方将class_mode设置为None,即不返回类别标签
        seed=seed)
    
    mask_generator = mask_datagen.flow_from_directory(
        'segment_data/mask_data/train',
        batch_size=5,
        target_size=(150, 150),
        class_mode=None, #这个地方将class_mode设置为None,即不返回类别标签
        seed=seed)
    
    print('##############################################################')

    3.3 第二步:同时对image和mask进行迭代

    #第三步:迭代查看,这里只查看训练数据集的,测试数据集的就不管了
    # 将生成器组合成一个产生图像和蒙版(mask)的生成器
    train_generator = zip(image_generator, mask_generator)
    
    count=1
    #犹豫期前面没有返回类别标签,这里迭代器只返回原始图像数据和mask对应的数据
    for x_batch_image,x_batch_mask in train_generator:
        print(F"------------开始第{count}次迭代-----------------------------")
        print(F"------------x_batch_image、x_batch_mask的形状如下----------------------")
        print(np.shape(x_batch_image),np.shape(x_batch_mask))
        print(x_batch_image[0])
        print('============================================================')
    
        #将每次augmentation之后的5幅图像显示出来
        for i in range(5):
            plt.subplot(2,5,i+1)
            plt.imshow(x_batch_image[i])  #由于本来就是(150,150,3)的格式,所以不需要再reshape了
            plt.subplot(2,5,5+i+1)
            plt.imshow(x_batch_mask[i])
            #plt.savefig("Scarlett_Johansson_data_iter_time/iter_time_"+str(count)+".png",format="png")
        plt.show()
        count+=1

    这里进行五次迭代,程序运行的结果如下:

    ‘'''
    Using TensorFlow backend.
    Found 15 images belonging to 3 classes.
    Found 15 images belonging to 3 classes.
    ##############################################################
    D:\ProgramData\Anaconda3\envs\tensorflow1.10.0\lib\site-packages\keras_preprocessing\image\image_data_generator.py:699: 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 '
    D:\ProgramData\Anaconda3\envs\tensorflow1.10.0\lib\site-packages\keras_preprocessing\image\image_data_generator.py:707: UserWarning: This ImageDataGenerator specifies `featurewise_std_normalization`, but it hasn't been fit on any training data. Fit it first by calling `.fit(numpy_data)`.
      warnings.warn('This ImageDataGenerator specifies '
    ------------开始第1次迭代-----------------------------
    ------------x_batch_image、x_batch_mask的形状如下----------------------
    (5, 150, 150, 3) (5, 150, 150, 3)
    ============================================================
    ------------开始第2次迭代-----------------------------
    ------------x_batch_image、x_batch_mask的形状如下----------------------
    (5, 150, 150, 3) (5, 150, 150, 3)
    ============================================================
    ------------开始第3次迭代-----------------------------
    ------------x_batch_image、x_batch_mask的形状如下----------------------
    (5, 150, 150, 3) (5, 150, 150, 3)
    ============================================================
    ------------开始第4次迭代-----------------------------
    ------------x_batch_image、x_batch_mask的形状如下----------------------
    (5, 150, 150, 3) (5, 150, 150, 3)
    ============================================================
    ------------开始第5次迭代-----------------------------
    ------------x_batch_image、x_batch_mask的形状如下----------------------
    (5, 150, 150, 3) (5, 150, 150, 3)
    ============================================================
    '''

    注意:中间有一段警告信息,说由于我在构造ImageDataGenerator类的对象的时候,使用了

    featurewise_center=True,

    featurewise_std_normalization=True,

    这两个参数,这就需要从这两个参数的意义说起了,可以参考我前面的系列文章(二),这里不再赘述,简单就是说这里需要使用到样本数据的统计信息,但是因为我这里没有原先的样本数据,所以就没有用,使用了上面的两个参数之后,第一步需要先使用fit()函数在样本数据上进行“拟合”(引号,明白意思就行),根据统计信息进行计算,所以这里会进行警告。

    3.4 变化结果展示

    从上面的结果可以看出,原始图像image和分割标注图像mask的变化是同步进行的,他们的对应关系没有被打乱。

     

    展开全文
  • keras中主要提供了主要的四个模块: (1)......\Lib\site-packages\keras\preprocessing\image.py (这个不完全,完全的详细的参考下面的序号2) (2)......\Lib\site-packages\keras_preprocessing\image.py (3...

    keras中主要提供了主要的四个模块:

    (1)......\Lib\site-packages\keras\preprocessing\image.py   (这个不完全,完全的详细的参考下面的序号2)

    (2)......\Lib\site-packages\keras_preprocessing\image.py 

    (3)......\Lib\site-packages\keras\applications\imagenet_utils.py  (这个不详细,里面就两个方法,详细的参考下面的序号4)

    (4)......\Lib\site-packages\keras_applications\imagenet_utils.py(这其实是一个专门用来处理ImageNet数据的相关工具,里面包含了5个方法,这里就先不去一个一个讨论了)

    其实就是原来老一些版本的keras中都是在keras里面的两个文件中进行处理的,新的keras版本逐渐分别迁移到了keras_preprocessingkeras_applications这两个包里面了。

    鉴于篇幅较多,里面涉及的函数使用较为繁杂,本次将通过系列文章来阐述说明,本篇为系列文章第一篇,介绍图像预处理相关的方法与类,本文介绍......\Lib\site-packages\keras_preprocessing\image.py 这一个文件里面的内容

    一、图像的读、写、存等基本操作

    1、list_pictures()

    原型为:list_pictures(directory, ext='jpg|jpeg|bmp|png|ppm')

    此方法会将一个文件下面的所有图片名称返回,以一个列表的形式,第一个参数为目录名称,第二个为图片的相关拓展名,如下:

    from keras_preprocessing import image
    
    img_directory="data"
    img_list=image.list_pictures(img_directory)
    print(img_list)
    '''运行结果为:
    ['data\\2001.png', 'data\\2002.jpg', 'data\\2003.jpg', 'data\\2004.jpg', 'data\\2005.png']
    '''

    2、load_img()

    函数原型为:

    def load_img(path, grayscale=False, color_mode='rgb', target_size=None,
                 interpolation='nearest'):
        """将图片加载成PIL格式的对象.
    
        #参数列表:
            path: 图片的路径名称,包涵图片名称.
            color_mode:  颜色模式,"grayscale", "rbg", "rgba"三种格式之一默认是"rgb"模式.
            target_size: 默认为None,即保持图像的原始大小,也可以是一个(img_height, img_width)形 
                         式的元组类型,表示新的我要加载进来之后图像的大小.
            interpolation: 当target_size不是原始大小的时候,会对图片进行重采样,支持下面几个参数
                           "nearest", "bilinear", 和 "bicubic".如果PIL 版本在 3.4.0或者是更新的 
                           时候,还支持 "box" and "hamming" 这两个参数. 默认情况下使用“nearest”
    
        # 返回值
            返回PIL.Image类的一个实例,所以具备Image类相关的方法和属性.
    '''
            PIL是老版本的一个python 图像标准库,主要支持python2.x版本,但是在python3中,
    已经更名为pillow库,但是在site-package文件夹之下依然还是使用PIL的文件夹名称,
    可以通过PIL.__version__查看安装的版本,我安装的是6.0.0版本。
    '''
    img_01=image.load_img("data/2001.png")  #img_01 是一个PIL.Image类的实例对象
    print(img_01.format)  # JPEG
    print(img_01.mode)    #RGB
    print(img_01.size)    #(500,537)
    print(img_01.info)    #以字典形式返回图片信息

    3、save_img()

    def save_img(path,
                 x,
                 data_format='channels_last',
                 file_format=None,
                 scale=True,
                 **kwargs):
        """将一个numpy数组保存为图像.
    
        # 参数
            path: Path or file object.
            x: Numpy array.
            data_format: Image data format,
                    either "channels_first" or "channels_last".
            file_format: 图像文件的格式. 如果是默认值None, 图片格式就是图片拓展名默认的格式.
                如果想要重新指定格式,则需要使用该参数;
            scale: 是否需要将像素的值缩放到 `[0, 255]`之间.默认是True,即进行缩放
            **kwargs: Additional keyword arguments passed to `PIL.Image.save()`.
        """

    下面关键看一下使用scale参数与不使用它的区别,自己定义一个numpy数组,定义一张4x4大小的图片,如下:

    #自己定义的一个(4,4,3)的numpy数组
    img_num=np.array([[[10,30,60],[100,120,150],[77,99,130],[200,30,59]],
                      [[40,10,160],[150,120,150],[77,99,130],[100,30,59]],
                      [[20,90,210],[100,220,150],[37,199,230],[210,90,99]],
                      [[100,40,40],[200,50,20],[157,9,140],[50,230,119]]])
    
    image.save_img("data/2006.jpg",img_num,scale=True)  #scale默认为true
    image.save_img("data/2007.jpg",img_num,scale=False) #scale设置为false

    结果如下:

      

    左边是经过缩放到【0,255】的,右边是没有缩放的,可以看出,还是有区别的,下面我们来读取图像进行验证。

    img_06=image.load_img("data/2006.jpg")  #img_01 是一个PIL.Image类的实例对象
    img_07=image.load_img("data/2007.jpg")
    a_06=image.img_to_array(img_06)
    a_07=image.img_to_array(img_07)
    
    print(a_06)
    print('==============================================')
    print(a_07)
    

    4、img_to_array()

    def img_to_array(img, data_format='channels_last', dtype='float32'):
        """将PIL.Image图像对象转化为numpy数组
    
        # 参数
            img: PIL.Image 类的实例
            data_format: Image data format,
                either "channels_first" or "channels_last".
            dtype: Dtype to use for the returned array.
    
        # 返回值
            A 3D Numpy array.
    

    5、array_to_img()

    def array_to_img(x, data_format='channels_last', scale=True, dtype='float32'):
        """将一个3-D的numpy数组转化为一个 PIL.Image对象
    
        # Arguments
            x: Input Numpy array.
            data_format: Image data format.
                either "channels_first" or "channels_last".
            scale: Whether to rescale image values
                to be within `[0, 255]`.
            dtype: Dtype to use.
    
        # 返回值
            A PIL Image instance(一个PIL.Image的实例对象).
        """

     二、图像的裁剪、旋转等预处理操作

    1、随机旋转random_rotation()

    函数原型如下:

    def random_rotation(x, rg, row_axis=1, col_axis=2, channel_axis=0,
                        fill_mode='nearest', cval=0.):
        """随机旋转一个图像.
    
        # Arguments
            x: 输入数组,必须是3D的.
            rg: 旋转角度,比如90,120等等.
            row_axis: 
            col_axis: 
            channel_axis: 
                如果是(channel,row,col)的格式,则分别取值1,2,0,这也是默认情况)
                如果是(row,col,channel)的格式,则分别取值0,1,2,这也是默认情况)
      
            fill_mode: (one of `{'constant', 'nearest', 'reflect', 'wrap'}`).
            cval: 边界之外的像素点的取值
        # Returns
            旋转之后的3D张量tensor
    '''
    需要注意的是,既然称之为“随机旋转”,所以并不是旋转一定的角度,这个角度是随机的,具体是多少,在下面范围【-rg,rg】这个区间内随机取值,如下:
    '''
    from keras_preprocessing import image
    import numpy as np
    
    img_02=image.load_img("data/2002.jpg")  #读取图片,转化成PIL.Image对象
    num_02=image.img_to_array(img_02)       #将PIL.Image对象转化成numpy数组
    num_02_=image.random_rotation(num_02,90,row_axis=0,col_axis=1,channel_axis=2)  #随机旋转【-90,90】
    image.save_img("data/2002_.jpg",num_02_) #保存旋转之后的图片,在这里连续运行两次,得到的结果是不一样的

       

    第一幅是原图,后面两次为随机旋转之后的图片。

    2、随即平移random_shift()

    def random_shift(x, wrg, hrg, row_axis=1, col_axis=2, channel_axis=0,
                     fill_mode='nearest', cval=0.):
        """对一张图片进行随机的空间平移.
    
        # Arguments
            x: 3D数组.
            wrg: 宽度方向的移动范围.注意这里的取值虽然没有范围,但是一般约束在【0,1】之间,因为他指的是平移的像素占宽度的比值,如果太大,图像完全移动到了看不见的位置,下面的hrg也是一样的
            hrg: 高度方向的移动范围.
           其他参数同上面是一样的
        # Returns
            Shifted Numpy image tensor.
        """
    img_03=image.load_img("data/2003.jpg")  #读取图片,转化成PIL.Image对象
    num_03=image.img_to_array(img_03)       #将PIL.Image对象转化成numpy数组
    num_03_=image.random_shift(num_03,0.2,0.3,row_axis=0,col_axis=1,channel_axis=2)  #随机平移
    image.save_img("data/2003_.jpg",num_03_) #保存平移之后的图片,在这里连续运行两次,得到的结果是不一样的

       

    左边是原始图像,右边是经过评议之后的图像,可以看出往左下角进行了一定的平移。

    3、随机错切random_shear()

    def random_shear(x, intensity, row_axis=1, col_axis=2, channel_axis=0,
                     fill_mode='nearest', cval=0.):
        """随机剪切.
    
        # Arguments
            x: Input tensor. Must be 3D.
            intensity: Transformation intensity in degrees.
          
        # Returns
            Sheared Numpy image tensor.
        """
    img_04=image.load_img("data/2004.jpg")  #读取图片,转化成PIL.Image对象
    num_04=image.img_to_array(img_04)       #将PIL.Image对象转化成numpy数组
    num_04_=image.random_shear(num_04,60,row_axis=0,col_axis=1,channel_axis=2)  #随机剪切
    image.save_img("data/2004_.jpg",num_04_) #保存变化之后的图片,

      

    4、随机缩放random_zoom()

    def random_zoom(x, zoom_range, row_axis=1, col_axis=2, channel_axis=0,
                    fill_mode='nearest', cval=0.):
        """随机缩放.
    
        # Arguments
            x: Input tensor. Must be 3D.
            zoom_range: Tuple of floats; zoom range for width and height.即(width,height)
            
        # Returns
            Zoomed Numpy image tensor.
        """
    img_05=image.load_img("data/2005.png")  #读取图片,转化成PIL.Image对象
    num_05=image.img_to_array(img_05)       #将PIL.Image对象转化成numpy数组
    num_05_=image.random_zoom(num_05,(0.5,0.5),row_axis=0,col_axis=1,channel_axis=2)  
    image.save_img("data/2005_.jpg",num_05_) #保存旋转之后的图片

    5、transform_matrix_offset_center(matrix, x, y)方法

    根据一个“仿射矩阵”来计算变换之后的图像

    这里面涉及到仿射变换的数学思想,这里就不再展开讨论了。

    6、仿射变换apply_affine_transform()

    def apply_affine_transform(x, theta=0, tx=0, ty=0, shear=0, zx=1, zy=1,
                               row_axis=0, col_axis=1, channel_axis=2,
                               fill_mode='nearest', cval=0.):
        """Applies an affine transformation specified by the parameters given.
    
        # Arguments
            x: 2D numpy array, single image.
            theta: Rotation angle in degrees.
            tx: Width shift.
            ty: Heigh shift.
            shear: Shear angle in degrees.
            zx: Zoom in x direction.
            zy: Zoom in y direction
            row_axis: Index of axis for rows in the input image.
            col_axis: Index of axis for columns in the input image.
            channel_axis: Index of axis for channels in the input image.
            fill_mode: Points outside the boundaries of the input
                are filled according to the given mode
                (one of `{'constant', 'nearest', 'reflect', 'wrap'}`).
            cval: Value used for points outside the boundaries
                of the input if `mode='constant'`.
    
        # Returns
            The transformed version of the input.
        """

    “仿射变换”是通过一系列的原子变换综合实现的,平移(Translation)、缩放(Scale)、旋转(Rotation)、翻转(Flip)、错切(Shear)等.

    补充点:

    图像的变换模型是指根据待匹配图像与背景图像之间几何畸变的情况,所选择的能最佳拟合两幅图像之间变化的几何变换模型。可采用的变换模型有如下几种:刚性变换、仿射变换、透视变换和非线形变换等,如下图:

    image

    我们常见的图像变换有图像的几何变换——拉伸、收缩、扭曲、旋转(stretch,shrink,distortion,rotation),拉伸、收缩、扭曲、旋转是图像的几何变换,在三维视觉技术中大量应用到这些变换,又分为仿射变换和透视变换。

    仿射变换(Affine transformation)

    透视变换(Perspective transformation)

    7、其他方法

    由于keras中本身提供的图像预处理的方法有限,不是特别多,所以后面还剩几个类似的方法就不再一一给出实例了,在这里统一归纳如下:

    def apply_channel_shift(x, intensity, channel_axis=0):
    
    def random_channel_shift(x, intensity_range, channel_axis=0):
    
    def apply_brightness_shift(x, brightness):
      
    def random_brightness(x, brightness_range):
    
    def flip_axis(x, axis):

    总结:上面的这些方法全部都在:keras_preprocessing\image.py 这个文件里面哦,只需要

    import keras.preprocessing import image 即可。

     

    展开全文
  • 跑实验时候,要准备自己的数据集,keras的接口方式还是比较友善的,对图像的数据预处理有两种方式:一种是.flow(),另一种是.flow_from_directory(directory)。 关键导入包: import keras from tensorflow....

    跑实验时候,要准备自己的数据集,keras的接口方式还是比较友善的,对图像的数据预处理有两种方式:一种是.flow(),另一种是.flow_from_directory(directory)。

    关键导入包:

    import keras
    from tensorflow.keras.preprocessing.image import ImageDataGenerator
    import keras.utils as np_utils

    .flow()的方式

    此时数据集是已经处理成了数组的形式,如我们从网上下载的公开数据集(nums, col,row,channel)。

    (X_train, y_train), (X_test, y_test) = cifar10.load_data()
    Y_train = np_utils.to_categorical(y_train, nb_classes)
    Y_test = np_utils.to_categorical(y_test, nb_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),
                        samples_per_epoch=len(X_train), nb_epoch=nb_epoch)
    
    # here's a more "manual" example(手动分批次训练)
    for e in range(nb_epoch):
        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

    .flow_from_directory(directory)的方式

    这种方式是从文件夹里读入图片,此时传入的文件夹(directory)的路径是数据集总路径,里面包含若干个直接以分类类别命名的子文件夹,各个类别的图片放好在各自所属类别的文件夹里面。代码读入数据成矩阵的同时,根据类别文件夹名字把数据集的class字典做好。目录结构如下图:

    └─train
        ├─class1_name
        │      xxr.jpg
        │      xxx.jpg
        │
        ├─class2_name
        │      xxr.jpg
        │      xxx.jpg
        │
        └─class3_name
                xxr.jpg
                xxx.jpg

     

    train_datagen = ImageDataGenerator(
            rescale=1./255,
            shear_range=0.2,
            zoom_range=0.2,
            horizontal_flip=True)
    
    test_datagen = ImageDataGenerator(rescale=1./255)
    
    train_generator = train_datagen.flow_from_directory(
            'data/train',
            target_size=(150, 150),
            batch_size=32,
            class_mode='binary')
    
    validation_generator = test_datagen.flow_from_directory(
            'data/validation',
            target_size=(150, 150),
            batch_size=32,
            class_mode='binary')
    
    model.fit_generator(
            train_generator,
            samples_per_epoch=2000,
            nb_epoch=50,
            validation_data=validation_generator,
            nb_val_samples=800)

    当然,更多信息可以直接看中文文档:https://keras-cn.readthedocs.io/en/latest/

     

     

    展开全文
  • 上一篇文章介绍了keras图像预处理的核心类—— ImageDataGenerator 类,其实关于keras的图像预处理与图像generator都是通过这个类来实现的,第一篇文章介绍的相关方法都是为这个类服务的辅助方法,本文要介绍的几个...

     

    上一篇文章介绍了keras图像预处理的核心类—— ImageDataGenerator 类 ,其实关于keras的图像预处理与图像generator都是通过这个类来实现的,第一篇文章介绍的相关方法都是为这个类服务的辅助方法,本文要介绍的几个类都是为 ImageDataGenerator 类服务的辅助类,所以在实际应用中,一般不需要用到辅助方法与辅助类,只需要使用ImageDataGenerator 类 即可,但是对于了解源码的架构,去了解一下这些辅助方法也是很有好处的。本篇文章来看一看那几个重要的辅助类。

    一、image.py的借口框架图

    主要使用的ImageDataGenerator 类 以及与之相关的辅助函数与辅助类之间的关系如下:

    二、几个关键辅助类的介绍

    在前面介绍ImageDataGenerator类的时候,里面有三个非常核心的方法,它们分别是flow、flow_from_directory、flow_from_dataframe,实际上它们每一个方法的实现都是通过下面的三个辅助类去实现的,对应关系如下:

    • flow()方法。由NumpyArrayIterator类去实现;
    • flow_from_directory()方法。由DirectoryIterator类去实现;
    • flow_from_dataframe方法。由DataFrameIterator类去实现

    而后面的三个辅助类又是继承了基类Iterator基类的。

    2.1 Iterator基类型

    class Iterator(IteratorType):
        """实现图像数据迭代的基类型.
    
        没一个继承自Iterator基类的子类型都必须实现 _get_batches_of_transformed_samples方法。
        # 构造函数参数
            n: Integer, 需要迭代的数据的总数
            batch_size: Integer, 没一个迭代轮次的batch的大小
            shuffle: Boolean, 在每一次迭代某个批次的数据的时候,是否需要混洗
            seed: shuffle的随机种子
        """

    2.2 NumpyArrayIterator类

    ImageDataGenerator类里面的flow方法就是通过这个类来实现的,类的定义如下:

    class NumpyArrayIterator(Iterator):
        """Iterator yielding data from a Numpy array.
    
        # 构造函数参数
            x: Numpy array of input data or tuple.
                If tuple, the second elements is either
                another numpy array or a list of numpy arrays,
                each of which gets passed
                through as an output without any modifications.
            y: Numpy array of targets data.
            image_data_generator: Instance of `ImageDataGenerator`
                to use for random transformations and normalization.
            batch_size: Integer, size of a batch.
            shuffle: Boolean, whether to shuffle the data between epochs.
            sample_weight: Numpy array of sample weights.
            seed: Random seed for data shuffling.
            data_format: String, one of `channels_first`, `channels_last`.
            save_to_dir: Optional directory where to save the pictures
                being yielded, in a viewable format. This is useful
                for visualizing the random transformations being
                applied, for debugging purposes.
            save_prefix: String prefix to use for saving sample
                images (if `save_to_dir` is set).
            save_format: Format to use for saving sample images
                (if `save_to_dir` is set).
            subset: Subset of data (`"training"` or `"validation"`) if
                validation_split is set in ImageDataGenerator.
            dtype: Dtype to use for the generated arrays.
        """

    2.3 DirectoryIterator类

    ImageDataGenerator类里面的flow_from_directory方法就是通过这个类来实现的,类的定义如下:

    class DirectoryIterator(Iterator):
        """Iterator capable of reading images from a directory on disk.
    
        # Arguments
            directory: Path to the directory to read images from.
                Each subdirectory in this directory will be
                considered to contain images from one class,
                or alternatively you could specify class subdirectories
                via the `classes` argument.
            image_data_generator: Instance of `ImageDataGenerator`
                to use for random transformations and normalization.
            target_size: tuple of integers, dimensions to resize input images to.
            color_mode: One of `"rgb"`, `"rgba"`, `"grayscale"`.
                Color mode to read images.
            classes: Optional list of strings, names of subdirectories
                containing images from each class (e.g. `["dogs", "cats"]`).
                It will be computed automatically if not set.
            class_mode: Mode for yielding the targets:
                `"binary"`: binary targets (if there are only two classes),
                `"categorical"`: categorical targets,
                `"sparse"`: integer targets,
                `"input"`: targets are images identical to input images (mainly
                    used to work with autoencoders),
                `None`: no targets get yielded (only input images are yielded).
            batch_size: Integer, size of a batch.
            shuffle: Boolean, whether to shuffle the data between epochs.
            seed: Random seed for data shuffling.
            data_format: String, one of `channels_first`, `channels_last`.
            save_to_dir: Optional directory where to save the pictures
                being yielded, in a viewable format. This is useful
                for visualizing the random transformations being
                applied, for debugging purposes.
            save_prefix: String prefix to use for saving sample
                images (if `save_to_dir` is set).
            save_format: Format to use for saving sample images
                (if `save_to_dir` is set).
            subset: Subset of data (`"training"` or `"validation"`) if
                validation_split is set in ImageDataGenerator.
            interpolation: Interpolation method used to resample the image if the
                target size is different from that of the loaded image.
                Supported methods are "nearest", "bilinear", and "bicubic".
                If PIL version 1.1.3 or newer is installed, "lanczos" is also
                supported. If PIL version 3.4.0 or newer is installed, "box" and
                "hamming" are also supported. By default, "nearest" is used.
            dtype: Dtype to use for generated arrays.
        """

    2.4 DateFrameIterator类

    ImageDataGenerator类里面的flow_from_dateframe方法就是通过这个类来实现的,类的定义如下:

    class DataFrameIterator(Iterator):
        """Iterator capable of reading images from a directory on disk
            through a dataframe.
    
        # Arguments
            dataframe: Pandas dataframe containing the filenames of the
                       images in a column and classes in another or column/s
                       that can be fed as raw target data.
            directory: Path to the directory to read images from.
                Each subdirectory in this directory will be
                considered to contain images from one class,
                or alternatively you could specify class subdirectories
                via the `classes` argument.
                if used with dataframe,this will be the directory to under which
                all the images are present.
            image_data_generator: Instance of `ImageDataGenerator`
                to use for random transformations and normalization.
            x_col: Column in dataframe that contains all the filenames.
            y_col: Column/s in dataframe that has the target data.
            has_ext: bool, Whether the filenames in x_col has extensions or not.
            target_size: tuple of integers, dimensions to resize input images to.
            color_mode: One of `"rgb"`, `"rgba"`, `"grayscale"`.
                Color mode to read images.
            classes: Optional list of strings, names of
                each class (e.g. `["dogs", "cats"]`).
                It will be computed automatically if not set.
            class_mode: Mode for yielding the targets:
                `"binary"`: binary targets (if there are only two classes),
                `"categorical"`: categorical targets,
                `"sparse"`: integer targets,
                `"input"`: targets are images identical to input images (mainly
                    used to work with autoencoders),
                `"other"`: targets are the data(numpy array) of y_col data
                `None`: no targets get yielded (only input images are yielded).
            batch_size: Integer, size of a batch.
            shuffle: Boolean, whether to shuffle the data between epochs.
            seed: Random seed for data shuffling.
            data_format: String, one of `channels_first`, `channels_last`.
            save_to_dir: Optional directory where to save the pictures
                being yielded, in a viewable format. This is useful
                for visualizing the random transformations being
                applied, for debugging purposes.
            save_prefix: String prefix to use for saving sample
                images (if `save_to_dir` is set).
            save_format: Format to use for saving sample images
                (if `save_to_dir` is set).
            subset: Subset of data (`"training"` or `"validation"`) if
                validation_split is set in ImageDataGenerator.
            interpolation: Interpolation method used to resample the image if the
                target size is different from that of the loaded image.
                Supported methods are "nearest", "bilinear", and "bicubic".
                If PIL version 1.1.3 or newer is installed, "lanczos" is also
                supported. If PIL version 3.4.0 or newer is installed, "box" and
                "hamming" are also supported. By default, "nearest" is used.
        """

     

    展开全文
  • keras中如何进行图像预处理并生成一个generator

    千次阅读 热门讨论 2018-12-21 19:15:33
    接下来,给出我自己目前积累的代码,从目录中自动读取图像,并产生generator: 第一步:建立好目录结构和图像 可以看到目录images_keras_dict下有次级目录,次级目录下就直接包含照片了 **第二步:写代码建立...
  • 本文目录1. 简介2. ImageDataGenerator类介绍使用示例3. ImageDataGenerator类方法3.1 fit()3.2 flow()3.3 flow_from_directory()3.4 flow_from_dataframe()3.5 standardize()4. 具体使用4.1 示例14.2 对数据进行去...
  • keras进行图像预处理

    千次阅读 2019-01-25 13:57:36
    转载自:图像预处理、增强   图片预处理 图片生成器ImageDataGenerator keras.preprocessing.image.ImageDataGenerator(featurewise_center=False, samplewise_center=False, featurewise_std_normalization...
  • 上一篇文章已经详细介绍了keras进行图像预处理的一些常规操作,但是有一个问题就是上面的那些方法都是针对一张图片进行操作的,我们在深度学习的时候,当然也可以事先先一张一张将图片进行预处理,然后再将图片放入...
  • keras分类猫狗数据(上)数据预处理

    千次阅读 热门讨论 2020-05-12 17:58:06
    keras分类猫狗数据(上)数据预处理 keras分类猫狗数据(中)使用CNN分类模型 keras分类猫狗数据(下)迁移学习 数据来源:https://www.kaggle.com/c/dogs-vs-cats 在本部分数据预处理,下载train.zip并解压...
  • 1、图片预处理
  • keras的基本用法(五)——图像predict

    万次阅读 2017-06-12 15:57:57
    keras的基本用法(五)——图像predict
  • 人工智能框架实战精讲:Keras项目

    千人学习 2020-06-24 14:27:13
    进入学习群,获取唐宇迪老师答疑 ...2.加载与预处理细胞图像数据 3.构建完成分类模型并进行测试识别 (注意: 作业需写在CSDN博客中,请把作业链接贴在评论区,老师会定期逐个批改~~)
  • 前言:初学图像识别,由于条件限制及代码的可读性,在知乎上找了一篇使用keras编写Faster-RCNN,进行修改后实现宠物狗识别的例子,原文链接https://zhuanlan.zhihu.com/p/31730165,这是一个系列,从数据的预处理到...
  • 1. 使用keras包 使用keras包下面preprocessing中的image中的load_img和img_to_array方法 from keras.preprocessing.image import load_img,img_to_array #path 为图片路径 #target_size为将图片转换为指定像素图片 ...
  • 当在做使用神经网络做分类(或回归)问题时,...使用tf.keras.applacations可以轻松地进行迁移学习,下面用VGG19模型举例。 直接使用模型(包含分类层) 对输入的图片进行预处理 因为输入VGG19的图片需要满足VGG1...
  • from keras.datasets import mnist 我们用mnist为例, MNIST手写数字数据库有60000个示例的训练集和10000个示例的测试集。数字已被规格化,并在固定大小的图像中居中。 它是一个很好的数据库,供那些想尝试在实际...
  • keras 数据读取几种方式

    千次阅读 2019-06-05 16:56:07
    keras数据读取(图像数据)的方式,可以不使用keras的方法而使用opencv或者pil直接读取做处理。这里主要总结了keras封装的几种图像数据读取方法, 一、keras.preprocessing.image.load_img()读取单张图像 1)load_...
  • 相信大家经过之前几篇文章的学习,已经对人工智能以及它和Keras的关系有了基本的认识,那么我们即将正式开始对于Keras的学习。 Keras是非常优秀的神经网络框架,他提供简单的API的同时也不失灵活性,适合多层次人群...
  • Keras model.predict

    万次阅读 热门讨论 2020-05-30 11:25:32
    #模型预测,输入测试集,输出预测结果 y_pred = model.predict(X_test,batch_size = 1) predict_test = model.predict(X_test) predict = argmax(predict_test,axis=1) #axis = 1是取行的最大值的索引,0是列...
  • Keras学习---数据预处理

    万次阅读 2017-07-14 11:29:56
    数据预处理是必要的,这里以MNIST dataset的输入数据预处理为例。 后续增加对文本的预处理说明。 1. 设置随机种子 np.random.seed(1337) # for reproducibility 2. 输入数据维度规格化 X_train = X_train....
1 2 3 4 5 ... 20
收藏数 4,934
精华内容 1,973
关键字:

keras图像预处理