AutoML TfLite Android Edge设备教程:如何在教程代码中解决BufferOverflowException

时间:2019-05-09 16:50:01

标签: java android tensorflow-lite automl google-cloud-automl

我正在测试Google Cloud AutoML视觉,我已经完成了培训过程,具有导出的边缘设备tflite模型,超过10万张图像,25个标签。

按照以下两个仓库中的说明和代码进行操作: https://cloud.google.com/vision/automl/docs/edge-quickstart https://cloud.google.com/vision/automl/docs/tflite-android-tutorial https://github.com/googlecodelabs/tensorflow-for-poets-2/tree/master/android/tflite

我假设问题不在于自定义tflite问题,而是本教程未解决的某种兼容性问题(错误或因为它已过时?)

上面github回购中包含的具有预训练模型的示例应用程序无需任何更改即可工作。当我换掉tflite软件包并进行本教程要求的代码更改时,遇到了BufferOverflowException

我假设问题不在于自定义tflite问题,而是本教程未解决的某种兼容性问题(错误或因为它已过时?)

上面github回购中包含的具有预训练模型的示例应用程序无需任何更改即可工作。当我换掉tflite软件包并进行本教程要求的代码更改时,遇到了BufferOverflowException

在try / catch块处代码崩溃(我添加了此内容,以查看发生了什么事)

'''
private void convertBitmapToByteBuffer(Bitmap bitmap) {
if (imgData == null) {
  return;
}
imgData.rewind();
bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
// Convert the image to floating point.
int pixel = 0;
long startTime = SystemClock.uptimeMillis();
for (int i = 0; i < DIM_IMG_SIZE_X; ++i) {
  for (int j = 0; j < DIM_IMG_SIZE_Y; ++j) {
    final int val = intValues[pixel++];
    try
    {
      imgData.putFloat((((val >> 16) & 0xFF))/IMAGE_STD);
      imgData.putFloat((((val >> 8) & 0xFF))/IMAGE_STD);
      imgData.putFloat((((val) & 0xFF))/IMAGE_STD);
    }
    catch (BufferOverflowException e)
    {
      Log.e("TfLiteCameraDemo", "Exception caught: ", e);
    }
  }
}
long endTime = SystemClock.uptimeMillis();
Log.d(TAG, "Timecost to put values into ByteBuffer: " + Long.toString(endTime - startTime));
}
'''

导入的tflite模型按照上面链接中的教程说明崩溃。

1 个答案:

答案 0 :(得分:0)

我意识到这是一篇较旧的文章,但我遇到了同样的问题并找到了解决方案。也许发布会在将来帮助其他人。

Tensorflow部分想要的缓冲区是150528字节。通过在上面使用putFloat(),代码试图将4x(float = 4字节)的数据放入imgData缓冲区。我只是尝试使缓冲区更大,而产生了另一个错误。最终起作用的是将数据从浮点数转换为字节。见下文。

原始:(由于缓冲区溢出错误而崩溃)

imgData.putFloat((((val >> 16) & 0xFF)-IMAGE_MEAN)/IMAGE_STD);
imgData.putFloat((((val >> 8) & 0xFF)-IMAGE_MEAN)/IMAGE_STD);
imgData.putFloat((((val) & 0xFF)-IMAGE_MEAN)/IMAGE_STD);

已修改:(这在我的Galaxy Note9上崩溃了,但是在准确识别方面做得不好。)

imgData.put((byte) ((byte) (((val >> 16) & 0xFF)- IMAGE_MEAN)/IMAGE_STD));
imgData.put((byte) ((byte) (((val >> 8) & 0xFF)-IMAGE_MEAN)/IMAGE_STD));
imgData.put((byte) (((byte) ((val) & 0xFF)-IMAGE_MEAN)/IMAGE_STD));