Search code examples
javaandroidandroid-cameraxgoogle-mlkit

Keep receiving this error "Failed to initialize detector". Am I not loading the tflite model correctly?


I am trying to setup an ImageAnalyzer with my Android app so I can run object classification using Google's ML Kit API. The issue I am currently facing, as the title suggests, is constantly seeing the error "Failed to initialize detector".

I've reread this tutorial about three times now and followed this post about someone facing the same error (although for a different reason) to no avail. I've also made sure everything with the CameraX API (except the ImageAnalyzer code that I will show in a second) works as expected.

As mentioned in the ML Kit documentation, here is the code I have regarding setting up a LocalModel, a CustomObjectDetectorOptions, and an ObjectDetector:

        LocalModel localModel = new LocalModel.Builder()
                .setAssetFilePath("mobilenet_v1_1.0_224_quantized_1_metadata_1.tflite")
                .build();
        CustomObjectDetectorOptions customObjectDetectorOptions =
                new CustomObjectDetectorOptions.Builder(localModel)
                        .setDetectorMode(CustomObjectDetectorOptions.STREAM_MODE)
                        .enableClassification()
                        .setClassificationConfidenceThreshold(0.5f)
                        .setMaxPerObjectLabelCount(3)
                        .build();
        ObjectDetector objectDetector = ObjectDetection.getClient(customObjectDetectorOptions);

Here is the ImageAnalyzer code I have, which basically makes a call to the ML Kit API by way of the processImage helper method:

    // Creates an ImageAnalysis for analyzing the camera preview feed
        ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
                .setTargetResolution(new Size(224, 224))
                .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
                .build();
        imageAnalysis.setAnalyzer(ContextCompat.getMainExecutor(this),
                new ImageAnalysis.Analyzer() {
                    @Override
                    public void analyze(@NonNull ImageProxy imageProxy) {
                        @SuppressLint("UnsafeExperimentalUsageError") Image mediaImage =
                                imageProxy.getImage();
                        if (mediaImage != null) {
                            Log.i(TAG, "Obtained ImageProxy object");
                            processImage(mediaImage, imageProxy)
                            .addOnCompleteListener(new OnCompleteListener<List<DetectedObject>>() {
                                @Override
                                public void onComplete(@NonNull Task<List<DetectedObject>> task) {
                                    imageProxy.close();
                                }
                            });
                        }
                    }
                });

Here is the processImage helper method, where I actually call objectDetector.process(...), the line of code that actually runs the tflite model.

    private Task<List<DetectedObject>> processImage(Image mediaImage, ImageProxy imageProxy) {
        InputImage image =
                InputImage.fromMediaImage(mediaImage,
                        imageProxy.getImageInfo().getRotationDegrees());
        return objectDetector.process(image)
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        String error = "Failed to process. Error: " + e.getMessage();
                        Log.i(TAG, error);
                    }
                })
                .addOnSuccessListener(new OnSuccessListener<List<DetectedObject>>() {
                    @Override
                    public void onSuccess(List<DetectedObject> results) {
                        String success = "Object(s) detected successfully!";
                        Log.i(TAG, success);
                        for (DetectedObject detectedObject : results) {
                            Rect boundingBox = detectedObject.getBoundingBox();
                            Integer trackingId = detectedObject.getTrackingId();
                            for (DetectedObject.Label label : detectedObject.getLabels()) {
                                String text = label.getText();
                                int index = label.getIndex();
                                float confidence = label.getConfidence();
                                Log.i(TAG, "Object detected: " + text + "; "
                                        + "Confidence: " + confidence);
                            }
                        }
                    }
                });
    }

Essentially, once I run the app, logcat just keeps logging these two lines on repeat. I know it means the ImageAnalyzer is continuously trying to analyze the image input, but for some reason the LocalModel just cannot process the input

2021-01-21 22:02:24.020 9328-9328/com.example.camerax I/MainActivity: Obtained ImageProxy object

2021-01-21 22:02:24.036 9328-9328/com.example.camerax I/MainActivity: Failed to process. Error: Failed to initialize detector.

I have only just started to work with Android, especially ML in Android, so any sort of help would be appreciated!


Solution

  • I managed to fix my issue before anyone answered, but in case anyone who just started to learn Android like me I'll leave my solution here.

    Basically, remember to create an asset folder in the /src/main directory rather than the /src/androidTest directory :P

    Once I did that, the model loaded correctly and now I just have to figure out how to display the results in my application.