tensorflow / flutter-tflite

Apache License 2.0
469 stars 125 forks source link

type 'int' is not a subtype of type 'Int64' of 'value' #130

Open patrik-jonsson-lumentec opened 1 year ago

patrik-jonsson-lumentec commented 1 year ago

I am using a tensorflow lite model created in Azure Custom Vision. The model returns a tensor consisting of 4 lists .

Here is my output specification

  final output = {
    0: List<List<num>>.filled(64, List<num>.filled(4, 0)),
    1: List<num>.filled(64, 0),
    // 1: List<Int64>.filled(64, Int64(0)),
    2: List<num>.filled(64, 0),
    3: [0.0],
  };

This works, but the values returned for the dict item 1, is supposed to be an int64, not an int. So the returned values are consistent, but messed up, e.g. 72057594037927936, instead of a 1.

When I try to use the commented out prefill of the dict item 1, i.e. List.filled(64, Int64(0)), where Int64 is defined in package:fixnum/fixnum.dart, it fails with the following message:

"type 'int' is not a subtype of type 'Int64' of 'value'"

How can I get the correct int values for a detected class, e.g. 1 instead of 72057594037927936?

Any advice would be highly appreciated.

Thanks,

Patrik

YassinNouh21 commented 1 year ago

The error you're seeing, "type 'int' is not a subtype of type 'Int64' of 'value'", likely stems from a data type mismatch between your TensorFlow Lite model and Flutter code.

Here's a quick plan to resolve it:

  1. Model Output: Confirm that your TensorFlow Lite model indeed should return Int64 values for dict item 1.

  2. Data Type Conversion: If the model is correct, explicitly convert int values to Int64 using Int64(value).

  3. Example and Testing: Refer to TensorFlow Flutter examples (https://github.com/tensorflow/flutter-tflite/tree/main/example) for guidance.

  4. For Custom Model: : If your TensorFlow Lite model was customized, ensure that the customizations are correctly implemented, and the data types are set as intended..

This should help fix the data type issue.

patrik-jonsson-lumentec commented 1 year ago

Thanks Yassin

Yes, the model is indeed returning int64 values, see image here from Netron image

I made a crude conversion as such: image

In the debugger you can see the values here: image

So, the issue is not the datatype per se, it is that flutter/dart seems to unpack values as ints that really seem to be represented as int64, thus scrambling the numbers, consistently though, but a bit difficult to use.

Does it make sense?

Patrik

patrik-jonsson-lumentec commented 1 year ago

Finally I figured out a solution that works for me. Not very elegant IMHO, but it works and perhaps can be used by someone else to build a more generic, elegant and robust solution.

` const int OBSERVATIONS = 64; const int COORDINATES = 4;

// ## Output specification
// There are three outputs from this model.

// * detected_boxes
// The detected bounding boxes. Each bounding box is represented as [x1, y1, x2, y2] where (x1, y1) and (x2, y2) are the coordinates of box corners.
// * detected_scores
// Probability for each detected boxes.
// * detected_classes
// The class index for the detected boxes.
// * Apparently the fourth parameter is not used?

final output = {
  0: List<List<num>>.filled(OBSERVATIONS, List<num>.filled(COORDINATES, 0)),
  1: List<num>.filled(OBSERVATIONS, 0),
  2: List<num>.filled(OBSERVATIONS, 0),
  3: [0.0],
};

// Int64 is 8 times as wide in bytes as Int8
final output_fetcher = {
  0: List<List<num>>.filled(OBSERVATIONS, List<num>.filled(COORDINATES, 0)),
  1: Uint8List.fromList(List<int>.filled(OBSERVATIONS * 8, 0)),
  2: List<num>.filled(OBSERVATIONS, 0),
  3: [0.0],
};

_interpreter!.runForMultipleInputs([input], output_fetcher);

output[0] = output_fetcher[0] as List<List<num>>;
output[1] = (output_fetcher[1]! as Uint8List)
    .buffer
    .asUint64List()
    .toInt8List()
    .toList();
output[2] = output_fetcher[2] as List<num>;
output[3] = output_fetcher[3] as List<num>;

return output.values.toList();

`