使用 Tensorflow 预测单个图像不准确

Predicting single image using Tensorflow not being accurate

我正在尝试建立一个 CNN 模型来对图像进行分类,但是每当训练完成并且我尝试向它提供单个图像(来自训练数据集)时,它总是错误地分类该图像。

请看下面我写的代码

提前谢谢你。

首先,我为我的训练集和测试集声明了一个图像数据生成器:

train_datagen = ImageDataGenerator(rescale = 1./255, rotation_range=20, horizontal_flip = True, 
validation_split=0.3)

test_datagen = ImageDataGenerator(rescale = 1./255,validation_split=0.3)

然后,我使用 flow_from_directory() 函数加载图像:

train_generator = train_datagen.flow_from_directory(
data_dir,
shuffle=False,
subset='training',
target_size = (224, 224), 
class_mode = 'categorical'
)

test_generator = test_datagen.flow_from_directory(
data_dir,
shuffle=False,
subset='validation',
target_size = (224, 224),
class_mode = 'categorical'
)

然后我加载了一个预训练模型并添加了几层来构建我的模型:

pretrained_model = VGG16(weights="imagenet", include_top=False, 

input_tensor=input_shape)
pretrained_model.trainable = False

model = tf.keras.Sequential([
    pretrained_model,
    Flatten(name="flatten"),
    Dense(3, activation="softmax")
])

然后我训练了模型:

INIT_LR = 3e-4
EPOCHS = 15
opt = Adam(lr=INIT_LR)

model.compile(loss="categorical_crossentropy", optimizer='Adam', metrics=["accuracy"])

H = model.fit(
    train_generator,
    validation_data=test_generator,
    epochs=EPOCHS,
    verbose= 1)

接下来是预测单张图片的部分:

我选择了作为训练集一部分的图像,我什至过度拟合了模型以确保预测应该是正确的,但是对于我输入到模型的每张图像,它都给我错误的结果。

我尝试了以下方法:

image = image.load_img(url,target_size = (224, 224))
img = tf.keras.preprocessing.image.img_to_array(image)
img = np.array([img])
img = img.astype('float32') / 255.
img = tf.keras.applications.vgg16.preprocess_input(img)

这没用

image = cv2.imread(url)
image = cv2.normalize(image, None,beta=255, dtype=cv2.CV_32F)
image = cv2.resize(image, (224, 224))
image = np.expand_dims(image, axis=0)

这也没有用,我也尝试了许多其他方法来预测单个图像,但 none 有效。

最后,唯一的方法是我必须为这个单一图像创建一个图像数据生成器和 Flow From Directory,它起作用了,但我认为不应该这样做。

这个答案可能是一个起点:

这些是可能的差异(简短要点):

  1. RGB 对比 BGROpenCV 加载 BGR)
  2. 使用的插值方法(INTER_LINEAR vs INTER_NEAREST)。
  3. img_to_array() 将数据类型转换为 float32 而不是 uint8 ,这是在使用 OpenCV.
  4. 加载时默认获得的 uint8
  5. tf.keras.applications.vgg16.preprocess_input(img)。这个预处理函数实际上可能与你上面写的图像预处理不同;还值得注意的是,如果您在以这种特定方式 (preprocess_input()) 训练时不对其进行预处理,那么在测试集上出现不良结果也是有道理的,因为预处理是不同的。

希望这些观察能有所启发。

代码img = tf.keras.applications.vgg16.preprocess_input(img)缩放像素 假设原始像素值在 0 到 255 范围内,图像中的值到 -1 到 +1 之间的值。在上一行代码中

img = img.astype('float32') / 255.

您重新缩放了像素。所以删除那行代码。现在要预测单个图像,您需要使用

扩展维度
img = np.expand_dims(img, axis=0) 

在您的第二次代码工作中,请注意 CV2 将图像读入为 BGR。如果您的模型是在 RGB 图像上训练的,那么您的预测将是错误的。使用下面的代码将图像转换为 RGB。

image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

作为旁注,您可以将 tf.keras.applications.vgg16.preprocess_input(img) 替换为下面的函数,它将在 -1 到 +1

之间缩放图像
def scalar(img):
    return img/127.5 - 1