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

前端 未结 6 1242
清酒与你
清酒与你 2020-12-16 05:03

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 t

6条回答
  •  暖寄归人
    2020-12-16 05:21

    Well, I guess I am late, though strictly speaking the bounty time was till tomorrow ;). But here goes my attempt. First, a function that marks cells that contain/touch a point. Given a structured grid with spacing lx, ly, and a set of points with coordinates (Xp, Yp), set containing cells:

    function cells = mark_cells(lx, ly, Xp, Yp, cells)
    
    % Find cell numbers to which points belong.
    % Search by subtracting point coordinates from
    % grid coordinates and observing the sign of the result.
    % Points lying on edges/grid points are assumed
    % to belong to all surrounding cells.
    
    sx=sign(bsxfun(@minus, lx, Xp'));
    sy=sign(bsxfun(@minus, ly, Yp'));
    cx=diff(sx, 1, 2);
    cy=diff(sy, 1, 2);
    
    % for every point, mark the surrounding cells
    for i=1:size(cy, 1)
        cells(find(cx(i,:)), find(cy(i,:)))=1;
    end
    end
    

    Now, the rest of the code. For every segment in the polygon (you have to walk through the segments one by one), intersect the segment with the grid lines. Intersection is done carefully, for horizontal and vertical lines separately, using the given grid point coordinates to avoid numerical inaccuracies. For the found intersection points I call mark_cells to mark the surrounding cells to 1:

    % example grid
    nx=21;
    ny=51;
    lx = linspace(0, 1, nx);
    ly = linspace(0, 1, ny);
    dx=1/(nx-1);
    dy=1/(ny-1);
    cells = zeros(nx-1, ny-1);
    
    % for every line in the polygon...
    % Xp and Yp contain start-end points of a single segment
    Xp = [0.15 0.61];
    Yp = [0.1 0.78];
    
    % line equation
    slope = diff(Yp)/diff(Xp);
    inter = Yp(1) - (slope*Xp(1));
    
    if isinf(slope)
        % SPECIAL CASE: vertical polygon segments
        % intersect horizontal grid lines
        ymax = 1+floor(max(Yp)/dy);
        ymin = 1+ceil(min(Yp)/dy);
        x=repmat(Xp(1), 1, ymax-ymin+1);
        y=ly(ymin:ymax);
        cells = mark_cells(lx, ly, x, y, cells);
    else
        % SPECIAL CASE: not horizontal polygon segments
        if slope ~= 0
            % intersect horizontal grid lines
            ymax = 1+floor(max(Yp)/dy);
            ymin = 1+ceil(min(Yp)/dy);
            xmax = (ly(ymax)-inter)/slope;
            xmin = (ly(ymin)-inter)/slope;
            % interpolate in x...
            x=linspace(xmin, xmax, ymax-ymin+1);
            % use exact grid point y-coordinates!
            y=ly(ymin:ymax); 
            cells = mark_cells(lx, ly, x, y, cells);
        end
    
        % intersect vertical grid lines
        xmax = 1+floor(max(Xp)/dx);
        xmin = 1+ceil(min(Xp)/dx);
        % interpolate in y...
        ymax = inter+slope*lx(xmax);
        ymin = inter+slope*lx(xmin);
        % use exact grid point x-coordinates!
        x=lx(xmin:xmax); 
        y=linspace(ymin, ymax, xmax-xmin+1);
        cells = mark_cells(lx, ly, x, y, cells);
    end
    

    Output for the example mesh/segment: output

    Walking through all polygon segments gives you the polygon 'halo'. Finally, the interior of the polygon is obtained using standard inpolygon function. Let me know if you need more details about the code.

提交回复
热议问题