为了账号安全,请及时绑定邮箱和手机立即绑定

当使用 OpenCV 完成图像加载和调整大小时,Resnet50 会产生不同的预测

当使用 OpenCV 完成图像加载和调整大小时,Resnet50 会产生不同的预测

素胚勾勒不出你 2023-09-26 16:23:14
我想使用 Keras Resnet50 模型和 OpenCV 来读取输入图像并调整其大小。我使用 Keras 中的相同预处理代码(对于 OpenCV,我需要转换为 RGB,因为这是 preprocess_input() 期望的格式)。我使用 OpenCV 和 Keras 图像加载得到的预测略有不同。我不明白为什么预测不一样。这是我的代码:import numpy as npimport jsonfrom tensorflow.keras.applications.resnet50 import ResNet50from tensorflow.keras.preprocessing import imagefrom tensorflow.keras.applications.resnet50 import preprocess_input, decode_predictionsimport cv2model = ResNet50(weights='imagenet')img_path = '/home/me/squirle.jpg'# Keras predictionimg = 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 predictionimgcv = 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)]如何使用 OpenCVimread()并resize()获得与 Keras 图像加载相同的预测?
查看完整描述

2 回答

?
森栏

TA贡献1810条经验 获得超5个赞

# 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)

  1. 如果你仔细看的话,你在cv2的情况下指定的插值是cv2.INTER_LINEAR(双线性插值);但是,默认情况下 image.load_img()使用INTER_NEAREST插值方法。

  2. img_to_array(img)。这里的参数dtype是:无

默认为 None,在这种情况下使用全局设置 tf.keras.backend.floatx() (除非您更改它,否则它默认为“float32”)

因此,img_to_array(img)您有一个由值组成的图像float32,而cv2.imread(img)返回一个值的 numpy 数组uint8

  1. 确保从 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,但由于第一次转换而丢失了。



查看完整回答
反对 回复 2023-09-26
?
慕仙森

TA贡献1827条经验 获得超7个赞

Keras 以RGB格式加载图像,而 OpenCV 以BGR格式加载图像。

ResNet50的预处理函数使用caffe设置,它期望图像为RGB格式,并应用以下内容:

  1. 反转通道(RGB -> BGR)

  2. 从各自的值中减去 [103.939, 116.779, 123.68]

由于每个通道要减去的值不同,因此通道顺序很重要。此外,预训练的ResNet50 模型的各层已经按照一定的顺序进行了训练。

因此,使用 OpenCV 加载图像时,必须将通道顺序从BGR反转为RGB

imgcv_resized =  imgcv_resized[:,:,::-1]


查看完整回答
反对 回复 2023-09-26
  • 2 回答
  • 0 关注
  • 87 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信