Android Question Help implementing ML Kit Object Detection

Lucas Siqueira

Active Member
Licensed User
Longtime User
Hello everyone, Erel did a wonderful job implementing several classes with ML Kit, but I've been trying to implement Object Detection for 3 days, but I haven't been able to, can anyone do it?

documentation:


Erel has already implemented:

1752198656768.png



1752198685751.png




1752198586625.png



1752198612614.png
 

jkhazraji

Active Member
Licensed User
Longtime User
I couldn't implement it in b4x, please help me to implement it

Before I came across this post, I was also digging in the same subject, but it seems that b4a does not lend itself to ML Kit easily although it deals with android for if you want to do the same thing in Android Studio, ML Kit detect object is easily integrated with 'implementation' statement. Therefore, depending on the examples from Google and Github I came out with a b4a code (manly inline Java) but still it has one stubborn error failure to initialize ML Kit:
Exception during ML Kit Initialization :Attempt to invoke virtual method 'com.google.mlkit.vision.common.internal.MultiFlavorDetectorCreator$MultiFlavorDetector com.google.mlkit.vision.common.internal.MultiFlavorDetectorCreator.create(com.google.mlkit.vision.common.internal.MultiFlavorDetectorCreator$DetectorOptions)' on a null object reference.
If you or the forum experts find a solution, sharing it will be of benefit.
B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A ML Kit Detection
    #VersionCode: 1
    #VersionName: 1.0
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
    
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

#AdditionalJar: com.google.mlkit:object-detection
#AdditionalJar: com.google.mlkit:vision-common
#AdditionalJar: com.google.android.gms:play-services-base
#AdditionalJar: com.google.android.gms:play-services-basement
#AdditionalJar: com.google.android.gms:play-services-tasks
#AdditionalJar: androidx.annotation:annotation
#AdditionalJar: kotlin-stdlib-1.6.10

Sub Process_Globals
    Private xui As XUI
    Private isMLKitInitialized As Boolean = False
End Sub

Sub Globals
    Private iv As ImageView
    Private btnDetect As Button
    Private lblResults As Label
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
    
    ' Initialize views
    iv.Initialize("iv")
    btnDetect.Initialize("btnDetect")
    lblResults.Initialize("lblResults")
    
    Activity.AddView(iv, 0, 0, 100%x, 60%y)
    Activity.AddView(btnDetect, 0, 65%y, 100%x, 15%y)
    Activity.AddView(lblResults, 0, 85%y, 100%x, 15%y)
    
    btnDetect.Text = "Detect Objects"
    btnDetect.Enabled = False
    lblResults.Text = "Initializing ML Kit..."
    
    ' Copy test image
    If Not(File.Exists(File.DirInternal,"home.jpg")) Then
        File.Copy(File.DirAssets,"home.jpg",File.DirInternal,"home.jpg")
    End If
    
    ' Load test image
    Dim bmp As Bitmap = LoadBitmap(File.DirInternal, "test.png")
    iv.Bitmap = bmp
    
    ' Wait for activity to be fully loaded, then initialize ML Kit
    Wait For Activity_Resume
    Sleep(1000) ' Give the activity time to fully load
    InitializeMLKit
End Sub

Sub InitializeMLKit
    Try
        Dim jo As JavaObject
        jo.InitializeContext
        jo.RunMethod("initializeMLKit", Array(GetBA))
    Catch
        Log("Error initializing ML Kit: " & LastException.Message)
        lblResults.Text = "ML Kit initialization error: " & LastException.Message
    End Try
End Sub

Sub btnDetect_Click
    If Not(isMLKitInitialized) Then
        lblResults.Text = "ML Kit not initialized yet"
        Return
    End If
    
    If iv.Bitmap <> Null Then
        lblResults.Text = "Detecting objects..."
        DetectObjects(iv.Bitmap)
    Else
        lblResults.Text = "No image loaded"
    End If
End Sub

Sub DetectObjects(bmp As Bitmap)
    Try
        Dim jo As JavaObject = Me
        jo.InitializeContext
        jo.RunMethod("detectObjects", Array(bmp, GetBA))
    Catch
        Log("Error in DetectObjects: " & LastException.Message)
        lblResults.Text = "Detection error: " & LastException.Message
    End Try
End Sub

Sub GetBA As JavaObject
    Dim jo As JavaObject
    Dim cls As String = Me
    cls = cls.SubString("class ".Length)
    jo.InitializeStatic(cls)
    Return jo.GetFieldJO("processBA")
End Sub

#If JAVA
import com.google.mlkit.common.MlKit;
import com.google.mlkit.vision.common.InputImage;
import com.google.mlkit.vision.objects.DetectedObject;
import com.google.mlkit.vision.objects.ObjectDetection;
import com.google.mlkit.vision.objects.ObjectDetector;
import com.google.mlkit.vision.objects.defaults.ObjectDetectorOptions;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.Task;
import android.graphics.Bitmap;
import java.util.List;
import anywheresoftware.b4a.BA;
import android.content.Context;
import android.util.Log;

private static ObjectDetector objectDetector = null;

public void initializeMLKit(BA ba) {
    try {
        Context context = ba.context;
        BA.Log("Starting ML Kit initialization...");
        
        MlKit.initialize(context);
        BA.Log("ML Kit initialized");
        
        ObjectDetectorOptions options = new ObjectDetectorOptions.Builder()
            .setDetectorMode(ObjectDetectorOptions.SINGLE_IMAGE_MODE)
            .build();
        
        BA.Log("Creating object detector...");
        
        objectDetector = ObjectDetection.getClient(options);
        
        if (objectDetector != null) {
            BA.Log("Object detector created successfully");
            ba.raiseEvent(this, "initialization_complete");
        } else {
            BA.Log("Failed to create object detector - returned null");
            ba.raiseEvent(this, "initialization_failed", "ObjectDetection.getClient returned null");
        }
        
    } catch (Exception e) {
        BA.Log("Exception during ML Kit initialization: " + e.getMessage());
        e.printStackTrace();
        ba.setLastException(e);
        ba.raiseEvent(this, "initialization_failed", e.getMessage());
    }
}

public void detectObjects(Bitmap bitmap, BA ba) {
    try {
        BA.Log("Starting object detection...");
        
        if (objectDetector == null) {
            BA.Log("Object detector is null");
            ba.raiseEvent(this, "detection_error", "Object detector not initialized");
            return;
        }
        
        if (bitmap == null) {
            BA.Log("Bitmap is null");
            ba.raiseEvent(this, "detection_error", "Bitmap is null");
            return;
        }
        
        if (bitmap.isRecycled()) {
            BA.Log("Bitmap is recycled");
            ba.raiseEvent(this, "detection_error", "Bitmap is recycled");
            return;
        }
        
        BA.Log("Bitmap size: " + bitmap.getWidth() + "x" + bitmap.getHeight());
        
        InputImage image = InputImage.fromBitmap(bitmap, 0);
        BA.Log("InputImage created");
        
        Task<List<DetectedObject>> task = objectDetector.process(image);
        
        task.addOnSuccessListener(new OnSuccessListener<List<DetectedObject>>() {
            @Override
            public void onSuccess(List<DetectedObject> detectedObjects) {
                BA.Log("Detection successful, found " + detectedObjects.size() + " objects");
                
                StringBuilder results = new StringBuilder();
                
                if (detectedObjects.isEmpty()) {
                    results.append("No objects detected");
                } else {
                    results.append("Found ").append(detectedObjects.size()).append(" objects:\n\n");
                    
                    int objectCount = 1;
                    for (DetectedObject detectedObject : detectedObjects) {
                        results.append("Object ").append(objectCount).append(":\n");
                        
                        results.append("  Position: ")
                              .append(detectedObject.getBoundingBox().toString())
                              .append("\n");
                        
                        List<DetectedObject.Label> labels = detectedObject.getLabels();
                        if (!labels.isEmpty()) {
                            results.append("  Classifications:\n");
                            for (DetectedObject.Label label : labels) {
                                results.append("    ")
                                      .append(label.getText())
                                      .append(" (")
                                      .append(String.format("%.1f", label.getConfidence() * 100))
                                      .append("%)\n");
                            }
                        } else {
                            results.append("  No classification available\n");
                        }
                        
                        results.append("\n");
                        objectCount++;
                    }
                }
                
                ba.raiseEvent(this, "detection_success", results.toString());
            }
        });
        
        task.addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(Exception e) {
                BA.Log("Detection failed: " + e.getMessage());
                e.printStackTrace();
                ba.raiseEvent(this, "detection_failed", e.getMessage());
            }
        });
        
    } catch (Exception e) {
        BA.Log("Exception during object detection: " + e.getMessage());
        e.printStackTrace();
        ba.raiseEvent(this, "detection_error", e.toString());
    }
}
#End If

Sub initialization_complete
    isMLKitInitialized = True
    btnDetect.Enabled = True
    lblResults.Text = "ML Kit initialized successfully! Ready to detect objects."
    Log("ML Kit initialized successfully")
End Sub

Sub initialization_failed(Error As String)
    isMLKitInitialized = False
    btnDetect.Enabled = False
    lblResults.Text = "Initialization failed: " & Error
    Log("Initialization failed: " & Error)
End Sub

Sub detection_success(Results As String)
    lblResults.Text = Results
    Log("Detection results: " & Results)
End Sub

Sub detection_failed(Error As String)
    lblResults.Text = "Detection failed: " & Error
    Log("Detection failed: " & Error)
End Sub

Sub detection_error(Error As String)
    lblResults.Text = "Error: " & Error
    Log("Error: " & Error)
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
Before I came across this post, I was also digging in the same subject, but it seems that b4a does not lend itself to ML Kit easily although it deals with android for if you want to do the same thing in Android Studio, ML Kit detect object is easily integrated with 'implementation' statement. Therefore, depending on the examples from Google and Github I came out with a b4a code (manly inline Java) but still it has one stubborn error failure to initialize ML Kit:
Exception during ML Kit Initialization :Attempt to invoke virtual method 'com.google.mlkit.vision.common.internal.MultiFlavorDetectorCreator$MultiFlavorDetector com.google.mlkit.vision.common.internal.MultiFlavorDetectorCreator.create(com.google.mlkit.vision.common.internal.MultiFlavorDetectorCreator$DetectorOptions)' on a null object reference.
If you or the forum experts find a solution, sharing it will be of benefit.
B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A ML Kit Detection
    #VersionCode: 1
    #VersionName: 1.0
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
   
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

#AdditionalJar: com.google.mlkit:object-detection
#AdditionalJar: com.google.mlkit:vision-common
#AdditionalJar: com.google.android.gms:play-services-base
#AdditionalJar: com.google.android.gms:play-services-basement
#AdditionalJar: com.google.android.gms:play-services-tasks
#AdditionalJar: androidx.annotation:annotation
#AdditionalJar: kotlin-stdlib-1.6.10

Sub Process_Globals
    Private xui As XUI
    Private isMLKitInitialized As Boolean = False
End Sub

Sub Globals
    Private iv As ImageView
    Private btnDetect As Button
    Private lblResults As Label
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
   
    ' Initialize views
    iv.Initialize("iv")
    btnDetect.Initialize("btnDetect")
    lblResults.Initialize("lblResults")
   
    Activity.AddView(iv, 0, 0, 100%x, 60%y)
    Activity.AddView(btnDetect, 0, 65%y, 100%x, 15%y)
    Activity.AddView(lblResults, 0, 85%y, 100%x, 15%y)
   
    btnDetect.Text = "Detect Objects"
    btnDetect.Enabled = False
    lblResults.Text = "Initializing ML Kit..."
   
    ' Copy test image
    If Not(File.Exists(File.DirInternal,"home.jpg")) Then
        File.Copy(File.DirAssets,"home.jpg",File.DirInternal,"home.jpg")
    End If
   
    ' Load test image
    Dim bmp As Bitmap = LoadBitmap(File.DirInternal, "test.png")
    iv.Bitmap = bmp
   
    ' Wait for activity to be fully loaded, then initialize ML Kit
    Wait For Activity_Resume
    Sleep(1000) ' Give the activity time to fully load
    InitializeMLKit
End Sub

Sub InitializeMLKit
    Try
        Dim jo As JavaObject
        jo.InitializeContext
        jo.RunMethod("initializeMLKit", Array(GetBA))
    Catch
        Log("Error initializing ML Kit: " & LastException.Message)
        lblResults.Text = "ML Kit initialization error: " & LastException.Message
    End Try
End Sub

Sub btnDetect_Click
    If Not(isMLKitInitialized) Then
        lblResults.Text = "ML Kit not initialized yet"
        Return
    End If
   
    If iv.Bitmap <> Null Then
        lblResults.Text = "Detecting objects..."
        DetectObjects(iv.Bitmap)
    Else
        lblResults.Text = "No image loaded"
    End If
End Sub

Sub DetectObjects(bmp As Bitmap)
    Try
        Dim jo As JavaObject = Me
        jo.InitializeContext
        jo.RunMethod("detectObjects", Array(bmp, GetBA))
    Catch
        Log("Error in DetectObjects: " & LastException.Message)
        lblResults.Text = "Detection error: " & LastException.Message
    End Try
End Sub

Sub GetBA As JavaObject
    Dim jo As JavaObject
    Dim cls As String = Me
    cls = cls.SubString("class ".Length)
    jo.InitializeStatic(cls)
    Return jo.GetFieldJO("processBA")
End Sub

#If JAVA
import com.google.mlkit.common.MlKit;
import com.google.mlkit.vision.common.InputImage;
import com.google.mlkit.vision.objects.DetectedObject;
import com.google.mlkit.vision.objects.ObjectDetection;
import com.google.mlkit.vision.objects.ObjectDetector;
import com.google.mlkit.vision.objects.defaults.ObjectDetectorOptions;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.Task;
import android.graphics.Bitmap;
import java.util.List;
import anywheresoftware.b4a.BA;
import android.content.Context;
import android.util.Log;

private static ObjectDetector objectDetector = null;

public void initializeMLKit(BA ba) {
    try {
        Context context = ba.context;
        BA.Log("Starting ML Kit initialization...");
       
        MlKit.initialize(context);
        BA.Log("ML Kit initialized");
       
        ObjectDetectorOptions options = new ObjectDetectorOptions.Builder()
            .setDetectorMode(ObjectDetectorOptions.SINGLE_IMAGE_MODE)
            .build();
       
        BA.Log("Creating object detector...");
       
        objectDetector = ObjectDetection.getClient(options);
       
        if (objectDetector != null) {
            BA.Log("Object detector created successfully");
            ba.raiseEvent(this, "initialization_complete");
        } else {
            BA.Log("Failed to create object detector - returned null");
            ba.raiseEvent(this, "initialization_failed", "ObjectDetection.getClient returned null");
        }
       
    } catch (Exception e) {
        BA.Log("Exception during ML Kit initialization: " + e.getMessage());
        e.printStackTrace();
        ba.setLastException(e);
        ba.raiseEvent(this, "initialization_failed", e.getMessage());
    }
}

public void detectObjects(Bitmap bitmap, BA ba) {
    try {
        BA.Log("Starting object detection...");
       
        if (objectDetector == null) {
            BA.Log("Object detector is null");
            ba.raiseEvent(this, "detection_error", "Object detector not initialized");
            return;
        }
       
        if (bitmap == null) {
            BA.Log("Bitmap is null");
            ba.raiseEvent(this, "detection_error", "Bitmap is null");
            return;
        }
       
        if (bitmap.isRecycled()) {
            BA.Log("Bitmap is recycled");
            ba.raiseEvent(this, "detection_error", "Bitmap is recycled");
            return;
        }
       
        BA.Log("Bitmap size: " + bitmap.getWidth() + "x" + bitmap.getHeight());
       
        InputImage image = InputImage.fromBitmap(bitmap, 0);
        BA.Log("InputImage created");
       
        Task<List<DetectedObject>> task = objectDetector.process(image);
       
        task.addOnSuccessListener(new OnSuccessListener<List<DetectedObject>>() {
            @Override
            public void onSuccess(List<DetectedObject> detectedObjects) {
                BA.Log("Detection successful, found " + detectedObjects.size() + " objects");
               
                StringBuilder results = new StringBuilder();
               
                if (detectedObjects.isEmpty()) {
                    results.append("No objects detected");
                } else {
                    results.append("Found ").append(detectedObjects.size()).append(" objects:\n\n");
                   
                    int objectCount = 1;
                    for (DetectedObject detectedObject : detectedObjects) {
                        results.append("Object ").append(objectCount).append(":\n");
                       
                        results.append("  Position: ")
                              .append(detectedObject.getBoundingBox().toString())
                              .append("\n");
                       
                        List<DetectedObject.Label> labels = detectedObject.getLabels();
                        if (!labels.isEmpty()) {
                            results.append("  Classifications:\n");
                            for (DetectedObject.Label label : labels) {
                                results.append("    ")
                                      .append(label.getText())
                                      .append(" (")
                                      .append(String.format("%.1f", label.getConfidence() * 100))
                                      .append("%)\n");
                            }
                        } else {
                            results.append("  No classification available\n");
                        }
                       
                        results.append("\n");
                        objectCount++;
                    }
                }
               
                ba.raiseEvent(this, "detection_success", results.toString());
            }
        });
       
        task.addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(Exception e) {
                BA.Log("Detection failed: " + e.getMessage());
                e.printStackTrace();
                ba.raiseEvent(this, "detection_failed", e.getMessage());
            }
        });
       
    } catch (Exception e) {
        BA.Log("Exception during object detection: " + e.getMessage());
        e.printStackTrace();
        ba.raiseEvent(this, "detection_error", e.toString());
    }
}
#End If

Sub initialization_complete
    isMLKitInitialized = True
    btnDetect.Enabled = True
    lblResults.Text = "ML Kit initialized successfully! Ready to detect objects."
    Log("ML Kit initialized successfully")
End Sub

Sub initialization_failed(Error As String)
    isMLKitInitialized = False
    btnDetect.Enabled = False
    lblResults.Text = "Initialization failed: " & Error
    Log("Initialization failed: " & Error)
End Sub

Sub detection_success(Results As String)
    lblResults.Text = Results
    Log("Detection results: " & Results)
End Sub

Sub detection_failed(Error As String)
    lblResults.Text = "Detection failed: " & Error
    Log("Detection failed: " & Error)
End Sub

Sub detection_error(Error As String)
    lblResults.Text = "Error: " & Error
    Log("Error: " & Error)
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub
You copy home.jpg but then pass test.png.
Just an observation without testing your code.
 
Upvote 0

jkhazraji

Active Member
Licensed User
Longtime User
You copy home.jpg but then pass test.png.
Just an observation without testing your code.
That's absolutely right but even if I correct the file path, I end up with the same error:
Exception during ML Kit Initialization :Attempt to invoke virtual method 'com.google.mlkit.vision.common.internal.MultiFlavorDetectorCreator$MultiFlavorDetector com.google.mlkit.vision.common.internal.MultiFlavorDetectorCreator.create(com.google.mlkit.vision.common.internal.MultiFlavorDetectorCreator$DetectorOptions)' on a null object reference.
 
Upvote 0

jkhazraji

Active Member
Licensed User
Longtime User
First of all you should create a NEW THREAD instead of posting to other threads

I suggest to create a small testproject showing the problem and upload it.
Hard to help otherwise
I replied to the question. Here it is:
 

Attachments

  • b4a_ml_objectDetection.zip
    141 KB · Views: 23
Upvote 0

jkhazraji

Active Member
Licensed User
Longtime User
First of all you should create a NEW THREAD instead of posting to other threads

I suggest to create a small testproject showing the problem and upload it.
Hard to help otherwise
If you give advice to others, that means you have the solution.
 
Upvote 0
Top