Theuno de Bruin
Theuno de Bruin

Reputation: 261

PlatformException when trying to detect objects on a custom tflite model

I used Cloud AutoML to train a custom model that suppose to detect marks on a piece of paper. I have the dataset exported as a TFLite file, and i have it hosted on firebase.

I managed to download the file and initiate the objectDetector fine. but are getting an error when processing an input image.

This is my code:

Initialise the detector in the cubit

  initialiseDetector({double confidenceThreshold = 0.5, int maximumLabelsPerObject = 10}) async {
    emit(ShoddyLoading(state.mainShoddyState.copyWith(message: 'Loading object detector')));
    try {
      ObjectDetector objectDetector = await ShoddyHelper.initialiseDetector(
        processingFromDownloadedFile: true,
        modelFile: state.mainShoddyState.modelFile,
        confidenceThreshold: confidenceThreshold,
        maximumLabelsPerObject: maximumLabelsPerObject,
      );
      emit(ShoddyModelLoaded(state.mainShoddyState.copyWith(objectDetector: objectDetector, message: 'Ready to start processing images')));
    } catch (error) {
      emit(ShoddyError(state.mainShoddyState.copyWith(message: error.toString())));
    }
  }

A helper / utilities file to download or use a model file

  static Future<ObjectDetector> initialiseDetector({File? modelFile, bool processingFromDownloadedFile = true, required double confidenceThreshold, required int maximumLabelsPerObject}) async {
    if (processingFromDownloadedFile) {
      if (modelFile != null) {
        return await initializeLocalDetector(modelFile, confidenceThreshold, maximumLabelsPerObject);
      } else {
        File modelFile = await loadModelFileFromFirebase();
        return await initializeLocalDetector(modelFile, confidenceThreshold, maximumLabelsPerObject);
      }
    } else {
      return await initializeFirebaseDetector(confidenceThreshold, maximumLabelsPerObject);
    }
  }

// Download the model file from firebase first
  static Future<File> loadModelFileFromFirebase(String modelName) async {
    try {
      FirebaseModelDownloader downloader = FirebaseModelDownloader.instance;

      List<FirebaseCustomModel> models = await downloader.listDownloadedModels();
      for (FirebaseCustomModel model in models) {
        print('Name: ${model.name}');
      }

      FirebaseModelDownloadConditions conditions = FirebaseModelDownloadConditions(
        iosAllowsCellularAccess: true,
        iosAllowsBackgroundDownloading: false,
        androidChargingRequired: false,
        androidWifiRequired: false,
        androidDeviceIdleRequired: false,
      );

      FirebaseCustomModel model = await downloader.getModel(
        modelName,
        FirebaseModelDownloadType.latestModel,
        conditions,
      );

      File modelFile = model.file;

      return modelFile;
    } catch (exception) {
      print('Failed on loading your model from Firebase: $exception');
      print('The program will not be resumed');
      rethrow;
    }
  }

  // Use a file downloaded from firebase
  static Future<ObjectDetector> initializeLocalDetector(File modelFile, double confidenceThreshold, int maximumLabelsPerObject) async {
    try {
      final options = LocalObjectDetectorOptions(
        mode: DetectionMode.single,
        modelPath: modelFile.path,
        classifyObjects: true,
        multipleObjects: true,
        confidenceThreshold: confidenceThreshold,
        maximumLabelsPerObject: maximumLabelsPerObject,
      );

      return ObjectDetector(options: options);
    } catch (exception) {
      print('Failed on loading your model to the TFLite interpreter: $exception');
      print('The program will not be resumed');
      rethrow;
    }
  }

  // Use the model file directly from firebase
  static Future<ObjectDetector> initializeFirebaseDetector(String modelName, double confidenceThreshold, int maximumLabelsPerObject) async {
    try {
      final options = FirebaseObjectDetectorOptions(
        mode: DetectionMode.single,
        modelName: modelName,
        classifyObjects: true,
        multipleObjects: true,
        confidenceThreshold: confidenceThreshold,
        maximumLabelsPerObject: maximumLabelsPerObject,
      );

      return ObjectDetector(options: options);
    } catch (exception) {
      print('Failed on loading your model to the TFLite interpreter: $exception');
      print('The program will not be resumed');
      rethrow;
    }
  }

The function to process an image

  processImage(File file) async {
    emit(ShoddyModelProcessing(state.mainShoddyState.copyWith(message: 'Looking for objects on the selected image')));
    try {
      List<dynamic>? results = [];
      if (state.mainShoddyState.objectDetector != null) {
        InputImage inputImage = InputImage.fromFilePath(file.path);
        List<DetectedObject> objects = await state.mainShoddyState.objectDetector!.processImage(inputImage);
        if (objects.isNotEmpty) {
          List<ObjectModel> objects = results.map((result) => ObjectModel(result)).toList();
          emit(ShoddyModelProcessed(state.mainShoddyState.copyWith(objects: objects, filteredObjects: objects, message: 'Image processed with results')));
          changeMatchPercentage(0.35);
        } else {
          emit(ShoddyModelProcessed(state.mainShoddyState.copyWith(objects: [], filteredObjects: [], message: 'Image processed with no results')));
        }
      }
    } catch (error) {
      emit(ShoddyError(state.mainShoddyState.copyWith(message: error.toString())));
    }
  }

When i call:

        List<DetectedObject> objects = await state.mainShoddyState.objectDetector!.processImage(inputImage);

I get the following error:

PlatformException(Error 3, com.google.visionkit.pipeline.error, Pipeline failed to fully start:
CalculatorGraph::Run() failed in Run: 
Calculator::Open() for node "BoxClassifierCalculator" failed: #vk Unexpected number of dimensions for output index 0: got 3D, expected either 2D (BxN with B=1) or 4D (BxHxWxN with B=1, W=1, H=1)., null)

Is there something i'm missing?

Upvotes: 2

Views: 429

Answers (2)

Theuno de Bruin
Theuno de Bruin

Reputation: 261

According to the ML kit documents its not possible to do object detection with AutoML Vision custom trained object detection models

https://developers.google.com/ml-kit/custom-models#automl_vision_edge

Note: ML Kit only supports custom image classification models. Although AutoML Vision allows training of object detection models, these cannot be used with ML Kit.

Upvotes: 1

Prajna Rai T
Prajna Rai T

Reputation: 1818

You have exported the model (not the database) as a TFLite model. And you are using MLKit's detection API.

In order for a TFLite model to be compatible with MLKit, it needs to accept 2-dimensional or 4-dimensional tensors, as documented here.

The exported model seems to accept a 3d tensor. The solution is to go back to the tool you used to develop the model and ensure the model interface is 4-d, with the specs according to this document.

Upvotes: 0

Related Questions