Joe*_*Joe 8 python opencv machine-learning keras tensorflow
我想使用使用 OpenCV 的 Keras Resnet50 模型来读取和调整输入图像的大小。我正在使用来自 Keras 的相同预处理代码(使用 OpenCV,我需要转换为 RGB,因为这是 preprocess_input() 期望的格式)。我使用 OpenCV 和 Keras 图像加载得到的预测略有不同。我不明白为什么预测不一样。
这是我的代码:
import numpy as np
import json
from tensorflow.keras.applications.resnet50 import ResNet50
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.resnet50 import preprocess_input, decode_predictions
import cv2
model = ResNet50(weights='imagenet')
img_path = '/home/me/squirle.jpg'
# Keras prediction
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
preds = model.predict(x)
print('Predicted Keras:', decode_predictions(preds, top=3)[0])
# OpenCV prediction
imgcv = cv2.imread(img_path)
dim = (224, 224)
imgcv_resized = cv2.resize(imgcv, dim, interpolation=cv2.INTER_LINEAR)
x = cv2.cvtColor(imgcv_resized , cv2.COLOR_BGR2RGB)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
preds = model.predict(x)
print('Predicted OpenCV:', decode_predictions(preds, top=3)[0])
Predicted Keras: [('n02490219', 'marmoset', 0.28250763), ('n02356798', 'fox_squirrel', 0.25657368), ('n02494079', 'squirrel_monkey', 0.19992349)]
Predicted OpenCV: [('n02356798', 'fox_squirrel', 0.5161952), ('n02490219', 'marmoset', 0.21953616), ('n02494079', 'squirrel_monkey', 0.1160824)]
Run Code Online (Sandbox Code Playgroud)
如何使用 OpenCVimread()并resize()获得与 Keras 图像加载相同的预测?
# Keras prediction
img = image.load_img(img_path, target_size=(224, 224))
# OpenCV prediction
imgcv = cv2.imread(img_path)
dim = (224, 224)
imgcv_resized = cv2.resize(imgcv, dim, interpolation=cv2.INTER_LINEAR)
Run Code Online (Sandbox Code Playgroud)
如果仔细看,你在 cv2 的情况下指定的插值是cv2.INTER_LINEAR(双线性插值);但是,默认情况下,
image.load_img()使用INTER_NEAREST插值方法。
img_to_array(img). dtype这里的论点是:无
默认为 None,在这种情况下使用全局设置 tf.keras.backend.floatx() (除非你改变它,它默认为“float32”)
因此,img_to_array(img)您有一个由float32值组成的图像,而cv2.imread(img)返回一个 numpyuint8值数组。
image = image[:,:,::-1]或image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB); 否则,您将颠倒 R 和 B 通道,从而导致不正确的比较。由于您应用的预处理在两种情况下都是相同的,唯一的区别是我上面提到的那些;调整这些变化应确保可重复性。
我想做出一个观察:假设一个库(cv2在这种情况下)自动(并且可以说只加载整数)而不是浮点数,唯一正确的方法是将第一个预测数组(Keras)转换为,uint8因为通过将后者强制转换为float32,信息中可能存在的差异将丢失。例如,当cv2您加载到uint8,并通过强制转换而不是233获取233.0. 然而,也许初始像素值是233,3但由于第一次转换而丢失了。