Steve on Image Processing

April 15th, 2007

Connected component labeling – Part 4

In the previous post in this series I talked about forming a graph based on pixel neighbor relationships, and then finding the connected components of the graph. Another approach starts by finding a foreground pixel and then iteratively searching that pixel's neighbors to find the connected component. Sometimes this technique is called the flood fill approach. I'll demonstrate the basic idea using a small sample image and a series of diagrams.

The matrix below and on the left is our binary image. Using 4-connected neighbors, the image has two connected components. The matrix on the right is going to become our label matrix when we're done. It is initialized to contain all zeros.

Step 1: Find a foreground pixel. Set the corresponding label matrix pixel to 1, which is the first label.

Step 2: Set the pixels that were just labeled to 0, and then find all the nonzero 4-connected neighbors. Set the corresponding pixels in the label matrix to 1.

Step 3: Set the pixels that were just labeled to 0, and then find all the nonzero 4-connected neighbors. Set the corresponding pixels in the label matrix to 1. (This step should seem familiar.)

Step 4: Set the pixels that were just labeled to 0, and then find all the nonzero 4-connected neighbors. Oops, there aren't any!

Step 5: We have finished labeling object 1. Now search for the next nonzero pixel. Set the corresponding pixel in the label matrix to 2, which is the next object label.

Step 6: Set the pixels that were just labeled to 0, and then find all the nonzero 4-connected neighbors. Set the corresponding pixels in the label matrix to 2.

Step 7: Set the pixels that were just labeled to 0, and then find all the nonzero 4-connected neighbors. Set the corresponding pixels in the label matrix to 2.

Step 8: Set the pixels that were just labeled to 0, and then find all the nonzero 4-connected neighbors. Since there aren't any, we know we have finished labeling object 2. Furthermore, since there are no nonzero pixels left in the image, we know we have completed the labeling operation.

Now let's talk about how you might program this in MATLAB. I'd use the neighbor indexing technique that I wrote about a couple of weeks ago. Start from this point:

Call the matrix on the left bw, and call the matrix on the right L.

bw = logical([0 0 0 0 0 0 0
    0 0 1 0 0 0 0
    0 1 0 1 1 1 0
    0 1 0 0 1 0 0
    0 0 0 0 0 0 0]);

L = [0 0 0 0 0 0 0
    0 1 1 0 0 0 0
    0 1 0 0 0 0 0
    0 0 0 0 0 0 0
    0 0 0 0 0 0 0];

The linear indices of the pixels that were just labeled are 8 and 12:

idx = [8; 12];

Here are the neighbor offsets for a four-connected neighborhood:

offsets = [-1; 5; 1; -5];

"Set the pixels that were just labeled to 0".

bw(idx) = 0;

"Find all the nonzero 4-connected neighbors." Do this by adding all neighbor offsets to all pixels in the current set.

neighbors = bsxfun(@plus, idx, offsets')
neighbors =

     7    13     9     3
    11    17    13     7

Remove duplicates.

neighbors = unique(neighbors(:))
neighbors =

     3
     7
     9
    11
    13
    17

Keep only the neighbors that are nonzero.

idx = neighbors(bw(neighbors))
idx =

    13

"Set the corresponding pixels in the label matrix to 1."

L(idx) = 1;

You'd repeat these operations in a loop until idx was empty, indicating that a connected component has been completely labeled.

I've covered two connected components methods in this series so far. In my next post I'll start to explain a third method - the one used by the Image Processing Toolbox functions bwlabel and bwlabeln.

PS. Good luck to everyone running in the Boston Marathon tomorrow!


Get the MATLAB code

Published with MATLAB® 7.4

26 Responses to “Connected component labeling – Part 4”

  1. jxwht replied on :

    Hi,Steve,it has a small mistake,the sentence:
    idx = neighbors(bw(neigbhors))
    should be
    idx = neighbors(bw(neighbors))

  2. Steve replied on :

    Jxwht—Thanks. I fixed the problem.

  3. Khosrow replied on :

    Hi Steve,
    the flood-fill algorithm you described here depends on the initial point you pick in each component. sometimes, it fails to detect all white pixels in the area.
    Khosrow

  4. Steve replied on :

    Khosrow—I don’t believe it does, but if you care to give an example I’ll take a look at it.

  5. Khosrow replied on :

    Steve, I don’t use MATHLAB. I just implemented this approach in Yorick. My program works fine for simple geometries. Even for complicated patterns, sometimes it is successful, but not always, depending on which initial pixel you pick in each region. My guess is that some sort of closed black bands form around a pixels blocking the algorithm to access the pixels beyond.
    anyways, I can send you a sample image, if you want. please, let me know your email.

  6. Steve replied on :

    Khosrow—The algorithm described here is for finding connected components. If a “closed black band forms around pixels blocking [access to] the pixels beyond,” then you don’t have a single connected component. I don’t know what you were trying to accomplish in your own implementation, but apparently the goal was something other than finding connected components.

  7. Khosrow replied on :

    Steve – True. I have several white foreground areas embedded in black background, and I want to index all the pixels in the first white region by 1, then all the pixels in the second region by 2, and etc. so that, later I can assign a property, let say color, to each region. I thought, this is what the flood-fill approach is supposed to do! even in the example given here, you have two separated areas. if there is only a single white area surrounded by black background all around, then what is the point of indexing at the first place? I can just say that all white pixels have index 1.

  8. Steve replied on :

    Khosrow—This post only sketches out the idea of one particular connected-component algorithm; it doesn’t provide the details. (The Image Processing Toolbox already provides this capability, after all.) In particular, once a particular region is marked, you have to continue scanning the image to find a pixel in the next region and then start the flood-filling process again from there.

  9. Khosrow replied on :

    Steve- OK. thanks a lot for sharing your expertise with us.

  10. stefano replied on :

    hi steve, why do you put ” offsets = [-1; 5; 1; -5];” ? I dont understand that .

  11. Steve replied on :

    Stefano—See my neighbor indexing post.

  12. stefano replied on :

    the last idx you put was idx=13… mmm i think that your last idx must be = 9 ; because of the step3 (figure) .

  13. Steve replied on :

    Stefano—Looks like that might be right, thanks.

  14. jorge replied on :

    Steve your post is great!!
    How can I programatically find the foreground pixel?. Is there any function in Matlab that can do this for us?

  15. Steve replied on :

    Jorge—Take a look at graythresh and im2bw.

  16. Domenico Schettini Filho replied on :

    Hi Steve.
    I am brazilian so i don´t write very well in english, sorry about this.
    This algorithm that you write here has a name? And where i can find an explanation about this algorithm?
    I am thinking in using this algorithm in a study of college.
    Thanks fou your attention.

  17. Steve replied on :

    Domenico—There are a couple of key terms mentioned in this post: “connected-component labeling” and “flood fill.”

  18. Domenico Schettini Filho replied on :

    Steve where i can find theoretical definition about this algorithm? For example, what books i can find an explanation of the algorithm?
    Thanks again.

  19. Steve replied on :

    Domenico—These are pretty widely used terms. I think you can use some basic Internet searches to find a lot of information about them.

  20. Domenico Schettini Filho replied on :

    Steve I’ve searched a more formal explanation of “connected-component labeling” and “flood fill” algorithm in a book or paper and I haven’t found nothing good on the internet. you know some material that explains this algorithm formally?
    Thanks.

  21. Steve replied on :

    Domenico—Seriously? The first link I see when I Google for “connected component labeling” is for a lengthy Wikipedia article with detailed descriptions of several algorithms, a number of diagrams, relevant cross references, and external reference links.

  22. Domenico Schettini Filho replied on :

    Yes it’s seriously. I need to get this information from websites, books, or anywhere else where there is a recognition by the scientific community.

  23. Domenico Schettini Filho replied on :

    But tahnks for your attention.

  24. Steve replied on :

    Domenico—Well, then, you could start with the search I suggested in my previous comment.

  25. ethan replied on :

    Hi Steve,

    Can you advice me how can I use this approach to assign index for the object which are separate and may be very closely placed in an image, such as image of a section of plant stem image showing closely placed cells. What if I want to assign a number in index for each of the cells even if they are very close to each other? The only distinction is the boundary of each cell separating them and shape is quite variable for each of the cells?

    Thanks

  26. Steve replied on :

    Ethan—You might want to look at my 07-Sep-2011 post, “almost-connected-component labeling.”


MathWorks
Steve Eddins is a software development manager in the MATLAB and image processing areas at MathWorks. Steve coauthored Digital Image Processing Using MATLAB. He writes here about image processing concepts, algorithm implementations, and MATLAB.

These postings are the author's and don't necessarily represent the opinions of The MathWorks.