Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is an simple way to compute the overlap between an image and a polygon?

Tags:

matlab

I have a closed non-self-intersecting polygon. Its vertices are saved in two vectors X, and Y. Finally the values of X and Y are bound between 0 and 22.

I'd like to construct a matrix of size 22x22 and set the value of each bin equal to true if part of the polygon overlaps with that bin, otherwise false.

My initial thought was to generate a grid of points defined with [a, b] = meshgrid(1:22) and then to use inpolygon to determine which points of the grid were in the polygon.

[a b] = meshgrid(1:22);
inPoly1 = inpolygon(a,b,X,Y);

However this only returns true if if the center of the bin is contained in the polygon, ie it returns the red shape in the image below. However what need is more along the lines of the green shape (although its still an incomplete solution).

To get the green blob I performed four calls to inpolygon. For each comparison I shifted the grid of points either NE, NW, SE, or SW by 1/2. This is equivalent to testing if the corners of a bin are in the polygon.

inPoly2 = inpolygon(a-.5,b-.5,X,Y) | inpolygon(a+.5,b-.5,X,Y) | inpolygon(a-.5,b+5,X,Y) | inpolygon(a+.5,b+.5,X,Y);

While this does provide me with a partial solution it fails in the case when a vertex is contain in a bin but none of the bin corners are.

Is there a more direct way of attacking this problem, with preferably a solution that produces more readable code?

enter image description here

This plot was drawn with:

imagesc(inPoly1 + inPoly2); hold on;
line(a, b, 'w.');
line(X, Y, 'y); 
like image 237
slayton Avatar asked Aug 31 '12 20:08

slayton


2 Answers

One suggestion is to use the polybool function (not available in 2008b or earlier). It finds the intersection of two polygons and returns resulting vertices (or an empty vector if no vertices exist). To use it here, we iterate (using arrayfun) over all of the squares in your grid check to see whether the output argument to polybool is empty (e.g. no overlap).

N=22;
sqX = repmat([1:N]',1,N);
sqX = sqX(:);
sqY = repmat(1:N,N,1);
sqY = sqY(:);

intersects = arrayfun((@(xs,ys) ...
      (~isempty(polybool('intersection',X,Y,[xs-1 xs-1 xs xs],[ys-1 ys ys ys-1])))),...
      sqX,sqY);

intersects = reshape(intersects,22,22);

Here is the resulting image:

enter image description here

Code for plotting:

imagesc(.5:1:N-.5,.5:1:N-.5,intersects');
hold on;
plot(X,Y,'w');
for x = 1:N
    plot([0 N],[x x],'-k');
    plot([x x],[0 N],'-k');
end
hold off;
like image 106
klurie Avatar answered Nov 06 '22 14:11

klurie


How about this pseudocode algorithm:

For each pair of points p1=p(i), p2=p(i+1), i = 1..n-1
    Find the line passing through p1 and p2
    Find every tile this line intersects // See note
    Add intersecting tiles to the list of contained tiles

Find the red area using the centers of each tile, and add these to the list of contained tiles

Note: This line will take a tiny bit of effort to implement, but I think there is a fairly straightforward, well-known algorithm for it.

Also, if I was using .NET, I would simply define a rectangle corresponding to each grid tile, and then see which ones intersect the polygon. I don't know if checking intersection is easy in Matlab, however.

like image 24
Superbest Avatar answered Nov 06 '22 15:11

Superbest