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