我正在尝试使用 keras 构建分类模型并将模型部署到我的 Android 手机。我使用该网站上的代码将我自己的转换模型(一个 .pb 文件)部署到我的 Android 手机。我从手机加载图像,一切正常,但预测结果与我从 PC 得到的结果完全不同。
在我的电脑上测试的过程是:
用 cv2 加载图像,并转换为 np.float32
使用 keras resnet50 'preprocess_input' python 函数对图像进行预处理
扩展图像尺寸以进行批处理(批处理大小为 1)
将图像转发到模型并得到结果
相关代码:
img = cv2.imread('./my_test_image.jpg')
x = preprocess_input(img.astype(np.float32))
x = np.expand_dims(x, axis=0)
net = load_model('./my_model.h5')
prediction_result = net.predict(x)
而且我注意到Android的图像预处理部分与我在keras中使用的方法不同,它的模式是caffe(将图像从RGB转换为BGR,然后将每个颜色通道相对于ImageNet数据集归零)。似乎原始代码用于模式 tf(将在 -1 到 1 之间缩放像素)。
所以我将下面的'preprocessBitmap'代码修改为我认为应该的,并使用像素值[127,127,127]的3通道RGB图像来测试它。该代码预测的结果与 .h5 模型的结果相同。但是当我加载图像进行分类时,预测结果与 .h5 模型不同。
有人知道吗?非常感谢。
我尝试了以下方法:
在我的手机中加载一个像素值为 [127,127,127] 的 3 通道 RGB 图像,并使用下面的修改代码,它会给我一个与在 PC 上使用 .h5 模型的预测结果相同的预测结果。
使用带有图像的 tensorflow gfile 模块在 PC 上测试转换后的 .pb 模型,它给了我正确的预测结果(与 .h5 模型相比)。所以我认为转换后的 .pb 文件没有任何问题。
preprocessBitmap 的整个部分
// code of 'preprocessBitmap' section in TensorflowImageClassifier.java
TraceCompat.beginSection("preprocessBitmap");
// Preprocess the image data from 0-255 int to normalized float based
// on the provided parameters.
bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
for (int i = 0; i < intValues.length; ++i) {
// this is a ARGB format, so we need to mask the least significant 8 bits to get blue, and next 8 bits to get green and next 8 bits to get red. Since we have an opaque image, alpha can be ignored.
final int val = intValues[i];
// original
/*
floatValues[i * 3 + 0] = (((val >> 16) & 0xFF) - imageMean) / imageStd;
floatValues[i * 3 + 1] = (((val >> 8) & 0xFF) - imageMean) / imageStd;
floatValues[i * 3 + 2] = ((val & 0xFF) - imageMean) / imageStd;
*/
// what I think it should be to do the same thing in mode caffe when using keras
floatValues[i * 3 + 0] = (((val >> 16) & 0xFF) - (float)123.68);
floatValues[i * 3 + 1] = (((val >> 8) & 0xFF) - (float)116.779);
floatValues[i * 3 + 2] = (((val & 0xFF)) - (float)103.939);
}
TraceCompat.endSection();