Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android TensorFlow Lite interpreter: How to fix "DataType error: cannot resolve DataType of java.lang.Float"

When running the TFLite interpreter giving as input a ByteBuffer containing floats, the application throws an exception:

"DataType error: cannot resolve DataType of java.lang.Float"

The model itself was trained on Keras, then converted to TF and then to TFLite.

For conversion I have used the TF (version 1.5.0) toco converter.

Input parameters for toco:

toco --input_file=converted.pb --output_file=model.tflite --input_format=TENSORFLOW_GRAPHDEF --input_shape=1,224,224,3 --input_array=main_input --output_array=main_output/Sigmoid --inference_type=FLOAT --output_format=TFLITE --input_type=FLOAT

Instead of the ByteBuffer I also have manually created a float[][][][] array with dimensions expected as input by the model: [1,224,224,3]

Leads to the same error as the ByteBuffer.

Please note that I am dividing the floats by 255 to get the pixel values in the range of [0,1].

import org.tensorflow.lite.Interpreter;
import java.nio.ByteBuffer;


public Interpreter tflite;

tflite = new Interpreter(loadModelFile(Test_TFLite.this,modelFile));

ByteBuffer bytebuffer_float = convertBitmapToByteBuffer_float(image, 1, 
    224, 3);

float out = 0;

tflite.run(bytebuffer_float,out);


private ByteBuffer convertBitmapToByteBuffer_float(Bitmap bitmap, int 
    BATCH_SIZE, int inputSize, int PIXEL_SIZE) {
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4 * BATCH_SIZE * 
    inputSize * inputSize * PIXEL_SIZE); //float_size = 4 bytes
        byteBuffer.order(ByteOrder.nativeOrder());
        int[] intValues = new int[inputSize * inputSize];
        bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, 
    bitmap.getWidth(), bitmap.getHeight());
        int pixel = 0;
        for (int i = 0; i < inputSize; ++i) {
            for (int j = 0; j < inputSize; ++j) { 
                final int val = intValues[pixel++];


                byteBuffer.putFloat( ((val >> 16) & 0xFF)* (1.f/255.f)); 
                byteBuffer.putFloat( ((val >> 8) & 0xFF)* (1.f/255.f)); 
                byteBuffer.putFloat( (val & 0xFF)* (1.f/255.f)); 
            }
        }
        return byteBuffer;
    }

I expect a single float value in range [0,1] as an output. There is no actual output as the interpreter throws an exception.

"DataType error: cannot resolve DataType of java.lang.Float"

like image 632
Moritz Avatar asked Jan 17 '19 11:01

Moritz


1 Answers

I've never used TF-Lite for Java myself. But, according to the docs, both arguments of tflite.run() have to be tensors. But for the output argument you are passing a single float only. So, I'm pretty sure this is the root cause of your error "cannot resolve DataType of java.lang.Float".

Note: also according to the docs, raw ByteBuffers as well as multidimensional arrays of the supported data types (float, int, long, byte) are supported. So, both of your approaches, ByteBuffer and float[][][][] should work. You only have to do the same for the output.

like image 77
sebrockm Avatar answered Sep 27 '22 19:09

sebrockm