trace the outline of a shape on a bitmap **RESOLVED**-VBForums
Results 1 to 14 of 14

Thread: trace the outline of a shape on a bitmap **RESOLVED**

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Oct 1999
    Location
    England
    Posts
    982

    trace the outline of a shape on a bitmap **RESOLVED**

    I have a picturebox with a bitmap. White background with red circle in it.
    How do I trace the edge of the red circle so I can reproduce its position and size with code onto another picturebox.

    My thought was to start at 0,0 and check each pixel row by row. For each row remember the first and last red pixel and change it to black to indicate the edge to the user.

    The shape on the image is owner drawn and will always be the same colour though the size and shape may differ.
    Last edited by davidrobin; Mar 21st, 2003 at 08:51 AM.

  2. #2

    Thread Starter
    Fanatic Member
    Join Date
    Oct 1999
    Location
    England
    Posts
    982
    I have included an image to represent the before and after of what the user sees.

    One problem of the method above would be if the image is really odd like a paint splat, some rows will have more than one red section.
    Attached Images Attached Images  

  3. #3
    Lively Member
    Join Date
    May 2000
    Posts
    84
    You can always try checking the neighbor of each pixel
    If any rook-wise adjacent neighbor is red and the pixel it self is not red then set the pixel to black.

    There are better (faster) ways but this should work.

    Pseudocode:

    Code:
    For each pixel (x, y)
      If  ( (x, y) != RED ) Then
    
        If ( (x, y-1) = RED ) or ( (x, y+1) = RED ) or 
           ( (x-1, y) = RED ) or ( (x+1, y) = RED ) Then
        
          SetPixel (x,y) = BLACK
    
        End If
      End If
    End For

  4. #4

    Thread Starter
    Fanatic Member
    Join Date
    Oct 1999
    Location
    England
    Posts
    982
    To further complicate things I have to recreate the shape in another picture box (for example) by using the polygon function. There fore I literally have to trace round the perimeter of the shape starting and ending at the same point.

  5. #5
    Lively Member
    Join Date
    May 2000
    Posts
    84
    Find one pixel that lies on the edge of the shape you want to trace around. This is your current pixel.

    Look at the eight adjacent neighbors for a place where the color changes (in your case from red to white)

    When looking for that point where the edge changes always start your next search where you left off in the last search.
    That way things go fast for large straing edges

    If that point is NOT the desired color then move counter-clockwise around the edge until it is.

    If the point is the desired color move clockwise around the edge until it changes.

    Select that edge pixel as your new current pixel. Repeat above until you get back to, or near, the first pixel.

    Beacuse some shapes might be very large recording every pixel to map back onto a polygon can get quite tedious. To fix this, just save every 3rd or 5th pixel on the edge until you get back to the starting pixel.

    You can also eliminate points by checking whether the 3rd pixel in a series of pixels lies on the same line as the previous two pixels. If so then delete the second pixel.

  6. #6

    Thread Starter
    Fanatic Member
    Join Date
    Oct 1999
    Location
    England
    Posts
    982
    Illustrator,
    I kind of understand what you are suggesting but am not being very successful at implementing it.

    I have included a framework with a picture box and image. The image is a circle (nice and simple) At the moment the program looks along each row at every pixel until it finds a red pixel. At that point my abilities fail me.

    I have included an image with a less standard shape on it as this program will have no idea what the image shape may be.

    If anyone can fill in a bit of code I would be grateful

  7. #7

    Thread Starter
    Fanatic Member
    Join Date
    Oct 1999
    Location
    England
    Posts
    982
    Oh dear, forgot to add the attachment.
    Attached Files Attached Files

  8. #8
    Lively Member
    Join Date
    May 2000
    Posts
    84
    I wrote some code that works quite well for what you are doing.
    There are a couple of cases where the program will have troubles

    1) if the red image ever touches the edge of the picture box
    2) if there are thin white lines breaking up the image
    3) if the image has inside components (like a donut)

    The above cases can be fixed with a little creativity.

    Anyways here is what I wrote (you should be able to make it more efficient, especially the clockwise and counterclockwise looping rountines)

    Code:
    Dim row As Integer, startrow As Integer
    Dim column As Integer, startcolumn As Integer
    Dim i As Integer
    Dim j As Integer
    Dim EdgePoints() As POINTAPI
    Dim PointCount As Integer
    
        'start in the image corner
        row = 0
        column = 0
        
        'while we are not on an edge and not at the end of the image
        While ((Picture1.Point(column, row) <> vbRed) And (row <> Picture1.ScaleHeight))
            column = column + 1
            If (column = Picture1.ScaleWidth) Then
                column = 0
                row = row + 1
            End If
        Wend
        
        'if not at the end of the image start the trace routine
        If (row <> Picture1.ScaleHeight) Then
            
            'set the the point above as the start point
            startrow = row - 1
            startcolumn = column
          
            'set the next starting point
            column = column - 1
                    
            'save the first points
            PointCount = 2
            ReDim Preserve EdgePoints(PointCount)
            EdgePoints(1).X = startcolumn
            EdgePoints(1).Y = startrow
            EdgePoints(PointCount - 1).X = column
            EdgePoints(PointCount - 1).Y = row
            
            'draw the two border points
            Picture1.PSet (startcolumn, startrow), QBColor(0)
            Picture1.PSet (column, row), QBColor(0)
            
            i = 0
            j = 1
            While ((column <> startcolumn Or row <> startrow) And PointCount < 10000)
                
                'scan clockwise if red
                While (Picture1.Point(column + i, row + j) = vbRed)
                    If (i = -1 And j = -1) Then
                        i = i + 1
                    ElseIf (i = 0 And j = -1) Then
                        i = i + 1
                    ElseIf (i = 1 And j = -1) Then
                        j = j + 1
                    ElseIf (i = 1 And j = 0) Then
                        j = j + 1
                    ElseIf (i = 1 And j = 1) Then
                        i = i - 1
                    ElseIf (i = 0 And j = 1) Then
                        i = i - 1
                    ElseIf (i = -1 And j = 1) Then
                        j = j - 1
                    ElseIf (i = -1 And j = 0) Then
                        j = j - 1
                    End If
                Wend
                
                'scan counter-clockwise is not red
                While (Picture1.Point(column + i, row + j) <> vbRed)
                    If (i = -1 And j = -1) Then
                        j = j + 1
                    ElseIf (i = 0 And j = -1) Then
                        i = i - 1
                    ElseIf (i = 1 And j = -1) Then
                        i = i - 1
                    ElseIf (i = 1 And j = 0) Then
                        j = j - 1
                    ElseIf (i = 1 And j = 1) Then
                        j = j - 1
                    ElseIf (i = 0 And j = 1) Then
                        i = i + 1
                    ElseIf (i = -1 And j = 1) Then
                        i = i + 1
                    ElseIf (i = -1 And j = 0) Then
                        j = j + 1
                    End If
                Wend
                
                'step back to the last white pixel
                If (i = -1 And j = -1) Then
                    i = i + 1
                ElseIf (i = 0 And j = -1) Then
                    i = i + 1
                ElseIf (i = 1 And j = -1) Then
                    j = j + 1
                ElseIf (i = 1 And j = 0) Then
                    j = j + 1
                ElseIf (i = 1 And j = 1) Then
                    i = i - 1
                ElseIf (i = 0 And j = 1) Then
                    i = i - 1
                ElseIf (i = -1 And j = 1) Then
                    j = j - 1
                ElseIf (i = -1 And j = 0) Then
                    j = j - 1
                End If
                
                'update pixel position
                column = column + i
                row = row + j
                
                'draw the border
                Picture1.PSet (column, row), QBColor(0)
                
                'add the new point to the data set
                PointCount = PointCount + 1
                ReDim Preserve EdgePoints(PointCount)
                EdgePoints(PointCount - 1).X = column
                EdgePoints(PointCount - 1).Y = row
                
            Wend
        End If
        
        MsgBox "PointCount:" & PointCount

  9. #9

    Thread Starter
    Fanatic Member
    Join Date
    Oct 1999
    Location
    England
    Posts
    982
    I have given it quick run through and it works fine. Absolutely amazing, well it is for me all I do at work is database programming (SQL 7) and vb. Nothing exciting like this.

    I'm not worthy

  10. #10
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755
    if theres a red circle with a hole in, Illuminator's code wont fill those outlines....
    this code fills all outlines! just click the BG....it also has a function to store object info...that means that it stores all objects pixel colors in a stack to be redrawn with another background (first click the BG, then on the other pic)...
    check it out!
    Attached Files Attached Files
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

  11. #11

    Thread Starter
    Fanatic Member
    Join Date
    Oct 1999
    Location
    England
    Posts
    982
    Cyborg: Certainly puts a different perspective on how to do it.

    Originally posted by Illuminator
    I wrote some code that works quite well for what you are doing.
    There are a couple of cases where the program will have troubles

    1) if the red image ever touches the edge of the picture box
    2) if there are thin white lines breaking up the image
    3) if the image has inside components (like a donut)

    The above cases can be fixed with a little creativity.
    It is a requirement that the above scenarios do not happen. I will put some checks in my code to make sure.

    Thanks all for your help.

  12. #12
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755
    my program dont have any of those problems...
    plus it's not only for red objects...
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

  13. #13

    Thread Starter
    Fanatic Member
    Join Date
    Oct 1999
    Location
    England
    Posts
    982
    Can I then redraw the shape from the bitmap on to another picture box using the polygon API call which is ultimately what I have to do.

  14. #14
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755
    dunno....have never used that api.....i just store those pixels positions and colors in an array and then go through that array and use setpixelv with the .x, .y and .color
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width

Survey posted by VBForums.