我想使用OpenCV读取和调整输入图像的大小来使用Keras的Resnet50模型。我使用了来自Keras的相同预处理代码(使用OpenCV时,我需要转换为RGB,因为这是preprocess_input()
期望的格式)。使用OpenCV和Keras加载图像时,我得到了略有不同的预测。我不明白为什么预测结果不一样。
这是我的代码:
如何使用OpenCV的imread()
和resize()
来获得与Keras图像加载相同的预测结果?
回答:
# Keras predictionimg = image.load_img(img_path, target_size=(224, 224)) # OpenCV predictionimgcv = cv2.imread(img_path)dim = (224, 224)imgcv_resized = cv2.resize(imgcv, dim, interpolation=cv2.INTER_LINEAR)
-
如果你仔细观察,在使用cv2的情况下,你指定的插值方法是
cv2.INTER_LINEAR
(双线性插值);然而,默认情况下,image.load_img()
使用的是INTER_NEAREST
插值方法。 -
img_to_array(img)
。这里的dtype
参数是:None
默认值为None,在这种情况下会使用全局设置tf.keras.backend.floatx()(除非你更改了它,默认值为”float32″)
因此,在img_to_array(img)
中,你得到的是由float32
值组成的图像,而cv2.imread(img)
返回的是uint8
值的numpy数组。
- 确保从BGR转换为RGB,因为OpenCV直接加载为BGR格式。你可以使用
image = image[:,:,::-1]
或image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
;否则,你会得到反转的R和B通道,导致比较结果不正确。
由于你在这两种情况下应用的预处理是相同的,上面提到的差异是唯一的不同之处;调整这些变化应该能确保结果的可重复性。
我想指出一个观察:假设使用一个库(在本例中是cv2
),它自动(并且可能只加载整数而不是浮点数),唯一正确的方法是将第一个预测数组(Keras)转换为uint8
,因为将后者转换为float32
会丢失可能的信息差异。例如,使用cv2
加载到uint8
,通过转换而不是233
你得到233.0
。然而,初始像素值可能是233.3
,但由于第一次转换而丢失了。