tensorflow / flutter-tflite

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unhandled exception: type 'List<double>' is not a subtype of type 'List<int>' of 'value'

zyrridian opened this issue · comments

I clone this example without changing anything and then run it perfectly fine, everything is working.

But when I change the model to this, the labels gone, in both gallery screen and live camera. This is the logs when I open live camera screen:

E/flutter (28541): [ERROR:flutter/runtime/dart_isolate.cc(1107)] Unhandled exception:
E/flutter (28541): type 'List<double>' is not a subtype of type 'List<int>' of 'value'
E/flutter (28541): #0      List.[]= (dart:core-patch/growable_array.dart:267:34)
E/flutter (28541): #1      Tensor._duplicateList (package:tflite_flutter/src/tensor.dart:237:10)
E/flutter (28541): #2      Tensor.copyTo (package:tflite_flutter/src/tensor.dart:203:7)
E/flutter (28541): #3      Interpreter.runForMultipleInputs (package:tflite_flutter/src/interpreter.dart:183:24)
E/flutter (28541): #4      Interpreter.run (package:tflite_flutter/src/interpreter.dart:172:5)
E/flutter (28541): #5      IsolateInference.entryPoint (package:image_classification/helper/isolate_inference.dart:84:19)
E/flutter (28541): <asynchronous suspension>

I'm not sure about this one, but I also got this message before unhandled exception:

E/System  (28541): java.util.concurrent.RejectedExecutionException: Task android.hardware.camera2.impl.-$$Lambda$CallbackProxies$SessionStateCallbackProxy$9H0ZdANdMrdpoq2bfIL2l3DVsKk@5b79261 rejected from java.util.concurrent.ThreadPoolExecutor@5c91186[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 4]
E/System  (28541): 	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2085)
E/System  (28541): 	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:848)
E/System  (28541): 	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1394)
E/System  (28541): 	at java.util.concurrent.Executors$DelegatedExecutorService.execute(Executors.java:624)
E/System  (28541): 	at android.hardware.camera2.impl.CallbackProxies$SessionStateCallbackProxy.onClosed(CallbackProxies.java:104)
E/System  (28541): 	at android.hardware.camera2.impl.CameraCaptureSessionImpl.close(CameraCaptureSessionImpl.java:582)
E/System  (28541): 	at android.hardware.camera2.impl.CameraCaptureSessionImpl.finalize(CameraCaptureSessionImpl.java:873)
E/System  (28541): 	at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:255)
E/System  (28541): 	at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:242)
E/System  (28541): 	at java.lang.Daemons$Daemon.run(Daemons.java:108)
E/System  (28541): 	at java.lang.Thread.run(Thread.java:764)
E/flutter (28541): #12     PlatformDispatcher._dispatchPlatformMessage (dart:ui/platform_dispatcher.dart:737:22)
E/flutter (28541): #13     _dispatchPlatformMessage (dart:ui/hooks.dart:257:31)

I made this model using Teachable Machine with floating point conversion type. I saw many people struggle when they are trying to implement teachable machine model with this package, I hope someone could give an explanation about this.

Your model's output is float32 and not an integer as in the example model. You need to change the output type to double to handle that. And the maxSocre needs to be changed to double as well. I have edited those changes for you. Replace the content of the 'isolate_inference.dart' to following and it should work as intended.

/*
 * Copyright 2023 The TensorFlow Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *             http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import 'dart:io';
import 'dart:isolate';
import 'package:camera/camera.dart';
import 'package:image/image.dart' as image_lib;
import 'package:image_classification_mobilenet/image_utils.dart';
import 'package:tflite_flutter/tflite_flutter.dart';

class IsolateInference {
  static const String _debugName = "TFLITE_INFERENCE";
  final ReceivePort _receivePort = ReceivePort();
  late Isolate _isolate;
  late SendPort _sendPort;

  SendPort get sendPort => _sendPort;

  Future<void> start() async {
    _isolate = await Isolate.spawn<SendPort>(entryPoint, _receivePort.sendPort,
        debugName: _debugName);
    _sendPort = await _receivePort.first;
  }

  Future<void> close() async {
    _isolate.kill();
    _receivePort.close();
  }

  static void entryPoint(SendPort sendPort) async {
    final port = ReceivePort();
    sendPort.send(port.sendPort);

    await for (final InferenceModel isolateModel in port) {
      image_lib.Image? img;
      if (isolateModel.isCameraFrame()) {
        img = ImageUtils.convertCameraImage(isolateModel.cameraImage!);
      } else {
        img = isolateModel.image;
      }

      // resize original image to match model shape.
      image_lib.Image imageInput = image_lib.copyResize(
        img!,
        width: isolateModel.inputShape[1],
        height: isolateModel.inputShape[2],
      );

      if (Platform.isAndroid && isolateModel.isCameraFrame()) {
        imageInput = image_lib.copyRotate(imageInput, angle: 90);
      }

      final imageMatrix = List.generate(
        imageInput.height,
        (y) => List.generate(
          imageInput.width,
          (x) {
            final pixel = imageInput.getPixel(x, y);
            return [pixel.r, pixel.g, pixel.b];
          },
        ),
      );

      // Set tensor input [1, 224, 224, 3]
      final input = [imageMatrix];
      // Set tensor output [1, 1001]
      final output = [List<double>.filled(isolateModel.outputShape[1], 0)];
      // // Run inference
      Interpreter interpreter =
          Interpreter.fromAddress(isolateModel.interpreterAddress);
      interpreter.run(input, output);
      // Get first output tensor
      final result = output.first;
      double maxScore = result.reduce((a, b) => a + b);
      // Set classification map {label: points}
      var classification = <String, double>{};
      for (var i = 0; i < result.length; i++) {
        if (result[i] != 0) {
          // Set label: points
          classification[isolateModel.labels[i]] =
              result[i].toDouble() / maxScore.toDouble();
        }
      }
      isolateModel.responsePort.send(classification);
    }
  }
}

class InferenceModel {
  CameraImage? cameraImage;
  image_lib.Image? image;
  int interpreterAddress;
  List<String> labels;
  List<int> inputShape;
  List<int> outputShape;
  late SendPort responsePort;

  InferenceModel(this.cameraImage, this.image, this.interpreterAddress,
      this.labels, this.inputShape, this.outputShape);

  // check if it is camera frame or still image
  bool isCameraFrame() {
    return cameraImage != null;
  }
}

@chathurach it works but now the result is highly inaccurate. I've tested my model and I'm quite sure that my model accuracy is not supposed to be that low. In the screenshot below, the result should be 'V'.

Screenshot (91)

This is the image test I used.

This could happen for many reasons. The most common one is that your inputs are not normalized correctly. Change the input formatting to the following code in the 'isolate_inference.dart'

final imageMatrix = List.generate(
        imageInput.height,
        (y) => List.generate(
          imageInput.width,
          (x) {
            final pixel = imageInput.getPixel(x, y);
            return [(pixel.r-127.5)/127.5, (pixel.g-127.5)/127.5, (pixel.b-127.5)/127.5];
          },
        ),
      );

If not working, change the divisor (127.5) to 255 and try. You will have to figure out the most appropriate normalization method for your model.

It works! I learn something new, thank you.