Steve on Image Processing

July 13th, 2009

A new look for connected component labeling in R2009a – Part 2

Last week I wrote about our desire to reduce the memory used by bwlabel. I also wrote about other issues we hoped to address:

  • The label matrix uses memory proportional to the total number of image pixels. This seems unreasonable when you're working with an image containing only a few object pixels.
  • When bwlabel was used with regionprops (a frequent combination), some computational work was duplicated in both functions.
  • Many users never use the label matrix directly. They only compute it in order to pass it to regionprops. That implies there may be a simpler, more usable interface design.

With so much code out there using bwlabel and regionprops, though, we did not want to introduce any compatibility problems.

Our solution was to introduce two new functions in R2009a, bwconncomp and labelmatrix, as well as a couple of new syntaxes for the existing function regionprops.

The new function bwconncomp finds the connected components of a binary image, just as bwlabel does. But it does not return the result as a label matrix.

BW = [1     1     1     0     0     0     0     0
      1     1     1     0     1     1     0     0
      1     1     1     0     1     1     0     0
      0     0     0     0     0     0     1     0
      0     0     0     0     0     0     1     0
      0     0     0     0     0     0     1     0
      0     1     1     0     0     1     1     0
      0     1     1     0     0     0     0     0];

s = bwconncomp(BW)
s = 

    Connectivity: 8
       ImageSize: [8 8]
      NumObjects: 3
    PixelIdxList: {[9x1 double]  [4x1 double]  [9x1 double]}

As you can see, bwconncomp produces a structure. The critical information for subsequent processing is the PixelIdxList field, which contains the linear indices of the pixels belonging to each object. For example, the 2nd object found comprises four pixels with the following linear indices:

s.PixelIdxList{2}
ans =

    15
    16
    23
    24

A key aspect of this design is that the amount of memory required is proportional to the number of object pixels, not the number of image pixels. For a 1000-by-1000 image containing a single foreground pixel, the output data structure is nicely compact:

BW2 = false(1000, 1000);
BW2(500, 500) = true;
s2 = bwconncomp(BW2)
s2 = 

    Connectivity: 8
       ImageSize: [1000 1000]
      NumObjects: 1
    PixelIdxList: {[499500]}

whos s2
  Name      Size            Bytes  Class     Attributes

  s2        1x1               596  struct              

You can compute the label matrix, if you really need it, using the new function labelmatrix.

L2 = labelmatrix(s2);
whos L2
  Name         Size                Bytes  Class    Attributes

  L2        1000x1000            1000000  uint8              

Notice that L2 is a uint8 matrix. Unlike bwlabel, labelmatrix does adjust the output data type based on the number of objects.

The last related change was to regionprops. As I mentioned before, we've noticed that this is a very common coding pattern:

  L = bwlabel(bw);
  s = regionprops(L, ...);

We've modified the syntax for regionprops so that you can now do this in a one step:

  s = regionprops(bw, ...);

For example:

bw = imread('text.png');
s = regionprops(bw, 'Centroid');

These several new and modified functions, working together, nicely solve several design problems:

  • Reducing memory use
  • Increasing speed (in many cases) by eliminating duplicate computation
  • Converting a two-step workflow to a one-step workflow

We had one last concern, though. It takes code changes to benefit from these enhancements. Users who aren't aware of the new features and don't change their code will never benefit. So what could we do to help users discover the new features?

I'll comment about that next time.


Get the MATLAB code

Published with MATLAB® 7.8

23 Responses to “A new look for connected component labeling in R2009a – Part 2”

  1. Shlomi replied on :

    Great!
    I had to encode (and later decode) my labes matrix as a sparse matrix due its large size and conequent impact on run-time memory!

  2. Shlomi replied on :

    Great idea!
    I previously had to use sparse matrices in order to save the labels matrix(when passing the labels matrix on the way) because of the huge run-time memory it consumed.

  3. SlamJ replied on :

    The update for ‘regionprops’ to calculate the perimeter of each labeled region in a label matrix is very useful. But is there any property of ‘regionprops’ to get the boundary arrays (Example: I need the output of B in the source code given by
    B = regionboundariesmex(double(L),8);)

  4. Steve replied on :

    SlamJ—You could get the 'Image' property using regionprops and then call bwboundaries on each.

  5. SlamJ replied on :

    Thanks for ur quick reply. ‘Image’ property using regionprops and calling bwboundaries on each gives the boundary on each region separately . But I need boundaries of each labelled region on a whole.(Example: label matrix with 420 objects should give the boundaries of all 420 objects as a whole and not taking each object separately to give each separated boundary)
    error: Function BWBOUNDARIES expected at most 4 input arguments but was called instead with 420 input arguments.

  6. Jestine replied on :

    Can u please explain the basic idea behind the regionboundariesmex.cpp like how does it search across the image for the first dissimilar pixel and use that location of the pixel as the boundary pixel and how does it trace the remaining?

  7. Steve replied on :

    SlamJ—Sounds to me like the convex hull might be of interest to you. See convhull. I think you may be trying to use regionprops and bwboundaries for something they are not really intended for.

  8. Steve replied on :

    Jestine—I might do a post in the future on contour tracing. In the meantime, take a look at tutorial number 014, “Contour tracing,” on the imageprocessingplace.com tutorials page.

  9. Hussain replied on :

    Hi Steve

    I am trying to order the objects in my L image from regionprops column wise I am not having much success how can I do that ??

    another query are any measuremnts taken from regionprops functions properly ordered ????

    Hussain

  10. Steve replied on :

    Hussain—See my post on bwlabel search order for information on modifying object order. Be aware that there isn’t a completely consistent way to order two-dimensional shapes in a purely columnwise or rowwise fashion.

    Regarding regionprops functions, I have no idea what you mean by “properly ordered.”

  11. Hussain replied on :

    Hi Steve

    Thank you very much for your asistance in this I am
    having big issues with this struggle. I am dealing with images of 100′s of objects.

    Steve to manually check objects for correct measurements is too much :(

    Forinstance the measurements appear in a 1d matrix so is the first measurement belonging to the first object in the first column etc, this is what I mean by properly ordered ??

  12. Steve replied on :

    Hussain—The output from regionprops is ordered in exactly the same order as objects are labeled in the label matrix. As I mentioned before, there is no completely consistent columnwise ordering of all possible two-dimensional shapes, so I would quibble with your notion of “properly ordered.”

  13. Tanya replied on :

    Steve- I am getting the error “Undefined function or method ‘regionboundariesmex’ for input arguments of type ‘double’.
    The line within “regionprops” that gives the error is “B = regionboundariesmex(double(L),8);” I checked and L is type double before this statement, and its being converted to double anyway. Is there another reason that this error may occur (like it can’t find ‘regionboundariesmex’). I have not ran this code from 4 years ago from Matlab 7.0 R14, so could that have some effect?

  14. Steve replied on :

    Tanya—You do not have a valid installation of Image Processing Toolbox for the platform you are running MATLAB on.

  15. Tanya replied on :

    Steve- I am currently running R2010a with the Image Processing Toolbox that came with it installed (Academic license). Should I try re-installing everything, or contact tech support to help, or ?

  16. Steve replied on :

    Tanya—I recommend reinstalling. If that doesn’t work then I recommend contacting tech support.

  17. Ramesh replied on :

    Steve,

    Regionprops runs very very slowly when I use it as a part of a code wherein I need to do labelling (of regions) on a set of images. I use Matlab v7.8.0 R2009a

    Any tips on how to speed it up?

    Thanks

  18. Steve replied on :

    Ramesh—regionprops on a 256-by-256 test image containing 88 connected components runs in 10 ms on my computer. Do you regard this as very very slow?

  19. shilan replied on :

    using “bwconncomp” function, I want to determine centeroid of regions with a size greater than for example 100! how is it possible to combine this function with something like find? Just in a way, for instance we use

    [r, c] = find(bwlabel(BW)==2)
    

    or there is another way?

  20. Steve replied on :

    Shilan—Try this:

    s = regionprops(bw, 'area', 'centroid');
    a = [s.Area];
    s = s(a > 100);
    
  21. Nick replied on :

    Hi Steve,

    I am attempting to find the area of a small structure in a thresholded image, and I was hoping to use the connected component labeling properties of |bwconncomp| to do so. Is there a way to feed in coordinates (likely specified with |ginput|) and ask |bwconncomp| to only focus on that particular region?

    I would essentially like to do the reverse of the example provided in the |bwlabel| documentation:

    [r, c] = find(bwlabel(BW)==2)

    that is, to specify the coordinates and only label that region.

    I see that functions like |regionprops| and |bwconncomp| work on the entire image, and I wonder if there is a more sophisticated way to only focus on a certain region than to create a duplicate image cropped to the region of interest in the background.

    Thanks for your help!

  22. Steve Eddins replied on :

    Nick—bwselect might be useful.

  23. Nick replied on :

    Thanks!


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.