B4J Question [Solved] Wand tool

Discussion in 'B4J Questions' started by jroriz, Sep 26, 2018.

  1. jroriz

    jroriz Active Member Licensed User

    img1.PNG
    to
    img2.PNG

    Is it possible to create something like a wand tool?

    I need to change all the yellow pixels, and then pixels "close to yellow", to black.
    Then all the rest to white.

    I was trying using BitmapCreator, and comparing pixel by pixel. But i could not figure out how to detect a range of pixels that are close to yellow.

    I think this is a hard one...
     
  2. Roycefer

    Roycefer Well-Known Member Licensed User

    There are a few ways to think about the "closeness" of a color to another color. A simple method that might work for you is to consider the RGB color space as a 3-dimensional euclidean space and just calculate distances using Pythagorean Theorem:
    Code:
    Dim colorDist As Double = Sqrt(Power(r1-r2,2)+Power(g1-g2,2)+Power(b1-b2,2))
    Then you can select a maximum permissible distance.

    There are more sophisticated ways that involve conversion to HSB color space or treating RGB color space as a vector space and taking inner products. If the Pythagorean Theorem method doesn't suit your needs, we can explore the more sophisticated solutions.

    Note that in the example picture you posted, the non-yellow pixels are all black. If this is representative of the real images you have to use, then it will be easier to just detect black pixels and turn them white and non-black pixels to black.
     
    jroriz and stevel05 like this.
  3. MarkusR

    MarkusR Well-Known Member Licensed User

    i answered in your other post.
    yellow is just red+green
     
  4. Sandman

    Sandman Well-Known Member Licensed User

    It might help more if you described how you plan to use the resulting image. I come from a Photoshop background (GIMP nowadays) so I tend to think more in that way than a strictly mathematical way that @Roycefer described.

    So, if you plan to use the resulting image as something you just display or perhaps place on top of another image, I would do this to get a perfect result.

    1. Starting image
      [​IMG]

    2. Throw away all colour, making it grayscale
      upload_2018-9-26_9-50-14.png

    3. Invert it
      upload_2018-9-26_9-50-58.png

    4. Adjusting the Levels by setting the background to white (this is not same as working with brightness, the latter destroys image data, Levels ”stretches” the available data)
      upload_2018-9-26_9-52-24.png
      (In this specific case I didn't have to set the blackpoint, the yellow was good enough to work with)

    5. And, if that's what you’re aiming for, multiplying the image into another picture:
      upload_2018-9-26_9-55-40.png
     
    KMatle likes this.
  5. MarkusR

    MarkusR Well-Known Member Licensed User

    it would look better with a lossless format like png.
    grey = (r+g+b) / 3

    Code:
    Sub Process_Globals
     
       
    Private xui As XUI
       
    Private ImageView1 As ImageView
       
    Private ImageView2 As ImageView
      ...

    Sub Test
     
        
    Dim Bitmap1 As B4XBitmap = xui.LoadBitmap(File.DirAssets,"clock.png")
     
        ImageView1.SetImage(Bitmap1) 
    '< a ImageView in layout
     
        
    Dim bc As BitmapCreator
        bc.Initialize(Bitmap1.Width,Bitmap1.Height)
        bc.CopyPixelsFromBitmap(Bitmap1)
     
        
    Dim x As Int
        
    Dim y As Int
        
    Dim pixel As ARGBColor
        
    For x = 0 To bc.mWidth-1
            
    For y = 0 To bc.mHeight-1
                bc.GetARGB(x,y,pixel)
                
    If pixel.r > 64 And pixel.b < 64 Then
                    pixel.r = pixel.r / 
    2
                    pixel.g = pixel.g / 
    4
                    pixel.b = pixel.b / 
    4
                
    Else
                    pixel.r =
    255
                    pixel.g =
    255
                    pixel.b =
    255
                
    End If
                bc.SetARGB(x,y,pixel)
            
    Next
        
    Next
     
        ImageView2.SetImage(bc.Bitmap) 
    '< a ImageView in layout
     
        Bitmap1 = bc.Bitmap
        
    Dim Out As OutputStream
        
    Log(File.DirTemp)
        Out = 
    File.OpenOutput(File.DirTemp, "Output.png"False)
        Bitmap1.WriteToStream(Out, 
    100"PNG")
        Out.Close
     
    End Sub
    Snap_2018.09.26_14h26m25s_002.png
     
    Last edited: Sep 26, 2018
    peacemaker and Erel like this.
  6. jroriz

    jroriz Active Member Licensed User

    It was perfect, using the first suggestion (from Roycefer). I did not test the others, but I greatly appreciate it!
    The result was better than I expected.
    The code I got is below. If anyone can improve it, I'm grateful.
    Thank you all. This forum is simply fantastic!

    Final code:

    Code:
    Sub Clean(Whichcolor As Int, bc As BitmapCreator)
       
        
    Dim x, y As Int
        
    Dim ProtectedColor, ARGB As ARGBColor
       
        bc.ColorToARGB(Whichcolor, ProtectedColor)
       
        
    For x = 0 To bc.mWidth-1
            
    For y = 0 To bc.mHeight-1

                bc.GetARGB(x, y, ARGB)
                
    Dim colorDist As Double = Sqrt(Power(ProtectedColor.r-ARGB.r,2)+Power(ProtectedColor.g-ARGB.g,2)+Power(ProtectedColor.b-ARGB.b,2))
               
                
    If colorDist > 200 Then
                    bc.SetColor(x,y,xui.Color_White)
                
    Else
                    bc.SetColor(x,y,xui.Color_black)
                
    End If
            
    Next
        
    Next

    End Sub
    How to call: Clean(xui.Color_white, bc), where bc is bitmapcreator.
     
    Last edited: Sep 28, 2018
    hibrid0, Erel and MarkusR like this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice