Steve on Image Processing

February 24th, 2007

ROIPOLY – rectangular regions and logical indexing

Several readers commented on my recent roipoly and poly2mask posts, and I wanted to follow up on a couple of issues they raised. The first issue is a common point of confusion about the selection of rectangular regions, and the second is how to access and modify pixels contained within a region of interest.

Contents

Rectangular regions

Users sometimes wonder why poly2mask and roipoly don't return some of the boundary pixels of a rectangular region as part of the mask. Here's an example.

x = [2 4 4 2 2];
y = [2 2 4 4 2];

mask = poly2mask(x, y, 5, 5)
mask =

     0     0     0     0     0
     0     0     0     0     0
     0     0     1     1     0
     0     0     1     1     0
     0     0     0     0     0

Some users expect rows 2 through 4 and columns 2 through 4 to be included in the mask. One reader commented that he uses a different function instead of roipoly because of this behavior.

As I have illustrated in my previous posts, roipoly and poly2mask treat a pixel not as a point, but as a unit square area. The upper-left corner of the (2,2) pixel is (1.5,1.5), and the lower-right corner is (2.5,2.5). So the polygon defined by the x-y vertices in the example above covers only one-fourth of the (2,2) pixel.

I suggest that you get used to defining rectangles that cover complete pixel areas. Such rectangles go along pixel edges, not through pixel centers. Here's a second example to demonstrate:

xp = [1.5 4.5 4.5 1.5 1.5];
yp = [1.5 1.5 4.5 4.5 1.5];

maskp = poly2mask(xp, yp, 5, 5)
maskp =

     0     0     0     0     0
     0     1     1     1     0
     0     1     1     1     0
     0     1     1     1     0
     0     0     0     0     0

Now the "mystery" is completely removed about which border rows and columns are in the mask. There's no need to use some other function.

Logical indexing

Another reader asked how to get and modify pixels inside a region of interest. One nice way to do that in MATLAB is to use logical indexing. The expression A(B), if B is logical and the same size as A, selects all the elements in A corresponding to the true elements of B.

I'll demonstrate using an example mask from the roipoly documentation.

clear
I = imread('eight.tif');
imshow(I)
c = [222 272 300 270 221 194];
r = [21 21 75 121 121 75];
mask = roipoly(I,c,r);
imshow(mask)

If you use whos or look in the workspace browser, you can see that mask is a logical matrix.

whos
  Name        Size             Bytes  Class      Attributes

  I         242x308            74536  uint8                
  c           1x6                 48  double               
  mask      242x308            74536  logical              
  r           1x6                 48  double               

The expression I(mask) is a column vector containing all the elements of I corresponding to the true values of mask. Here, for example, is how you would compute the mean of the pixels inside the region of interest:

mean(I(mask))
ans =

  156.0468

You can use logical indexing on the left-hand side of an assignment as well.

I2 = I;
I2(mask) = 255 - I(mask);  % Or imcomplement(I(mask)).
imshow(I2)

Here's a documentation link for logical indexing. Or you might be interested in this MATLAB Digest article that Loren and I wrote about MATLAB indexing.


Get the MATLAB code

Published with MATLAB® 7.3

26 Responses to “ROIPOLY – rectangular regions and logical indexing”

  1. Brian W. replied on :

    Thank you. :)

  2. keerthi replied on :

    thank you som uch. it is very informative and useful.

  3. andy replied on :

    Thank you! But how to decompose the mask to make it work with the decomposed image??

  4. Steve replied on :

    Andy—What’s a decomposed image?

  5. andy replied on :

    I want to create a mask which contains a ROI.Just like things in JPEG2000,how to create a mask with a given region of interest.the mask should contain all the coefficents in every subband in the wavelet domain.
    thank u!

  6. Steve replied on :

    Andy—A mask is just a binary image. The set of nonzero pixels in the mask defines the region of interest. You can create the mask however you like.

  7. SYED ABDAHEER replied on :

    Respected Sir
    I have gone through above said matlab based commend line. I thiunk its based on only two dimentional image. But how can I made the things for medical (3-D) images.Please give your suggestion.
    With warm regards from
    SYED ABDAHEER

  8. Steve replied on :

    Syed—For a logical indexing expression A(D), D has to match the size of A. If you have a 2-D logical mask and are working with 3-D data, then you either have to replicate the mask along the third dimension, or you have to work with the data one plane at a time.

  9. subarna replied on :

    Nice explanation, thank you.
    if the ROI is a rectangle (axis not verticle), and if we wish to see it in a verticle rectanglular box by using imshow, how to proceed?
    how to assign this extracted rectangular ROI to another vertical rectangle? since the indices of mask follow lower to higher column values, not according to the directions of the polygon to be extracted.

  10. Steve replied on :

    Subama—I don’t understand your question.

  11. ilyas replied on :

    Hi, Steve,

    I am very thankful for your nice explanation. I would like to ask you a question. when we use roipoly and then figure pops up. After that we have option to select region of interest by selecting vertices on figure by mouse. The question is what I should to to save the part of image which I select by mouse.

    Thank you so much for your time and consideration.

  12. ilyas replied on :

    I am sorry. I mean how I can exract and save the part of image which I select by mouse.

  13. Steve replied on :

    Ilyas—The post you commented on explains how to use the mask returned by roipoly to extract the image pixel values that are inside the polygon. If you have a truecolor (M-by-N-by-3) image, though, you’ll need to use separate logical indexing expressions for each color component, like this:

    R = im(:,:,1);
    G = im(:,:,2);
    B = im(:,:,3);
    
    red_pixels = R(mask);
    green_pixels = G(mask);
    blue_pixels = B(mask);
    
  14. jon replied on :

    Is there a way to use roipoly to allow the user to draw a polygon on a figure that contains a plot but not an image? My goal is to allow the user to draw a polygon on a scatter plot and to then return the coordinates of the plotted points that lie within the polygon. I have been able to do this using impoly.m, but most of my current work uses matlab 7.4.0 (r2007a), and the image toolbox associated with this version of matlab does not seem to include impoly. So I would like to implement this without impoly but have not succeeded. Any suggestion would be appreciated. Thanks.

  15. Steve replied on :

    Jon—Make your own copy of roipoly and edit it so that it doesn’t call poly2mask at the end.

  16. jon replied on :

    thanks steve. working now.

  17. willow chang replied on :

    ROIPOLY — How to display the image in color?

    Steve,

    When I am using roipoly(img) to interactively select ROI, it often occurs to me that if the displayed image is colorful instead of grayscale, it will make my life much easier, as colorful pictures show more visual depths than black-and-white ones. Do you have any way of doing this, for instance, by using a colormap?

    Thank you.

    Willow

  18. Steve replied on :

    Willow—You have a few options:

    • Make img a truecolor image.
    • Display img, then set the figure colormap, then call roipoly with no input arguments.
    • Write your own implementation using tools like impoly and poly2mask.
  19. Justin replied on :

    Steve,
    I am trying to use bwboundaries+regionprops to create a mask of user-specified objects. I have a step where the user clicks on his objects of interest (these will remain as part of the final mask) and another step where the user can click-draw polygons on the figure to add/remove parts of the image.

    The problem is, the points returned upon userclicks and “boundary” (B{k} from [B,L]=bwboundaries(I)) are integers and aren’t specified in the way that you mentioned in your discussion about rectangular regions. So when I try to visualize the mask, the image/mask is missing some of the boundary regions.

    I could try to fiddle with the coordinates (look for it’s corners/edges and increase/decrease their values by 0.5, but I am wondering if Matlab has some built-in functionality that would allow me to get around this issue in a quicker fashion.

    Thanks for your help,
    -Justin

  20. Justin replied on :

    I can get around part of the issue by using the ‘Image’ option from regionprops, but i am still stuck when it comes to the user-selecting of points part.

    I want to user to be able to click and connect the edges of a polygon which will then be used to increase/decrease the size of the initial mask. (cut out or restore based on the drawn shape & location)

  21. Justin replied on :

    As a separate question (and i’m probably missing something really simple here), but in your first example, how come you don’t see a result like”:

    mask =

    0 0 0 0 0
    0 0 0 0 0
    0 0 1 0 0
    0 0 0 0 0
    0 0 0 0 0

    Shouldn’t the way the coordinates are defined also mean that only 1/4th of pixel (4,4) is covered too?

    -Justin

  22. Steve replied on :

    Justin—I don’t exactly understand how you are using bwboundaries in your application, but I’ll try to give some partial but hopefully useful advice. First, you might find bwselect useful for the part where users click on objects to select them. Regarding your comment #21: If the rules were defined the way you suggest, you could tile the image plan completely with rectangular polygons that were each 2 units wide and 2 units high, and only 1/4 of the image pixels would be considered to belong inside ANY of the polygons, despite the fact that the polygons cover the plane. If you want to understand the details of why the ROIPOLY rules are defined the way they are, take a look at my ROIPOLY and POLY2MASK series (part 1, part 2, part 3).

    So I suggest you take a look at bwselect and the ROIPOLY series, and then come back here and ask more questions if needed.

  23. alex replied on :

    I have been trying to define a polygon using roipoly() because I have an irregular shaped object (a foot) that i want to make a patch for in my robot model. I have an image of the foot stored as jpg and I need this as a patch in matlab. I have discovered now though the roipoly() returns a mask, not what I want. What i need is the verticies stored as x and y data that i can send to the patch command.
    IS it possible to get these values from roipoly()? Or is there some other function out there that will capture my clicks as vertices?

    cheers
    Alex

  24. Steve replied on :

    Alex—Check out the last couple of syntaxes in the roipoly doc. These syntaxes return the polygon vertices. Or you could try using impoly.

  25. sundar naganathan replied on :

    Hi Steve,
    This was very useful.
    Say I want to draw a square in an image and analyze all the pixels within the square. As you said, defining a mask and then using indexing I can get all the pixels within the square. Since the mask is binary, when I do image overlay of the mask on the original image, it appears as a white square.
    Apart from the analysis of the pixels within the square over time, I would also like to display just the boundary of the square (and not the white mask) in the original image (or movie). I can then show how things are changing within the square (as the movie is running).

  26. sundar naganathan replied on :

    Hi Steve,
    I have one more question regarding roipoly.
    Is it possible to use roipoly to define an ellipse and then get the integrated intensity of all the pixels within the ellipse ?
    I tried using imellipse, but I did not know how to proceed with the function handle that I get using imellipse.

    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.