Steve on Image Processing

Using ismember with the output of regionprops 60

Posted by Steve Eddins,

I recently heard a MathWorks application engineer (hi, Brett!) say that a short little paragraph in the regionprops documentation was very "powerful." Here it is:

The function ismember is useful in conjunction with regionprops for selecting regions based on certain criteria. For example, these commands create a binary image containing only the regions whose area is greater than 80.

   idx = find([stats.Area] > 80);
   BW2 = ismember(L,idx);

When I heard Brett's comment, I immediately pulled out my high-tech note-taking device (index card) from my back pocket and wrote: "regionprops - ismember - blog topic."

The basic idea is this: If I have a binary image containing objects, how can I make a new binary image containing a subset of the objects satisfying certain criteria? The answer is in three parts:

1. Use bwlabel and regionprops to compute measurements of the objects.

2. Compute a vector of labels for the objects satisfying the criteria. Sometimes a special structure syntax called the "comma-separated list" is very useful for this step; I'll show that syntax below.

3. Use ismember to compute the desired binary image.

I've posted several examples using bwlabel and regionprops, so I won't go into much detail about them. You label objects in a binary image using bwlabel, and then you compute geometric measurements of the labeled objects using regionprops.

Let's use the blobs.png image for our example.

bw = imread('blobs.png');
imshow(bw)
L = bwlabel(bw);
s = regionprops(L, 'Area', 'BoundingBox');
s(1)
ans = 

           Area: 35
    BoundingBox: [0.5000 0.5000 14 14]

regionprops returns a structure array containing the desired measurements for each object.

The comma-separated list syntax for structures offers an easy way to convert a particular field from a structure array into a vector, assuming that the field value is always a scalar. Here's how it works. When s is a structure array with field foo, and you write the following expression:

   s.foo

MATLAB translates that into this "comma-separated list":

   s(1).foo, s(2).foo, ..., s(end).foo

Therefore, if s(k).foo is a scalar, you can create a vector of all the foo values by enclosing s.foo in brackets, like this:

   foo_fector = [s.foo];

Here's how it works for the 'Area' measurements we computed above for the blobs.png image.

area_values = [s.Area]
area_values =

  Columns 1 through 7

          35         393          19         139          36          58         736

  Columns 8 through 14

          53           2           2           1           2           2           2

  Columns 15 through 21

           1         196        3940        4326         504          40         422

  Columns 22 through 28

         966         655         175          40          39        1108          35

Suppose we want a list of all the objects whos area is between 100 and 1000. We can do that using find and relational operators, like this:

idx = find((100 <= area_values) & (area_values <= 1000))
idx =

     2     4     7    16    19    21    22    23    24

And that brings us to ismember. We can construct a binary image containing all the objects whos area is between 100 and 1000 by passing L and idx to ismember.

bw2 = ismember(L, idx);
imshow(bw2)

Let's try that with another measurement, solidity. Solidity is defined as the area of the region divided by the area of the convex hull of the region.

s = regionprops(L, {'Solidity'});
solidity = [s.Solidity]
solidity =

  Columns 1 through 9

    0.2397    0.9680    0.6786    0.0700    0.8000    0.1321    0.4461    0.7910    1.0000

  Columns 10 through 18

    1.0000    1.0000    1.0000    1.0000    1.0000    1.0000    1.0000    0.0972    0.1681

  Columns 19 through 27

    1.0000    0.2235    0.0386    0.1505    0.9791    0.9669    0.2260    0.2191    0.5604

  Column 28

    0.2397

Here are all the objects with a solidity of 0.9 or higher:

imshow(ismember(L, find(solidity >= 0.9)))

And here are all the objects with a solidity of 0.25 or lower:

imshow(ismember(L, find(solidity <= 0.25)))


Get the MATLAB code

Published with MATLAB® 7.7

60 CommentsOldest to Newest

Hi Steve.
I am regularly reading your posts. I got impressed by your great ideas.All r very useful to my work. Can u pls tell me the procedure by which regionprops finds perimeter and Max Lenght of an Object? Thanks in Advance.

Nice feature Steve. I guess I should have read the documentation more carefully. What I had been doing is to loop through all blobs, seeing if each blob met the criteria for exclusion, and then using its PixelIdxList to erase it’s pixels from the original binary image. Looks like that can be replaced with just a line or two using your method. Of course we then need to run bwlabel() and regionprops() again to get a new structure of blob measurements with just the acceptable blobs in it.

Mark—If you just need the measurements for the objects, then relabeling may not be necessary. I guess it depends on the nature of the follow-up processing.

Kavitha—See the ComputePerimeter subfunction of regionprops. There is no “Max Length” measurement for regionprops.

hi steve…nice work…i was wondering….what if we have a hole in one of the solidity r the labeled object and we need to find the centroid of those holes?…is it possible?

Nanditha—Yes, it’s possible, but it will require a bit of coding. You could use the 'FilledImage' and 'Image' measurements of regionprops to identify the pixels that belong to holes, and then use findmean to compute the centroids.

Hi steve i’m using the regionprops to find the area with binary value of 1. How to convert this area in cm^2

Kushairy—You’ll need to know the spatial dimensions of each pixel. If you do not know that, you’ll need to do some sort of camera calibration, possibly aided by the use of fiducial marks in your scenes.

Hi Steve,
I’ve got a b&w image(pixel values are only 1s and 0s) of bubbles in water, where bubbles are black and water is white.
Do you have any idea how to position the bubbles in water? Such as naming (x,y) positions of each centres of the bubbles or any other way.
Many thanks in advance.

@Wei – I think you are looking for the centriod of the bubbles. Centriod calculations are part of the output from REGIONPROPS. The example in the doc is complete:

BW = imread('text.png');
s = regionprops(BW, 'centroid');
centroids = cat(1, s.Centroid);
imshow(BW)
hold on
plot(centroids(:,1), centroids(:,2), 'b*')
hold off

Hi Steve,

I have lots of fluorescent water droplets on a plate, in an RGB file and i want to know the mean intensity of each droplet. I’m thinking regionprops and a ‘meanintensity’ property, but i also want to see on the figure output the regions I’m selecting.

your advice would be awesome!
Thanks in advance

Charles—The reference page for regionprops includes an example that shows how to “mark” the center of an object with an asterisk (or some other marker). Would that help?

i was wonder when i recieve the stats.Image , it is smaller from the original image how i can set it in the original image size?

Mix—Use the BoundingBox property to determine where the object is located in the original image.

I’m wondering if there is an easy way to substitute a certain regionprops characteristic with the numbered labels as produced by bwlabel.

This would be a standard reclassification in GIS terms, where you replace the patch number by the characteristics associated with the patch. However I don’t seem to find a numbered value in the regionprops output that binds it to the bwlabel output. Although it should be possible as you produce a selected image using ismember().

Any solutions here?

Koen—The k-th element of the output of regionprops corresponds to the object labeled the value k in the output of bwlabel. In other words:

s = regionprops(L);
s(10)   % measurements for the object L==10

Does that help?

Steve,
I have another question about ‘regionprops’, and hope that you may shed some light on it. Thanks in advance.

I have been working on calculating the orientation of an image shape based on moments. Here are my questions:

1. From wikipedia and other sources, the orientation of a shape is computed by:

orientation = 0.5*atan(2*u11/(u20-u02))*180/pi,

where u11, u20, and u02 are second order central moments.

2. But the code in the matlab function ‘regionprops’ is (uxx, uyy, and uxy are actually u20, u02, and u11, respectively):
————————

if (uyy > uxx)
  num = uyy - uxx + sqrt((uyy - uxx)^2 + 4*uxy^2);
  den = 2*uxy;
else
  num = 2*uxy;
  den = uxx - uyy + sqrt((uxx - uyy)^2 + 4*uxy^2);
end
if (num == 0) && (den == 0)
  stats(k).Orientation = 0;
else
  stats(k).Orientation = (180/pi) * atan(num/den);
end

———————–
Why is the formula different from what is described in wikipedia (the additional ‘sqrt’ term)?

3. Does the above calculations about image orientations apply both to binary and grayscale images? For grayscale images, the shape would be the whole image.

4. Also, regionprops calculates the second momemts as follows. Would you please explain what the term ‘1/12′ means. Is it still necessary if we are dealing with grayscale images?
—————————

% Calculate normalized second central moments for the region. 1/12 is
% the normalized second central moment of a pixel with unit length.
uxx = sum(x.^2)/N + 1/12;
uyy = sum(y.^2)/N + 1/12;
uxy = sum(x.*y)/N;

—————————

Thanks again.

Yuan-Liang—1. I can’t explain formulas that appear in unspecified wikipedia pages or other sources, and “orientation of a shape” is a phrase that needs a more specific definition. Our code is computing the orientation of the ellipse that has the same normalized 2nd-order moments as the shape in question, and the equations for that come from Haralick and Shapiro, Computer and Robot Vision vol I, Addison-Wesley 1992, Appendix A. 2. I feel no particular need to rederive the Haralick equations at the moment, especially since I just did a spot-check of regionprops using line segments at various angles, and regionprops is returning accurate answers. 3. These formulas are for flat shapes only, so they would not apply directly to grayscale images. 4. Does the code comment not supply sufficient information about where the 1/12 term comes from?

hello steve. I have been doing image procesing for retinal images for past 2 months. I have segmented some required portions from the image.These are gray scale images. now how can i use ‘regionprops’ for computing the mean intensity of the segmented region in the gray scale image. Pls help.

Prashanth—If you have a relatively recent version of the Image Processing Toolbox, you can pass in your gray scale image as the second argument to regionprops and compute the 'MeanIntensity' measurement.

Ayrton—”foo” is just a fieldname I made up in order to illustrate the comma-separated list syntax.

Hi Steve,

Your posts are very helpful for Matlab users.
Do you know how can I get the binary image by using
“regionprops ConvexImage”?
Thanks.

Dansheng

Dansheng—The following code will give you the binary image corresponding to a single object.

L = bwlabel(bw);
s = regionprops(L, 'ConvexImage');
bw = s(k).ConvexImage;  % convex image for the k-th object

To get the union of all convex images, you’ll have to put the pieces together in your own code, and you’ll need to get the BoundingBox for each object in order to do that.

s = regionprops(L, 'ConvexImage', 'BoundingBox');

I may do a blog with the details soon.

Hi Steve,
Your posts are really helpful. I want to ask that using regionprops, is there any way to smooth or fill the jagged boundaries of the objects in an image so that the objects have clean boundaries. I have some objects in an image and i want to find the corners of these objects. But due to jagged boundaries, i am not able to find the true corners as i also get corners along the sides of the object due to jagged boundaries. Kindly help.Thanks.
Martin.

So can you give an idea what else can i do. I am trying to use the hough transform function in matlab for detecting lines which will be basically boundaries of object. Then to extend these lines and intersection of these lines will give me the true corners. But in matlab for hough functions, i need to adjust the parameters a lot and in the end i also don’t get all the lines.So it gives some error.
Martin.

Martin—There are papers in the literature about approximating curves with polygons. Also, it sounds like you might be looking for rectangles, so I would look in the literature specifically for that.

i just want to ask,after i do skin segmentation the eyes region will become holes,so how can link back those holes belong to with bounding box??i want to do this to confirm that bounding box got face inside if it got holes…pls reply me

Thanks for the interesting post!

How can I plot all of the bounding boxes on top of my image?

Is there any way of extracting the values from the BoundingBox, and grouping them into 4’s – i.e. to represent the top left, top right, bottom left and bottom right coordinates?

Thanks again for your post!

hi steve,
i supposed to find area of my binary image.
but then, when i try to compute the area, the same problem keep on occur like below..
how can i solve the problem?

hope u can help me..
thanks.

wani

 s=regionprops(L,'Area','BoundingBox');
??? Attempt to execute SCRIPT regionprops as a function.

Hi Steve. Is there a way to do something similar but keep the regionprops information intact by site? ie- once I filter by solidity I lose the centroid information. I’d like to keep my structure but not those entries that don’t meet my requirements. Or is the best way to just run regionprops again? Thanks.

Jeff—Sure. You can filter based on a certain measurement and then use the results to select all the corresponding measurements using code that might look like this:

s = regionprops(BW, 'Solidity', ...);
keep_these = [s.Solidity] > 0.8;
s = s(keep_these);

I’m interested in the question issued at comments 24 and 25. Is that followup post available somewhere? Where do I start with that code?

Dear steve after finding connected components for binary image how to put bounding box for each connected component . I am new to matlab pls help me

[L,n] = bwlabel(bw);
s = regionprops(L, ‘Area’, ‘BoundingBox’);

Dear Steve,

I put the bounding box for the binary image using the below code . How to find the distance between the bounding boxes and how to save the image in variable after applying bounding box

stats = regionprops(bw,’BoundingBox’);

hold on
for object = 1 : length(stats)
bb = stats(object).BoundingBox;
rectangle(‘Position’,bb,’FaceColor’,’w’);

end
k = figure
hold off

Sanjay—You’ll need to code up the bounding-box distance calculation yourself. The values you need (corner position and size) are in the BoundingBox field of the struct array returned by regionprops. For saving the resulting image, take a look at getframe or print.

Hi Steve,
I am trying to find out how exactly regionprops measures the perimeter of an object. The help file says it calculates the distance between each adjoining pair of pixels around the boarders, yet the fact that it does not give discrete numbers seems to suggest something more complicated than simple pixel-counting. Looking at the m-file does not bring me much further than realising that the code makes use of a MEX-file called regionboundariesmex. Could you give me some indication what that does? Is it anything along the lines of digital straight segment approximation, chain codes or minimum-perimeter polygon approximation?

Christine—The doc for regionprops is cryptic but accurate on this point: “regionprops computes the perimeter by calculating the distance between each adjoining pair of pixels around the border of the region.” The distance between diagonally connected pixels is the Euclidean distance between the pixel centers: sqrt(2).

Hi Steve,

I have two binary images of the same size. I want to select regions from image one, where that region has to partially overlap with a region from image two.

Yours Richard

mh… The help doc gives an example for the boarder around a sample object (assuming the white region depicts the sample object and the green one the boarder (?)). This boarder contains 44 pixels, with 2 diagonal connections. I would have thought that the perimeter according to the above definition is 44.83 then, however regionprops calculates 35.66. Clearly, I am getting something wrong there.

Christine—I get 44.8284:

>> bw = zeros(1,13);
>> bw = [bw; zeros(3,1), ones(3,11), zeros(3,1)];
>> bw = [bw; zeros(11,5), ones(11,3), zeros(11,5)];
>> bw = [bw; zeros(1,13)];
>> s = regionprops(bw,'perimeter')

s = 

    Perimeter: 44.8284

Hi, Steve,

I find 5 objects in a binary image. I can get Centroid values of each object. How do I use the property “MeanIntensity” of regionprops() to calculate each object’s mean intensity?

[L,N]=bwlabel(img_bright_bw);

stats2=regionprops(L,'Area', 'Centroid', 'BoundingBox');
stats2=regionprops(L,'all');
idx = find([stats2.Area] > 50);
ob1=stats2(1).Centroid;

Many thanks!
Maria

Hey I want to calculate the aspect ratios of bounding boxes of different blobs in my binary image. and then retain only those with aspect ratios less than 0.3. How can i do this.

How can i convert the structure array of bounding box to a vector..

Maria—I assume you mean the mean intensity of pixel values in some other grayscale image, since the mean intensity of binary image objects is 1. If the grayscale image is called A, then this would do the trick:

stats = regionprops(img_bright_bw, A, 'MeanIntensity');

Hi Steve – I have two images – one contains class labels (one of 1 or 2) and one containing image segment (region) unique IDs. I am trying to use regionprops (or something like regionprops) to figure out most frequently occurring label from the label image per region and generate a new image where each unique region contains this most frequently occurring label. Is there a way to do this? Thank you very much.

Sum—There isn’t an existing Image Processing Toolbox function that will do it for you automatically. To implement it, I would probably dilate the region, use a logical operation to identify the dilated pixels that are not part of the original region, and then use the locations of those pixels to index into a label matrix to find the labels of adjacent regions. I’ll put this on my list of potential blog topics.

Hi Steve,
I have an image with big blue blobs, an image with small red blobs and an image with small green blobs. I want to identify blue blobs that have: a) no small blobs, b)green small blobs, c)red small blobs and d) both green and red small blobs; when all 3 images are superimposed. I’ve tried using regionprops centroids but something goes wrong with the loops. Any suggestion? Thank you!

Great work. Really very much important ; little little things are explained very very much well…!! thank you so much..!!

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