Android Question how to remove an image background

jkhazraji

Active Member
Licensed User
Longtime User
Is there a b4a code to remove an image background. Some paid sites do that by ai. Is there a way in b4a?
 

DonManfred

Expert
Licensed User
Longtime User
Like this?

This may also work:
 
Upvote 3

jkhazraji

Active Member
Licensed User
Longtime User
Like this?

This may also work:
Great, Thanks. That is very close, but I need the foreground bitmap rather than the white mask.
 
Upvote 0

jkhazraji

Active Member
Licensed User
Longtime User
While it was likely, you did not specify that you wanted to do this programmatically, in your app, and since you wrote:

I thought you just wanted to create images, using external tools, to use in your projects.
I said b4a code. I will be grateful for any. 🙏
 
Last edited:
Upvote 0

walterf25

Expert
Licensed User
Longtime User
I modified Erel's code to fit my needs, this code works fine for me, removing the background completely, it only works for B4A, I still have not gotten a perfect solution for B4i.

Selfie Segmenter:
'v1.01
Sub Class_Globals
    Type SegmentationResult (Success As Boolean, ForegroundBitmap As B4XBitmap, ForegroundMask As B4XBitmap)
    Private segmenter As JavaObject
    Private xui As XUI
End Sub

Public Sub Initialize
    Dim options As JavaObject
    options.InitializeNewInstance("com.google.mlkit.vision.segmentation.subject.SubjectSegmenterOptions.Builder", Null)
    options = options.RunMethodJO("enableForegroundBitmap", Null).RunMethodJO("enableForegroundConfidenceMask", Null).RunMethod("build", Null)
    Dim SubjectSegmentation As JavaObject
    SubjectSegmentation.InitializeStatic("com.google.mlkit.vision.segmentation.subject.SubjectSegmentation")
    segmenter = SubjectSegmentation.RunMethod("getClient", Array(options))
End Sub

Private Sub CreateInputImage(bmp As B4XBitmap) As Object
    Dim InputImage As JavaObject
    InputImage.InitializeStatic("com.google.mlkit.vision.common.InputImage")
    Return InputImage.RunMethod("fromBitmap", Array(bmp, 0))
End Sub

Public Sub Process (bmp As B4XBitmap, getForeGroundMask As Boolean, maskColor As Int) As ResumableSub
    Dim image As JavaObject = CreateInputImage(bmp)
    Dim width, height As Int
    width = image.RunMethod("getWidth", Null)
    height = image.RunMethod("getHeight", Null)
    Dim colores(width & height) As Int
    Dim task As JavaObject = segmenter.RunMethod("process", Array(image))
    Do While task.RunMethod("isComplete", Null).As(Boolean) = False
        Sleep(50)
    Loop
    Dim res As SegmentationResult
    res.Initialize
    If task.RunMethod("isSuccessful", Null) Then
        res.Success = True
        Dim SubjectSegmentationResult As JavaObject = task.RunMethod("getResult", Null)
        res.ForegroundBitmap = SubjectSegmentationResult.RunMethod("getForegroundBitmap", Null)
      
        If getForeGroundMask Then
        Dim ForegroundMask As JavaObject
        ForegroundMask = SubjectSegmentationResult.RunMethod("getForegroundConfidenceMask", Null)
        Dim bitmapMask As BitmapCreator
        bitmapMask.Initialize(width, height)
        For i = 0 To (width * height) - 1
            If (ForegroundMask.RunMethod("get", Null)) > 0.5 Then
                colores(i) = maskColor
            Else
                colores(i) = xui.Color_White
            End If
        Next
        Dim bmpx As JavaObject
        Dim foregroundBitmap As B4XBitmap
        bmpx = bmpx.InitializeStatic("android.graphics.Bitmap")
        Dim config As JavaObject
        config = config.InitializeStatic("android.graphics.Bitmap.Config")
        bmpx = bmpx.RunMethodJO("createBitmap", Array(colores, width, height, config.GetField("ARGB_8888")))
        foregroundBitmap = bmpx
        res.ForegroundMask = foregroundBitmap
        End If
    End If
    Return res
End Sub

The changes were made in the Sub Process function, I added a few parameters to retrieve either the Mask or the foregound bitmap and also in the Initialize Sub to enable the foreground confidence mask.

B4X:
Public Sub Initialize
    Dim options As JavaObject
    options.InitializeNewInstance("com.google.mlkit.vision.segmentation.subject.SubjectSegmenterOptions.Builder", Null)
    options = options.RunMethodJO("enableForegroundBitmap", Null).RunMethodJO("enableForegroundConfidenceMask", Null).RunMethod("build", Null)
    Dim SubjectSegmentation As JavaObject
    SubjectSegmentation.InitializeStatic("com.google.mlkit.vision.segmentation.subject.SubjectSegmentation")
    segmenter = SubjectSegmentation.RunMethod("getClient", Array(options))
End Sub

Hope this is what you are looking for, let me know if this works for you.

Walter
 
Last edited:
Upvote 0

jkhazraji

Active Member
Licensed User
Longtime User
I modified Erel's code to fit my needs, this code works fine for me, removing the background completely, it only works for B4A, I still have not gotten a perfect solution for B4i.

Selfie Segmenter:
'v1.01
Sub Class_Globals
    Type SegmentationResult (Success As Boolean, ForegroundBitmap As B4XBitmap, ForegroundMask As B4XBitmap)
    Private segmenter As JavaObject
    Private xui As XUI
End Sub

Public Sub Initialize
    Dim options As JavaObject
    options.InitializeNewInstance("com.google.mlkit.vision.segmentation.subject.SubjectSegmenterOptions.Builder", Null)
    options = options.RunMethodJO("enableForegroundBitmap", Null).RunMethodJO("enableForegroundConfidenceMask", Null).RunMethod("build", Null)
    Dim SubjectSegmentation As JavaObject
    SubjectSegmentation.InitializeStatic("com.google.mlkit.vision.segmentation.subject.SubjectSegmentation")
    segmenter = SubjectSegmentation.RunMethod("getClient", Array(options))
End Sub

Private Sub CreateInputImage(bmp As B4XBitmap) As Object
    Dim InputImage As JavaObject
    InputImage.InitializeStatic("com.google.mlkit.vision.common.InputImage")
    Return InputImage.RunMethod("fromBitmap", Array(bmp, 0))
End Sub

Public Sub Process (bmp As B4XBitmap, getForeGroundMask As Boolean, maskColor As Int) As ResumableSub
    Dim image As JavaObject = CreateInputImage(bmp)
    Dim width, height As Int
    width = image.RunMethod("getWidth", Null)
    height = image.RunMethod("getHeight", Null)
    Dim colores(width & height) As Int
    Dim task As JavaObject = segmenter.RunMethod("process", Array(image))
    Do While task.RunMethod("isComplete", Null).As(Boolean) = False
        Sleep(50)
    Loop
    Dim res As SegmentationResult
    res.Initialize
    If task.RunMethod("isSuccessful", Null) Then
        res.Success = True
        Dim SubjectSegmentationResult As JavaObject = task.RunMethod("getResult", Null)
        res.ForegroundBitmap = SubjectSegmentationResult.RunMethod("getForegroundBitmap", Null)
     
        If getForeGroundMask Then
        Dim ForegroundMask As JavaObject
        ForegroundMask = SubjectSegmentationResult.RunMethod("getForegroundConfidenceMask", Null)
        Dim bitmapMask As BitmapCreator
        bitmapMask.Initialize(width, height)
        For i = 0 To (width * height) - 1
            If (ForegroundMask.RunMethod("get", Null)) > 0.5 Then
                colores(i) = maskColor
            Else
                colores(i) = xui.Color_White
            End If
        Next
        Dim bmpx As JavaObject
        Dim foregroundBitmap As B4XBitmap
        bmpx = bmpx.InitializeStatic("android.graphics.Bitmap")
        Dim config As JavaObject
        config = config.InitializeStatic("android.graphics.Bitmap.Config")
        bmpx = bmpx.RunMethodJO("createBitmap", Array(colores, width, height, config.GetField("ARGB_8888")))
        foregroundBitmap = bmpx
        res.ForegroundMask = foregroundBitmap
        End If
    End If
    Return res
End Sub

The changes were made in the Sub Process function, I added a few parameters to retrieve either the Mask or the foregound bitmap and also in the Initialize Sub to enable the foreground confidence mask.

B4X:
Public Sub Initialize
    Dim options As JavaObject
    options.InitializeNewInstance("com.google.mlkit.vision.segmentation.subject.SubjectSegmenterOptions.Builder", Null)
    options = options.RunMethodJO("enableForegroundBitmap", Null).RunMethodJO("enableForegroundConfidenceMask", Null).RunMethod("build", Null)
    Dim SubjectSegmentation As JavaObject
    SubjectSegmentation.InitializeStatic("com.google.mlkit.vision.segmentation.subject.SubjectSegmentation")
    segmenter = SubjectSegmentation.RunMethod("getClient", Array(options))
End Sub

Hope this is what you are looking for, let me know if this works for you.

Walter
After replacing the code you recommended and using getForeGroundMask as True and maskColor as colors.White, I did not get it working. Can you supply an example please.
 
Upvote 0

walterf25

Expert
Licensed User
Longtime User
After replacing the code you recommended and using getForeGroundMask as True and maskColor as colors.White, I did not get it working. Can you supply an example please.
Try getForeGroundMask to False if you want to remove the background, set to True only if you want to retrieve the Mask.
 
Upvote 0

jkhazraji

Active Member
Licensed User
Longtime User
Try getForeGroundMask to False if you want to remove the background, set to True only if you want to retrieve the Mask.
Thanks. This code does not work:
B4X:
Dim cc As ContentChooser
    cc.Initialize("cc")
    cc.Show("image/*", "choose image")
    Wait For cc_Result (Success As Boolean, Dir As String, FileName As String)
    If Success Then
        'I'm resizing the image here. It might be better to leave the image with the original resolution.
        Dim bmp As B4XBitmap = xui.LoadBitmapResize(Dir, FileName, B4XImageView1.mBase.Width, B4XImageView1.mBase.Height, True)
        B4XImageView1.Bitmap = bmp
        B4XImageView2.Clear
        Wait For (segmenter.Process(bmp, True, Colors.White)) Complete (Result As SegmentationResult)
        If Result.Success Then
            B4XImageView2.Bitmap = Result.ForegroundBitmap
        End If
    End If
Result.Success is always False
 
Upvote 0

walterf25

Expert
Licensed User
Longtime User
Thanks. This code does not work:
B4X:
Dim cc As ContentChooser
    cc.Initialize("cc")
    cc.Show("image/*", "choose image")
    Wait For cc_Result (Success As Boolean, Dir As String, FileName As String)
    If Success Then
        'I'm resizing the image here. It might be better to leave the image with the original resolution.
        Dim bmp As B4XBitmap = xui.LoadBitmapResize(Dir, FileName, B4XImageView1.mBase.Width, B4XImageView1.mBase.Height, True)
        B4XImageView1.Bitmap = bmp
        B4XImageView2.Clear
        Wait For (segmenter.Process(bmp, True, Colors.White)) Complete (Result As SegmentationResult)
        If Result.Success Then
            B4XImageView2.Bitmap = Result.ForegroundBitmap
        End If
    End If
Result.Success is always False
Try it like this, setting getForegroundMask to False

B4X:
Dim cc As ContentChooser
    cc.Initialize("cc")
    cc.Show("image/*", "choose image")
    Wait For cc_Result (Success As Boolean, Dir As String, FileName As String)
    If Success Then
        'I'm resizing the image here. It might be better to leave the image with the original resolution.
        Dim bmp As B4XBitmap = xui.LoadBitmapResize(Dir, FileName, B4XImageView1.mBase.Width, B4XImageView1.mBase.Height, True)
        B4XImageView1.Bitmap = bmp
        B4XImageView2.Clear
        Wait For (segmenter.Process(bmp, False, Colors.White)) Complete (Result As SegmentationResult)
        If Result.Success Then
            B4XImageView2.Bitmap = Result.ForegroundBitmap
        End If
    End If

Try it with the attached modified project.
 

Attachments

  • Segmentation.zip
    12.4 KB · Views: 5
Last edited:
Upvote 0
Top