Tensorflow.keras 的 ImageDataGenerator.flow_from_directory 如何缩放图像值?

How Does Tensorflow.keras's ImageDataGenerator.flow_from_directory scale image values?

我有一个经过训练的张量流模型,在制作训练数据库时,我使用了

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等变量在别处定义)

当我在函数 returns 的 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] 的像素值。我在这里发现我可以规范化图像:。但我想使用 tensorflow 使用的确切 algorithm/parameters,这样我就可以最大限度地提高我在现实世界中的准确性。谢谢

关于 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() 将图像读取为数据类型为 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: 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)

所以您的问题的答案是:只需将您的数组乘以 1/255,您将得到与 ImageDataGenerator returns

相同的结果