Steve on Image Processing and MATLAB

Concepts, algorithms & MATLAB

POLY2MASK and ROIPOLY – Part 1 19

Posted by Steve Eddins,

This is the first of several blogs about the algorithm behind poly2mask and roipoly. poly2mask takes a set of polygon vertices and produces a binary mask image. The binary mask has 1s for pixels inside the polygon and 0s for pixels outside.

Here's a quick peek at what it does.

x1 = [40 225 160 40];
y1 = [230 170 45 230];
mask = poly2mask(x1, y1, 300, 300);
hold on
hold off

Earlier versions of the Image Processing Toolbox just had roipoly. It contained both the core algorithm as well as a simple GUI for specifying the polygon vertices with mouse clicks. A few releases ago, we separated the core algorithm into its own function, poly2mask. Now roipoly handles image display and grabbing mouse clicks, and it calls poly2mask for the computation.

You can see that the computation might be nontrivial if you use a more complicated polygon, and if you zoom in a bit so you can see what's going on along the polygon edges. My second example computes a 25-by-25 mask, displays the mask using high magnification, and displays a gray grid showing the edges of the pixels.

x2 = [10 24 5 15.5 10];
y2 = [2 5 15 20.5 2];
M = 25;
N = 25;

mask = poly2mask(x2,y2,25,25);
map = [255 255 255; 218 157 30] / 255;

hold on
xx = 0.5:1:N+0.5;
yy = 0.5:1:M+0.5;
for k = 1:numel(xx)
    plot([xx(k) xx(k)], [0.5 M+0.5], 'Color', [.8 .8 .8]);

for k = 1:numel(yy)
    plot([0.5 N+0.5], [yy(k) yy(k)], 'Color', [.8 .8 .8]);

plot(x2,y2,'LineWidth',2,'Color',[189 50 21]/255);
hold off

The interesting pixels are those which are only partially inside the polygon. How do we decide the mask value for those pixels?

In the computer graphics space, I believe the most common term for this operation is polygon scan conversion. If you do a Web search on this term you'll find lots of links, many of which go to computer graphics course notes.

My own educational background is in electrical engineering, specializing in digital image and signal processing. When I left academia to become a software developer, implementing image processing algorithms, I found that many things I really needed to know were in the computer graphics literature, not in the image processing literature. (That's why the image processing team has Graphics Gems volumes 1-5 on our bookshelf.) That is most certainly the case for polygon scan conversion.

In my next blogs on this topic, I'll explain the desirable properties that a polygon scan conversion algorithm should have, the special cases that tend to trip up simple implementations, and the details of the Image Processing Toolbox implementation.

Get the MATLAB code

Published with MATLAB® 7.3


Comments are closed.

19 CommentsOldest to Newest

Sagiv replied on : 1 of 19
Hi Steve, I think there's a typo in your code. In the second example there're two declarations: x2 and y2 while the following two lines use x and y instead: mask = poly2mask(x,y,25,25); plot(x,y,'LineWidth',2,'Color',[189 50 21]/255); Thanks, -Sagiv.
Steve replied on : 2 of 19
Sagiv - Thanks, I fixed the problem. I didn't notice it when I published from MATLAB because I happened to have x and y variables in my workspace with the same values.
Andy replied on : 3 of 19
Dear Steve, I have a question smiliar to deciding the mask values along the edge. I hope it's okay to ask here. How is the motion blur (obtained by fspecial('motion',len,theta)) actually defined? I couldn't find the formula in the Uers' Guide. Thanks. Andy
Steve replied on : 4 of 19
Andy - The output values are computed as the nearest distance between the element center and the idealized line segment. I couldn't find this anywhere in the doc, so we'll make a note to add this information in a future release.
Olivier replied on : 5 of 19
Dear Steve, I am actually looking for an algorithm that does the reverse of this script; a mask2poly so to speak. So, the input is a mask and the output a number of vertices. Would you know if there is any script in Matlab that does this? Regards, Olivier.
Olivier replied on : 7 of 19
Steve, Thanks for the advice, but I think I need a vertex reduction script now. Any advice on that? Thanks again, Olivier.
Steve replied on : 8 of 19
Olivier - I don't have a polygon vertex reduction function to offer you, but I'll add it to my list of possible blog topics. Fortunately, for the output of bwboundaries or bwtraceboundary, the vertices all lie on a regular axes-oriented grid, so there are no numerical problems with determining colinearity. I think you might be able to eliminate vertices efficiently in iterations in which you alternate between considering odd-numbered and even-numbered vertices.
Sridharan Kamalakannan replied on : 9 of 19
Hi Steve, I have a polygon which i coverted to a mask by using poly2mask command. Now i have to color the mask by using patch, i.e. i want to superimpose a color mask on an image such that I can adjust the transparency of the mask. In short I would like to know if there is some command to fill specific pixels with a color such that its transparency can be adjusted.
Steve replied on : 10 of 19
Sridharan—Use your polygon vertices to create a patch object that is superimposed over the image. Then you can adjust the transparency of the patch.
MoHDa replied on : 11 of 19
I have one question about the ROIPOLY: I have an image with stripes, I use the "edge" command for finding the edges, is it possible to use the output of edge as input to ROIPOLY and just extract the information that is included in the edges lines?
Steve replied on : 12 of 19
MoHDa—It might be possible. You'll need to use one of the options that produces closed edge contours, or work out some way of closing them yourself.
Paul Alexander replied on : 13 of 19
Here is a crazy question for you Steve. I have some gridded files of latitude and longitude. I have vectors of some regions in lat and long too. I need to create a mask that represents where when my gridded lat and long fall within the polygon defined by my boundary vectors. Mask2poly comes close; but I really need to use predefined non-scalars for 'm' and 'n'. Appreciate any help you may be able to offer.
Steve replied on : 14 of 19
Paul—I'm not really sure what you mean by nonscalar m and n, but it sounds to me like the MATLAB function inpolygon might be useful to you. Just be aware that inpolygon (and poly2mask as well) are plane geometry and not spherical geometry functions. If your boundary polygon wraps a pole, they probably won't work for you.
eric replied on : 15 of 19
Dear Steve, Any progress on the "mask2poly" function? I tried reading the bwboundary and bwperim and bwtraceboundary, but left with confusion. My goal is to offer an alternative to the use of impoly, by using a simple graythresh command to create a mask. However, where I am having trouble, is that I would like to save the graythresh information in an roi structure (where I store certain aspects of imroi output, such as the accepted position vector, createmask, color,...). Because imroi has a createmask subfunction, it's easy to go from roi vertices to mask. However, I can't seem to go from mask to position vertices in an easy manner. mask2poly seemed like the closest thing I can find (since google returns nothing except answers to the opposite, i.e. "roi to mask", when searching for "convert mask to roi" not in quotations) Lemme know, Eric
Jeremy Heil replied on : 16 of 19
Why does this code (which I think is syntactically intuitive) seems to swap the xdim and ydim when it generates the output.
xpts=[ 1 3 3 1];
ypts=[4 4 8 8];

poly2mask( xpts, ypts, xdim, ydim )
poly2mask( xpts, ypts, ydim, xdim )
gets the output you expect?
Steve replied on : 17 of 19
Jeremy—The answer is in the doc, which gives the following as the syntax for poly2mask:
bw = poly2mask(x, y, m, n)
and says that m is the number of rows and n is the number of columns. So your first call to poly2mask is incorrect. Perhaps I shouldn't have designed it that way. But I did.
Leo replied on : 18 of 19
Hi Steve, How can I specify more than one polygon (not connected) on the same image using roipoly? For example, I want to create a mask for two distant apples on a tree. Any suggestions?