How to get bounding boxes around rectangular rooms which are rotated by some angle ?

I have a floorplan which is rotated with some angle. I do not know the angle. Can I get the bounding box around the rooms in floor plan . If it is not rotated, using regionprops(), I am able to get the bounding boxes. But if it is rotated, since the bounding box do not rotates, I am unable to get the bounding box around the rooms. I want to get the coordinates of those rooms. Is there any other way to get the coordinates of the rooms with/without using bounding box method?Or I sit possible to get the coordinates of the 4 line segments of each room which bound the rooms?

 Réponse acceptée

You could also use this FEX file to get the vertices of each room,
though you would have to generate an image of each room separately. You could also use it to find the corners of the convex hull of the floorplan.

10 commentaires

Thank you for your information. Could you please tell me is there any way to distingush the points to the room they belong to? I want to have like a set of corner points of individual rooms. Is there any way to achieve that?
I can not have the individual images for rooms. So that's why I am asking.
You can use regionprops(...,'PixelIdxList') to derive images of the individual rooms. Use the PixelIdxList for each room to fill its own binary map.
Could you please tell me how the output will be when i use pgonCorners(I,k)? Is the first coordinate the top-left of the image? I want to know what corner the coordinates represent.
As you'll see in the documentation, the coordinates will be in counter-clockwise order. They will be in (row,column) matrix coordinates, not (x,y) intrinsic coordinates, the same conventions as bwboundaries.
function corners = pgonCorners(BW,k,N)
%Method of detecting the corners in a binary image of a convex polygon with
%a known number of vertices. Uses a linear programming approach.
%
% corners = pgonCorners(BW,k)
% corners = pgonCorners(BW,k,N)
%
%IN:
%
% BW: Input binary image
% k: Number of vertices to search for.
% N: Number of angular samples partitioning the unit circle (default=360).
% Affects the resolution of the search.
%
%OUT:
%
% corners: Detected corners in counter-clockwise order as a k x 2 matrix.
Nothing else is guaranteed about the ordering I don't think, but you seem to believe the rotation angle will always be less than 45 degrees. The top left should in that case be detectable by computing the ray from the centroid of the room to each of the corners. The ray with the smallest angle to the [-1,-1] direction would correspond to top left.
pgonCorners() gives me 4 set of coordinates whereas the floor plan has 3 rooms in it.When the floor plan is rotated, it is giving the correct number of set of coordinates, but this is not the case when floor plan is not rotated. May be it of giving the coordinates of centroids of the rooms. Could you please tell me how to solve this issue?
If you have 3 rooms, you must create 3 separate images each containing only one of the rooms. I described earlier how you can do this with regionprops(...,'PixelIdxList').
Could you please check this code? bwlabel also producing the rooms seperately while running the code and pgnCorners is applied to identify the coordinates.
Also could you please tell me what will be the output of regionprops(....,'PixelIdxList')? Can you please write the function(not completely, just to know how to use it) If you don't mind ?
I= imread('C:\Users\User\Desktop\tkinter_codes\floorplans\ROBIN\closeddoorsCat1_1.jpg');
[L,n] = bwlabel(I);
for i = 1:n
I = L == i;
imshow(I)
corners = pgonCorners(I,4,360);
disp(corners)
array(i,1)=corners(1)
array(i,2)=corners(2)
array(i,3)=corners(3)
array(i,4)=corners(4)
array(i,5)=corners(5)
array(i,6)=corners(6)
array(i,7)=corners(7)
array(i,8)=corners(8)
hold on
plot( corners(:,2),corners(:,1),'yo','MarkerFaceColor','r',...
'MarkerSize',12,'LineWidth',2);
hold off
pause(0.5)
end
for j=1:n-1
bbox_loc(j,1)=array(j+1,1)
bbox_loc(j,2)=array(j+1,2)
bbox_loc(j,3)=array(j+1,3)
bbox_loc(j,4)=array(j+1,4)
bbox_loc(j,5)=array(j+1,5)
bbox_loc(j,6)=array(j+1,6)
bbox_loc(j,7)=array(j+1,7)
bbox_loc(j,8)=array(j+1,8)
end
save('C:\\Users\\User\\Desktop\\cfile.mat','bbox_loc')
function corners = pgonCorners(BW,k,N)
%Method of detecting the corners in a binary image of a convex polygon with
%a known number of vertices. Uses a linear programming approach.
%
% corners = pgonCorners(BW,k)
% corners = pgonCorners(BW,k,N)
%
%IN:
%
% BW: Input binary image
% k: Number of vertices to search for.
% N: Number of angular samples partitioning the unit circle (default=360).
% Affects the resolution of the search.
%
%OUT:
%
% corners: Detected corners in counter-clockwise order as a k x 2 matrix.
if nargin<3, N=360; end
theta=linspace(0,360,N+1); theta(end)=[];
IJ=bwboundaries(BW);
IJ=IJ{1};
centroid=mean(IJ);
IJ=IJ-centroid;
c=nan(size(theta));
for i=1:N
[~,c(i)]=max(IJ*[cosd(theta(i));sind(theta(i))]);
end
Ih=IJ(c,1); Jh=IJ(c,2);
[H,~,~,binX,binY]=histcounts2(Ih,Jh,k);
bin=sub2ind([k,k],binX,binY);
[~,binmax] = maxk(H(:),k);
[tf,loc]=ismember(bin,binmax);
IJh=[Ih(tf), Jh(tf)];
G=loc(tf);
C=splitapply(@(z)mean(z,1),IJh,G);
[~,perm]=sort( cart2pol(C(:,2),C(:,1)),'descend' );
corners=C(perm,:)+centroid;
end
As a simple example, the attached file contains two box shaped regions
load Boxes
imshow(A);
and here is how I woul make a duplicate image with only the smaller box.
reg=regionprops(A>0,'PixelIdxList');
B=false(size(A));
B(reg(2).PixelIdxList)=1;
imshow(B)
Thank you so much. Now it's working fine

Connectez-vous pour commenter.

Plus de réponses (2)

You can find the required pixel values anf get the points. Check below:
I = imread("image.jpeg") ;
[y,x] = find(I~=255) ;
imshow(I)
hold on
plot(x,y,'*r')
% Bounding box
BB = [min(x) min(y) ;max(x) max(y)] ;

5 commentaires

I am trying to have points for each room. This works fine but how can I get like a 3 sets, such that each set have points of a room.
Try hough transform.
Thank you for your information. Could you please tell me is there any way to distingush the points to the room they belong to? I want to have like a set of corner points of individual rooms. Is there any way to achieve that?
I can not have the individual images for rooms. So that's why I am asking.
The bounding box is aligned with the edges of the image. It does not tilt the bounding box to align with the edges of your rooms like in your tilted image.
See my answer if you want the boundaries of the rooms regardless if they're tilted or not.

Connectez-vous pour commenter.

Here is one way to get the coordinates of the boundary points of each room. Each boundary is shown outlining the room in a different color.
% By Image Analyst
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 22;
%--------------------------------------------------------------------------------------------------------
% READ IN IMAGE
folder = pwd;
baseFileName = 'image.jpeg';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% The file doesn't exist -- didn't find it there in that folder.
% Check the entire search path (other folders) for the file by stripping off the folder.
fullFileNameOnSearchPath = baseFileName; % No path this time.
if ~exist(fullFileNameOnSearchPath, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
grayImage = imread(fullFileName);
% Get the dimensions of the image.
% numberOfColorChannels should be = 1 for a gray scale image, and 3 for an RGB color image.
[rows, columns, numberOfColorChannels] = size(grayImage);
if numberOfColorChannels > 1
% It's not really gray scale like we expected - it's color.
% Use weighted sum of ALL channels to create a gray scale image.
grayImage = rgb2gray(grayImage);
% ALTERNATE METHOD: Convert it to gray scale by taking only the green channel,
% which in a typical snapshot will be the least noisy channel.
% grayImage = grayImage(:, :, 2); % Take green channel.
end
subplot(2, 1, 1);
imshow(grayImage, []);
impixelinfo;
title('Original Gray Scale Image', 'FontSize', fontSize, 'Interpreter', 'None');
hFig = gcf;
hFig.WindowState = 'maximized'; % May not work in earlier versions of MATLAB.
drawnow;
%--------------------------------------------------------------------------------------------------------
% SEGMENTATION OF IMAGE
% Get a binary image
binaryImage = imbinarize(grayImage);
% Get rid of big white frame around the border of the image.
binaryImage = imclearborder(binaryImage);
subplot(2, 1, 2);
imshow(binaryImage, []);
impixelinfo;
title('Binary Image', 'FontSize', fontSize, 'Interpreter', 'None');
hFig = gcf;
hFig.WindowState = 'maximized'; % May not work in earlier versions of MATLAB.
drawnow;
% Get the coordinates around each room
boundaries = bwboundaries(binaryImage);
numRooms = length(boundaries);
% Plot them
roomColors = hsv(numRooms);
hold on;
for k = 1 : numRooms
thisBoundary = boundaries{k};
x = thisBoundary(:, 2);
y = thisBoundary(:, 1);
plot(x, y, '-', 'Color', roomColors(k, :), 'LineWidth', 4);
end

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by