Other Wizard to select the edges of an image

Star-Dust

Expert
Licensed User
Longtime User
I started a small algorithm to trace and the edges of an image.
With this little code, it traces the edges of the second image, the frame. And with that track I cut the image of the horse.

ezgif.com-crop.gif


I'm still working on it, I do not want to reach very high levels but I would like to perfect it. :D:D:D
 

Star-Dust

Expert
Licensed User
Longtime User
Even if finding the edges is one thing, tracing the contours is another.

Because to find the edges, with this algorithm, we calculate the derivative of the image and identify the points that reach a certain value, those are the edges.

But to make a cut you have to have the points sorted sequentially, to get the points adjacent to the other, to be able to go through the canvas path to cut then the image.

This algorithm does not necessarily list the points sequentially, starting from the first and moving to the nearest one so as to draw a line. But you could have them in a disordered way too ..
I remain convinced that in any case it is necessary to have a recursive function that starting from a point on board goes to find the next closest one, etc.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Note that with BitmapCreator you can use "brute force" to do similar thing quite easily:

SS-2018-04-27_08.33.47.png


B4X:
Sub CropImageBaseOnMask (src As B4XBitmap, Mask As B4XBitmap) As B4XBitmap
   Dim target As BitmapCreator
   target.Initialize(src.Width, src.Height)
   target.CopyPixelsFromBitmap(Mask)
   Dim srcbc As BitmapCreator
   srcbc.Initialize(src.Width, src.Height)
   srcbc.CopyPixelsFromBitmap(src)
   For x = 0 To srcbc.mWidth - 1
       For y = 0 To srcbc.mHeight - 1
           If target.IsTransparent(x, y) = False Then
               target.CopyPixel(srcbc, x, y, x, y)
           End If
       Next
   Next
   Return target.Bitmap
End Sub

(I'm moving the thread to the questions forum to make it searchable)

Edit: changed the code to use IsTransparent which is more clear and also a bit faster.
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
Of course.

I did in other cases with Canvas and Bitmap and it is easier than finding the edges.
I have seen examples similar to yours (not XUI) to make a circular image made I believe by @DonManfred or @JordiCP
Copying an image from one Bitmap to another only at points where the frame in the corresponding point is not transparent.
This means that the frame is completely colored and translucent in outline

I used to superimpose the frame on the image to get a similar result (Https://www.b4x.com/android/forum/threads/save-only-the-image-inside-the-panel.92333/#post-584133)
This is because I needed to have the center of the transparent frame and therefore the edge had to be colored, so I adopted another method

But the goal of this algorithm is another, that is to identify the edges of an image, for me it is only an academic exercise
 
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
I did in other cases with Canvas and Bitmap
This solution is different and was not possible before (at least not with such simple code). It uses BitmapCreator to directly access the pixels data. There is no Canvas involved.

ut the goal of this algorithm is another, that is to identify the edges of an image, for me it is only an academic exercise
This is definitely an interesting algorithm. I just wanted to show how BitmapCreator can also be used here.
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
This solution is different and was not possible before (at least not with such simple code). It uses BitmapCreator to directly access the pixels data. There is no Canvas involved.


This is definitely an interesting algorithm. I just wanted to show how BitmapCreator can also be used here.
The code to which I referred was this:
https://www.b4x.com/android/forum/t...-a-round-corners-panel-how.60310/#post-380309

By replacing Canvas.DrawDrawable on the canvas, but draw the frame with Canvas.DrawBitmap Get the same result.

Of course the code is slightly longer
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
The main differences are:

- Speed. In this case it is 18 times faster.
- BitmapCreator is cross platform.

B4X:
Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("1")
   Dim src As B4XBitmap = xui.LoadBitmapResize(File.DirAssets, "white-black-horse-14593326.jpg", 400, 400, False)
   Dim mask As B4XBitmap = xui.LoadBitmapResize(File.DirAssets, "1200px-Heart_corazn.svg.png", 400, 400, False)
   Dim n As Long = DateTime.Now
   For i = 1 To 10
       Activity.SetBackgroundImage(CropImageBaseOnMaskWithBitmapCreator(src, mask))
   Next
   Log($"BitmapCreator: time per iteration: $1.1{(DateTime.Now - n) / 10}"$)
   Dim n As Long = DateTime.Now
   For i = 1 To 10
       Activity.SetBackgroundImage(CropImageBaseOnMaskWithCanvas(src, mask))
   Next
   Log($"Canvas: time per iteration: $1.1{(DateTime.Now - n) / 10}"$)
End Sub

Sub CropImageBaseOnMaskWithBitmapCreator (src As B4XBitmap, Mask As B4XBitmap) As B4XBitmap
   Dim target As BitmapCreator
   target.Initialize(src.Width, src.Height)
   target.CopyPixelsFromBitmap(Mask)
   Dim srcbc As BitmapCreator
   srcbc.Initialize(src.Width, src.Height)
   srcbc.CopyPixelsFromBitmap(src)
   For x = 0 To srcbc.mWidth - 1
       For y = 0 To srcbc.mHeight - 1
           If target.IsTransparent(x, y) = False Then
               target.CopyPixel(srcbc, x, y, x, y)
           End If
       Next
   Next
   Return target.Bitmap
End Sub


Sub CropImageBaseOnMaskWithCanvas(src As Bitmap, mask As Bitmap) As Bitmap
   Dim B1,B2 As Bitmap
   Dim cv As Canvas
   B1.InitializeMutable(src.Width, src.Height)
   cv.Initialize2(B1)
   Dim rt As Rect
   rt.Initialize(0, 0, src.Width, src.Height)
   cv.DrawBitmap(src, Null, rt)
  
   B2.InitializeMutable(src.Width, src.Height)
   cv.Initialize2(B2)
   cv.DrawBitmap(mask, Null, rt)
   For r=0 To B2.Height-1
       For c=0 To B2.Width-1
           If B2.GetPixel(c,r)<>Colors.Transparent Then
               cv.DrawPoint(c,r,B1.GetPixel(c,r))
           End If
       Next
   Next
   Return B2

BitmapCreator: time per iteration: 13.5 ms
Canvas: time per iteration: 249 ms
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
Very good :) I will learn to use it
 
Upvote 0
Top