math.random
math.random

Reputation: 99

Cannot copy to a TensorFlowLite tensor (input_1) with 150528 bytes from a Java Buffer with 602112 bytes

I'm trying to use my model in the tflitecamerademo example.

Here is my model enter image description here

The demo crashes with the following reason

java.lang.IllegalArgumentException: Cannot copy to a TensorFlowLite tensor (input_1) with 150528 bytes from a Java Buffer with 602112 bytes.

I initialize the byte buffer following google's example

imgData = ByteBuffer.allocateDirect(4 * DIM_BATCH_SIZE * DIM_IMG_SIZE_X * DIM_IMG_SIZE_Y * DIM_PIXEL_SIZE);

imgData.order(ByteOrder.nativeOrder());

DIM_BATCH_SIZE = 1
DIM_IMG_SIZE_X = 224
DIM_IMG_SIZE_Y = 224
DIM_PIXEL_SIZE = 3

Then I resize the image to the net resolution and convert it to a byte buffer

Bitmap reshapeBitmap = Bitmap.createScaledBitmap(bitmap, 224, 224, false);
convertBitmapToByteBuffer(reshapeBitmap);


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++];
                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);
            }
        }
        long endTime = SystemClock.uptimeMillis();
        //Log.d("Timecost to put values into ByteBuffer: " + Long.toString(endTime - startTime));
    }

And last, I run the detection

tflite.run(imgData, labelProbArray);

Here the crash happens due to the input size being different to to buffer size.

Now, if we multiply by hand 1 * 224 * 224 * 3 * 4 we get 602112, the correct size. Why my code is missing the last multiplication.

Upvotes: 4

Views: 8722

Answers (2)

Yang
Yang

Reputation: 612

we can just using ImageProcessor CastOp(DataType.UINT8) to cast the bitmap into uint8.

ImageProcessor imageProcessor;
TensorImage xceptionTfliteInput;
if(IS_INT8){
    imageProcessor =
           new ImageProcessor.Builder()
                            .add(new ResizeOp(INPNUT_SIZE.getHeight(), INPNUT_SIZE.getWidth(), ResizeOp.ResizeMethod.BILINEAR))
                            .add(new NormalizeOp(0, 255))
                            .add(new QuantizeOp(inputQuantParams.getZeroPoint(), inputQuantParams.getScale()))
                            .add(new CastOp(DataType.UINT8))
                            .build();
    xceptionTfliteInput = new TensorImage(DataType.UINT8);
} else {
    imageProcessor =
          new ImageProcessor.Builder()
                            .add(new ResizeOp(INPNUT_SIZE.getHeight(), INPNUT_SIZE.getWidth(), ResizeOp.ResizeMethod.BILINEAR))
                            .add(new NormalizeOp(0, 255))
                            .build();
     xceptionTfliteInput = new TensorImage(DataType.FLOAT32);
}
xceptionTfliteInput.load(bitmap);
xceptionTfliteInput = imageProcessor.process(xceptionTfliteInput);

Upvotes: 1

Alex K.
Alex K.

Reputation: 861

This is caused by type mismatch.
According to model description you have integer type input/output, maybe quantized model.
You are trying to prepare floating point data buffer to feed. There are 2 most common solutions:

1)Prepare uint8 data. Write bitmap pixels as 1 byte uint8s into bytebuffer:

imgData = ByteBuffer.allocateDirect(DIM_BATCH_SIZE * DIM_IMG_SIZE_X * DIM_IMG_SIZE_Y * DIM_PIXEL_SIZE); // now buffer size and input size match

imgData.order(ByteOrder.nativeOrder());

Bitmap reshapeBitmap = Bitmap.createScaledBitmap(bitmap, 224, 224, false);
convertBitmapToByteBuffer(reshapeBitmap);


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++];
                imgData.putChar((byte)((((val >> 16) & 0xFF)-IMAGE_MEAN)/IMAGE_STD*255));
                imgData.putChar((byte)((((val >> 8) & 0xFF)-IMAGE_MEAN)/IMAGE_STD*255));
                imgData.putChar((byte)((((val) & 0xFF)-IMAGE_MEAN)/IMAGE_STD*255));
            }
        }
        long endTime = SystemClock.uptimeMillis();
        //Log.d("Timecost to put values into ByteBuffer: " + Long.toString(endTime - startTime));
    }

Also take a look at tflite support lib, it simplifies way how you deal with input/output data and may come handy.

2)Find model with floating point input and use your code

Upvotes: 1

Related Questions