How can I detect the maximum-sized rectangle that I can draw onto the mask?

前端 未结 3 1731
温柔的废话
温柔的废话 2020-12-06 03:17

I\'m making an image processing project and I have stuck in one the project\'s steps. Here is the situation;

This is my mask:

3条回答
  •  清歌不尽
    2020-12-06 03:43

    Here is a correct answer. You must use dynamic programming! Other methods of direct calculation (like cutting 1 pixel from each edge) might produce sub-optimal results. My method guarantees that it selects the largest possible rectangle that fits in the mask. I assume that the mask has 1 big convex white blob of any shape with black background around it.

    I wrote 2 methods. findRect() which finds the best possible square (starting on x,y with length l). The second method LargestInscribedImage() is an example of how to find any rectangle (of any aspect ratio). The trick is to resize the mask image, find a square and resize it back. In my example the method finds the larges rectangle that can be fit in the mask having the same aspect ration as the mask image. For example if the mask image is of size 100x200 pixels than the algorithm will find the largest rectangle having aspect ratio 1:2.

    % ----------------------------------------------------------
    function LargestInscribedImage()
    % ----------------------------------------------------------
        close all
        im = double(imread('aa.bmp')); % Balck and white image of your mask
        im = im(:,:,1);  % If it is colored RGB take only one of the channels
        b = imresize(im,[size(im,1) size(im,1)]); Make the mask square by resizing it by its aspect ratio.
        SC = 1;  % Put 2..4 to scale down the image an speed up the algorithm
    
        [x1,y1,l1] = findRect(b,SC);          % Lunch the dyn prog algorithm
        [x2,y2,l2] = findRect(rot90(b),SC);   % rotate the image by 90deg and solve
        % Rotate back: x2,y2 according to rot90
        tmp = x2;
        x2 = size(im,1)/SC-y2-l2;
        y2 = tmp;
    
    % Select the best solution of the above (for the original image and for the rotated by 90degrees
            if (l1>=l2)
               corn = sqCorn(x1,y1,l1);
            else
               corn = sqCorn(x2,y2,l2);
            end
    
            b = imresize(b,1/SC);
        figure;imshow(b>0); hold on;
        plot(corn(1,:),corn(2,:),'O')
    
        corn = corn*SC;
        corn(1,:) = corn(1,:)*size(im,2)/size(im,1);
        figure;imshow(im); hold on;
        plot(corn(1,:),corn(2,:),'O')
    end
    
    function corn = sqCorn(x,y,l)
         corn = [x,y;x,y+l;x+l,y;x+l,y+l]';
    end
    % ----------------------------------------------------------
    function [x,y,l] = findRect(b,SC)
    b = imresize(b,1/SC);
    res = zeros(size(b,1),size(b,2),3);
    % initialize first col
    for i = 1:1:size(b,1)
        if (b(i,1) > 0)
           res(i,1,:) = [i,1,0];
        end
    end
    % initialize first row
    for i = 1:1:size(b,2)
        if (b(1,i) > 0)
           res(1,i,:) = [1,i,0];
        end
    end
    
    % DynProg
    for i = 2:1:size(b,1)
    for j = 2:1:size(b,2)
        isWhite = b(i,j) > 0;
        if (~isWhite)
           res(i,j,:)=res(i-1,j-1,:); % copy
        else
            if (b(i-1,j-1)>0)  % continuous line
               lineBeg    = [res(i-1,j-1,1),res(i-1,j-1,2)]; 
               lineLenght = res(i-1,j-1,3); 
               if ((b(lineBeg(1),j)>0)&&(b(i,lineBeg(2))>0))  % if second diag is good
                  res(i,j,:) = [lineBeg,lineLenght+1];
               else
                  res(i,j,:)=res(i-1,j-1,:); % copy since line has ended
               end
            else
               res(i,j,:) = [i,j,0];         % Line start
            end
        end
    
    end
    end
    
    % check last col
    [maxValCol,WhereCol] = max(res(:,end,3));
    % check last row
    [maxValRow,WhereRow] = max(res(end,:,3));
    
    % Find max
    x= 0; y = 0; l = 0;
    if (maxValCol>maxValRow)
       y = res(WhereCol,end,1);
       x = res(WhereCol,end,2);
       l = maxValCol;
    else
       y = res(end,WhereRow,1);
       x = res(end,WhereRow,2);
       l = maxValRow;
    end
    
        corn = [x,y;x,y+l;x+l,y;x+l,y+l]';
    %    figure;imshow(b>0); hold on;
     %   plot(corn(1,:),corn(2,:),'O')
    return;
    end
    

提交回复
热议问题