Region Growing Algorithm

danem picture danem · May 1, 2011 · Viewed 10.7k times · Source

Hey everyone. I'm really struggling to figure out the logic with this one and was hoping you could help me out. Before I continue I just want to let you know that I am amateur programmer and a beginner at that, with no formal Computer Science training of any sort, so please bear with me. :D Also, I'm using Python, but I could use Java or something similar.

Anywho, I am looking to implement a Region Growing for use in a rudimentary Drawbot. Here is an article on region growing: http://en.wikipedia.org/wiki/Region_growing

The way I envision it, the image the draw is based upon will meet the following criteria:

  • The image will be at most 3x3 inches in size at an arbitrary Color Depth

  • The image will be a black continuous shape on a white background

  • The shape can be located anywhere on the background.

I've considered the following solutions to this problem. While some work to an extent, each has some considerable flaws in either their performance or feasibility (at least they don't seem feasible to me). Furthermore, because this is a Drawbot, this needs to be done with a single continuous line. This doesn't mean however that I can't backtrack, it only eliminates the possibility of multiple starting points (seeds).

Considered Approaches:

Random Walk:

Solving this problem with a random walk was my first instinct. A random walk program accomplishing this would, I imagine, look something like this:

pseudo python...

Cells To Visit = Number of Black Cells
Cells Visited = 0
MarkColor = red
While Cells Visited < Cells To Visit:
    if currentcell is black:
        Mark Current Cell As Visited #change pixel to red
        Cells Visited +=1
    neighbors = Get_Adjacent_Cells() #returns cells either black or red
    next cell = random.choose(neighbors)
    currentCell = next cell

While I suppose this is feasible, it seems to me to be highly ineffective and doesn't guarantee good results, but in the interest of actually getting something done I may end up trying this... Is my logic in the pseudocode even vaguely correct?

Sweeping Pattern:

This method to me seemed to be the most trivial to implement. My idea here is that I could choose a starting point at one extreme of the shape (e.g. the lowest most left point). From there it would draw to the right, moving only on the x axis until it hit a white pixel. From here it would move up one pixel on the y axis, and then move left on the x axis until it reached a white pixel. If the pixel directly above it happend to be white, backtrack on the x axis until it finds a black pixel above it.

This method upon further inspection has some major short comings. When faced with a shape such as this:

diagram1

The result will look like this:

diagram2

And even if I were to tell it to start sweeping down after awhile, the middle leg would still be overlooked.

4/8 Connected Neighborhood:

http://en.wikipedia.org/wiki/8-connected_neighborhood

This method appears to me to be the most powerful and effective, but at this point I can't figure it out fully, nor can I think of how I would implement it without potentially leaving some overlooked areas

At every cell I would look at the neighboring black cells, devise some method for ranking which one I should visit first, visit all of them, and repeat the process until all cells are covered.

The problems I could see here is first of all dealing with the data structure necessary to accomplish this, and also merely figuring out the logic behind it.


Those are the best solutions I've been able to think of. Thank you for taking the time to read this, I realize it is long, but I thought that I should make it as explicit as possible. Any and all suggestions will be greatly appreciated... Thanks!

Edit:

I also looked into maze generating and solving algorithms, but wasn't sure how to implement that here. My understanding of the maze solving algorithms is that they rely on the passages of the maze to be of equal width. I could of course be wrong about that.

Answer

YXD picture YXD · May 1, 2011

Basic region growing, in pseudocode looks something like:

seed_point // starting point
visited // boolean array/matrix, same size as image
point_queue // empty queue

point_queue.enqueue( seed_point )
visited( seed_point ) = true

while( point_queue is not empty ) {
    this_point = point_queue.dequeue()
    for each neighbour of this_point {
        if not visited( neighbour ) and neighbour is black/red/whatever
            point_queue.enqueue( neighbour )
            visited( neighbour ) = true
    }
}

// we are done. the "visited" matrix tells
// us which pixels are in the region

I don't understand where the ranking that you've mentioned comes into it though. Am I missing something?