【问题标题】:How Does Tensorflow.keras's ImageDataGenerator.flow_from_directory scale image values?Tensorflow.keras 的 ImageDataGenerator.flow_from_directory 如何缩放图像值?
【发布时间】:2021-02-14 23:49:30
【问题描述】:

我有一个训练有素的 tensorflow 模型,在制作训练数据库时,我使用了

from tensorflow.keras.preprocessing.image import ImageDataGenerator
ImageDataGenerator.flow_from_directory(organized_dir,
                                       target_size=(image_dim, image_dim),
                                       color_mode="grayscale",
                                       batch_size=20,
                                       shuffle=True,
                                       follow_links=True)

(我只是显示我选择提供的参数,image_dim 等变量在别处定义)

当我在函数返回的 DirectoryIterator 对象上使用next() 查看其中一个批次时,图像的像素值似乎从其原始 rgb 值 [0,255] 缩放到灰度 [0,1]。我希望它是灰度的,我的理解是 ML 模型在 0 到 1 之间的数字上表现最好。太棒了!

但是,现在我想在不同的图像上使用模型。在cv2 中打开它们并转换为灰度不会像 tensorflow 那样缩放像素值,它只是将颜色值保持在 [0,255] 而不是 [0,1]:

>>> z = cv2.imread("img.png")
>>> cv2.cvtColor(z, cv2.COLOR_BGR2GRAY)
array([[255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255],
       ...,
       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255]], dtype=uint8)

所以,我要问的是如何使用 tensorflow 的数据集使用的相同转换来使图像使用从 [0,255] 到 [0,1] 的像素值。我在这里发现我可以标准化图像:Normalizing images in OpenCV。但我想使用 tensorflow 使用的确切算法/参数,这样我就可以最大限度地提高我在现实世界中的准确性。谢谢??????

【问题讨论】:

    标签: python tensorflow opencv keras tf.keras


    【解决方案1】:

    您对 ImageDataGenerator 重新缩放图像像素值的看法不正确。根据文档,生成器有一个名为 rescale 的参数。对于此参数,文档说明:

    rescale: rescaling factor. Defaults to None. If None or 0, no rescaling is applied,
     otherwise we multiply the data by the value provided
     (after applying all other transformations).
    

    所以要将值从 0 重新调整为 1,然后使用

    rescale=1/255
    

    迁移学习中使用的许多模型要求像素值介于 -1 和 +1 之间。 对于这种情况,请使用

    rescale=1/127.5-1
    

    您正在读取的图像可能已经重新调整了像素值。测试您的图像是否经过预缩放使用

    import numpy as np
    import cv2
    path_to_file=        #specify the full path to the file
    img=cv2.imread(path_to_file,0)# read in image as grayscale
    max_pixel_value=np.max(img) #  find maximum pixel value
    min_pixel_value=np.min(img) # find minimum pixel value
    print('max pixel value= ', max_pixel_value, '  min pixel value= ', min_pixel_value)
    

    【讨论】:

    • 这是有道理的,但为什么 cv2 imread() 会给出 0 到 255 之间的像素值?
    • 另外,有没有办法检查像素值是否已经重新缩放?
    • 查看更新的答案。我已经验证生成器不会重新缩放像素值,除非您指定重新缩放参数的值。
    • @Vladimir Kulyashov 似乎是正确的 cv2 将它们读取为dtype=uint8,尽管您对我的问题有正确的答案。
    【解决方案2】:

    cv2.imread() 将图像读取为数据类型为 uint8 的 np.array。这就是为什么您拥有从 0 到 255 的所有值。要将值重新调整为 [0, 1] 只需将它们除以 255

    In[1]: import cv2
      ...: import numpy as np
    In[2]: img = cv2.imread('some_image.jpg')
    In[3]: img
    Out[3]: 
    array([[[110,  89,  92],
            [110,  89,  92],
            [ 50,  29,  32],
            ...
    
    In[4]: type(img)
    Out[4]: numpy.ndarray
    
    In[5]: img.dtype
    Out[5]: dtype('uint8')
    
    In[6]: img = (img / 255)
    In[7]: np.min(img), np.max(img)
    Out[7]: (0.0, 1.0)
    
    In[8]: img
    Out[8]: 
    array([[[0.43137255, 0.34901961, 0.36078431],
            [0.43137255, 0.34901961, 0.36078431],
            [0.19607843, 0.11372549, 0.1254902 ],
            ...
    
    In[9]: img.dtype
    Out[9]: dtype('float64')
    

    这是来自 ImageDataGenerator 文档字符串的引用:

    rescale:重新缩放因子。默认为无。 如果 None 或 0,则不应用重新缩放, 否则我们将数据乘以提供的值 (在应用所有其他转换之后)

    所以你的问题的答案是:只需将你的数组乘以 1/255,你就会得到与 ImageDataGenerator 返回的结果相同的结果

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-07
      • 2013-05-29
      • 2011-02-25
      • 1970-01-01
      • 1970-01-01
      • 2014-09-04
      • 1970-01-01
      相关资源
      最近更新 更多