Open occasionalcode opened 9 months ago
@occasionalcode I would say that the output’s tensors you have are in wrong order. To check for the correct tensors order you can definitely check the name of your model on Kaggle. If you still cannot find your model, please upload your tflite file on Netron. Those two ways will help you reveal the output layer with the correct tensor order. My guess is that 0’s type should be List<List< double >> . That is all the hints so far I can give you. If you have more questions, please let me know!
If you add the line
debugPrint(outputTensors.toString());
just after the line var outputTensors = getOutputTensors();
in the interpreter.dart file for the function runForMultipleInputs then you will see what is returned as outputs. In the case of the ssd_mobilenet_v2_fpnlite_320x320_coco17_tpu-8 model the result is:
flutter: [Tensor{_tensor: Pointer: address=0x10bcb5450, name: StatefulPartitionedCall:1, type: float32, shape: [1, 10], data: 40}, Tensor{_tensor: Pointer: address=0x10bcb5370, name: StatefulPartitionedCall:3, type: float32, shape: [1, 10, 4], data: 160}, Tensor{_tensor: Pointer: address=0x10bcb54c0, name: StatefulPartitionedCall:0, type: float32, shape: [1], data: 4}, Tensor{_tensor: Pointer: address=0x10bcb53e0, name: StatefulPartitionedCall:2, type: float32, shape: [1, 10], data: 40}]
You can see the StatefulPartitionedCalls are not returned in order but instead are returned in the order 1,3,0,2. If you drop that particular model into Netron , you see what those stateflulPartitionCalls actually are; 0: is for the number of detected boxes 1: is for the scores of the detected boxes 2: is for the categories of the detected boxes 3: is for the locations of the detected boxes
as such final output = { 0: [List<num>.filled(10, 0)], 1: [List<List<num>>.filled(10, List<num>.filled(4, 0))], 2: [0.0], 3: [List<num>.filled(10, 0)], };
as outlined in the above comment by occasionalcode is indeed the correct order for final output tensors...
but you are not quite done yet... as the class _DetectorServer within the detector_service.dart file still needs modifications because of the altered order of outputs. Specifically
final scores = output.elementAt(2).first as List<double>;
needs to change to
final scores = output.elementAt(0).first as List<double>;
and
final locationsRaw = output.first.first as List<List<double>>;
need to change to
final locationsRaw = output.elementAt(1).first as List<List<double>>;
and
final numberOfDetectionsRaw = output.last.first as double;
needs to change to
final numberOfDetectionsRaw = output.elementAt(2).first as double;
and
final classesRaw = output.elementAt(1).first as List<double>;
needs to change to
final classesRaw = output.elementAt(3).first as List<double>;
It wasn't until I made these changes that my custom tflite model would actually detect anything.
If you add the line
debugPrint(outputTensors.toString());
just after the linevar outputTensors = getOutputTensors();
in the interpreter.dart file for the function runForMultipleInputs then you will see what is returned as outputs. In the case of the ssd_mobilenet_v2_fpnlite_320x320_coco17_tpu-8 model the result is:flutter: [Tensor{_tensor: Pointer: address=0x10bcb5450, name: StatefulPartitionedCall:1, type: float32, shape: [1, 10], data: 40}, Tensor{_tensor: Pointer: address=0x10bcb5370, name: StatefulPartitionedCall:3, type: float32, shape: [1, 10, 4], data: 160}, Tensor{_tensor: Pointer: address=0x10bcb54c0, name: StatefulPartitionedCall:0, type: float32, shape: [1], data: 4}, Tensor{_tensor: Pointer: address=0x10bcb53e0, name: StatefulPartitionedCall:2, type: float32, shape: [1, 10], data: 40}]
You can see the StatefulPartitionedCalls are not returned in order but instead are returned in the order 1,3,0,2. If you drop that particular model into Netron , you see what those stateflulPartitionCalls actually are; 0: is for the number of detected boxes 1: is for the scores of the detected boxes 2: is for the categories of the detected boxes 3: is for the locations of the detected boxes
as such
final output = { 0: [List<num>.filled(10, 0)], 1: [List<List<num>>.filled(10, List<num>.filled(4, 0))], 2: [0.0], 3: [List<num>.filled(10, 0)], };
as outlined in the above comment by occasionalcode is indeed the correct order for final output tensors... but you are not quite done yet... as the class _DetectorServer within the detector_service.dart file still needs modifications because of the altered order of outputs. Specificallyfinal scores = output.elementAt(2).first as List<double>;
needs to change tofinal scores = output.elementAt(0).first as List<double>;
andfinal locationsRaw = output.first.first as List<List<double>>;
need to change tofinal locationsRaw = output.elementAt(1).first as List<List<double>>;
andfinal numberOfDetectionsRaw = output.last.first as double;
needs to change tofinal numberOfDetectionsRaw = output.elementAt(2).first as double;
andfinal classesRaw = output.elementAt(1).first as List<double>;
needs to change tofinal classesRaw = output.elementAt(3).first as List<double>;
It wasn't until I made these changes that my custom tflite model would actually detect anything.
it works for me, thanks!
hi! im trying to create a Object detection application using this repo https://github.com/tensorflow/flutter-tflite. i tried to use my custom model and it gave me a output shape error
i tried to follow the suggestion from #134
and right now im facing this error
do you have any suggestions on how i can solve this problem?
here is the code https://paste.ofcode.org/4raUUvjbfPPcjZNSQ5Gk6J