How can i extract part of a matrix when the part i'm extracting is slanted?

I have an image and i used the impoly() command do draw a slanted rectangle. I have the positions of the vertex of the rectangle and i would like to copy the intensities on those indexes into another matrix. My problem is that the matrix i want to extract is slanted. This is the relevant part of my code:
filename = uigetfile; %get the file name
obj = VideoReader(filename);
nFrames=obj.NumberOfFrames;
thisfig = figure();
for k = 1 : nFrames
this_frame = read(obj, k);
thisax = axes('Parent', thisfig);
image(this_frame, 'Parent', thisax);
if k==nFrames
title(thisax, sprintf('Frame #%d', k));
end
if k==1
result=input('How many rectangles would you like to draw? ');
pos=zeros(4,2,10); %declaring a reasonable size for post
for i=1:result
handle=impoly;
sample=getPosition(handle);
pos(:,:,i) = getPosition(handle);
end
end
end

4 comentarios

Hello @Maayan , I have the same problem where I am trying to find the indices inside a tilted rectangle on a big matrix. I have a 120*210 matrix and I have an initial horizontal rectangle (which I have the coordinates of 4 vertices, and it is a 40*70 indecies inside the big matrix), now I am rotationg the rectangle at a given angle and I want to extract the new indecis inside the tilted rectangle.
I am reading the comments to your question and I do not follow, could you let me know if and which one of these answrs helpded you?
I will add apicture of my problem so you could see if it is similar to yours. (The green rectangle is the initial one with known coordinates and indecies, the red one is the rotated rectangle with known angle but unknown index- The big matrix is shown in a countor format).
Thank you so much.
@mohammad jolaei if you know the location of the original corners and the angle, you can get the location of the rotated version using the rotation matrix. https://en.wikipedia.org/wiki/Rotation_matrix
Hello @Image Analyst and thank you for your comment. You are right, I can find the rotated version by using the rotation matrix. But the problem is that I need to extract a new matrix from the larger matrix after rotation which is inside the rotataed rectangle and the same size as the initial matrix (inside the initial rectangle).
When I find the rotated points of the rotated rectangle, I have decimals numbers and it makes it harder to find the indecis since the vertices are not integers.
Also, Lets say I floor the numbers and make them integers, how do I find the index inside this new rotataed (tilted) rectangle?
You can use the floating point numbers and use poly2mask to get a binary mask of the rotated part. Then you can use that to either mask the image (blacken outside of the rectangle mask) or to extract all the pixel values in a 1-D list.

Iniciar sesión para comentar.

 Respuesta aceptada

Matt J
Matt J el 29 de Sept. de 2013
Perhaps you should just use IMROTATE to rotate your entire image, so that the rectangle is no longer slanted. Then extract a normal box.

2 comentarios

I don't know the angle in which it is slanted and it changes every time you run the code so i don't think i can use the imrotate function.
You said you know the vertices of your rectangle. The angle can be computed from the vertices.

Iniciar sesión para comentar.

Más respuestas (2)

Matt J
Matt J el 15 de Sept. de 2013
Editada: Matt J el 15 de Sept. de 2013
I have the positions of the vertex of the rectangle and i would like to copy the intensities on those indexes into another matrix.
I assume you really mean that you want the image values enclosed by the polygon. The vertex coordinates can fall in between pixel locations and so are not indexable.
To get the enclosed values, you can do
regionValues=this_frame( createMask(handle) )
where "handle" is your handle to the impoly object.

4 comentarios

Hi, i tried to use the createMask() command but i got a vector with values, not a matrix as i wished.The values in my vector are the intensities values of my polygon? and if that is the case is there any way to do it in a matrix way?
Matt J
Matt J el 15 de Sept. de 2013
Editada: Matt J el 15 de Sept. de 2013
not a matrix as i wished
If you want the polygon values embedded in a new matrix, what should the matrix values be outside the polygon? Zeros? If so, you can just do
masked_frame= this_frame.*createMask(handle);
I don't want any values outside the polygon, I just want the values inside the polygon. My problem is that i don't really need the impoly() function, but it seems that that is the best way to do what i want-I want to draw rectangles that can be also slanted-meaning not parallel with the figure axes.I understand there is no way to draw a rectangle with the imrect() command and then to rotate it,so i need to use the impoly() command. I need to extract the values inside my polygon/rectangle into a new matrix so i will be able to calculate things like the mean of the columns and etc.
Matt J
Matt J el 15 de Sept. de 2013
Editada: Matt J el 15 de Sept. de 2013
I need to extract the values inside my polygon/rectangle into a new matrix so i will be able to calculate things like the mean of the columns and etc.
Since your data has a slanted geometry, it's not clear what you mean by "mean of the columns". A column is a notion that applies to rectangular arrays. My vague impression (you have to be clearer!) is that you want to take means etc... across the columns of your original matrix, but ignoring data outside the polygon. If so, and if you have the Statistics Toolbox, then you could fill the region outside the polygon with NaNs and use NANMEAN, NANSTD, etc...
mask=createMask(handle);
this_frame(~mask)=nan;
columnMeans=nanmean(this_frame)
If you don't have nanmean, nanstd, etc... you can re-invent them by doing things like
columnMeans=sum(this_frame.*mask,1)./sum(mask,1);

Iniciar sesión para comentar.

See my well commented demo below. You should be easily able to adapt it from copying and pasting rectangles to polygons using impoly() and poly2mask(). If you can't let me know.
% Lets user drag out a box on an image, then define where they want to paste it.
% Then it pastes the drawn region onto the original image.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
imtool close all; % Close all imtool figures.
clear; % Erase all existing variables.
workspace; % Make sure the workspace panel is showing.
fontSize = 20;
format compact;
% Check that user has the Image Processing Toolbox installed.
hasIPT = license('test', 'image_toolbox');
if ~hasIPT
% User does not have the toolbox installed.
message = sprintf('Sorry, but you do not seem to have the Image Processing Toolbox.\nDo you want to try to continue anyway?');
reply = questdlg(message, 'Toolbox missing', 'Yes', 'No', 'Yes');
if strcmpi(reply, 'No')
% User said No, so exit.
return;
end
end
% Read in a standard MATLAB gray scale demo image.
folder = fullfile(matlabroot, '\toolbox\images\imdemos');
baseFileName = 'eight.tif';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% File doesn't exist -- didn't find it there. Check the search path for it.
fullFileName = baseFileName; % No path this time.
if ~exist(fullFileName, '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.
% numberOfColorBands should be = 1.
[rows columns numberOfColorBands] = size(grayImage);
% Display the original gray scale image.
subplot(2, 2, 1);
imshow(grayImage);
axis on;
title('Original Grayscale Image', 'FontSize', fontSize);
% Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
% Give a name to the title bar.
set(gcf,'name','Demo by ImageAnalyst','numbertitle','off')
% Let's compute and display the histogram, just for fun.
[pixelCount grayLevels] = imhist(grayImage);
subplot(2, 2, 2);
bar(pixelCount);
grid on;
title('Histogram of original image', 'FontSize', fontSize);
xlim([0 grayLevels(end)]); % Scale x axis manually.
% Ask user to draw a box.
subplot(2, 2, 1);
promptMessage = sprintf('Drag out a box that you want to copy,\nor click Cancel to quit.');
titleBarCaption = 'Continue?';
button = questdlg(promptMessage, titleBarCaption, 'Continue', 'Cancel', 'Continue');
if strcmpi(button, 'Cancel')
return;
end
k = waitforbuttonpress;
point1 = get(gca,'CurrentPoint'); % button down detected
finalRect = rbbox; % return figure units
point2 = get(gca,'CurrentPoint'); % button up detected
point1 = point1(1,1:2); % extract x and y
point2 = point2(1,1:2);
p1 = min(point1,point2); % calculate locations
offset = abs(point1-point2); % and dimensions
% Find the coordinates of the box.
xCoords = [p1(1) p1(1)+offset(1) p1(1)+offset(1) p1(1) p1(1)];
yCoords = [p1(2) p1(2) p1(2)+offset(2) p1(2)+offset(2) p1(2)];
x1 = round(xCoords(1));
x2 = round(xCoords(2));
y1 = round(yCoords(5));
y2 = round(yCoords(3));
hold on
axis manual
plot(xCoords, yCoords, 'b-'); % redraw in dataspace units
% Display the cropped image.
croppedImage = grayImage(y1:y2,x1:x2);
subplot(2, 2, 3);
imshow(croppedImage);
axis on;
title('Region that you defined', 'FontSize', fontSize);
% Paste it onto the original image
[rows2 columns2] = size(croppedImage)
promptMessage = sprintf('Click on the upper left point where you want to paste it,\nor click Cancel to quit.');
titleBarCaption = 'Continue?';
button = questdlg(promptMessage, titleBarCaption, 'Continue', 'Cancel', 'Continue');
if strcmpi(button, 'Cancel')
return;
end
[x, y] = ginput(1)
% Determine the pasting boundaries.
r1 = int32(y);
c1 = int32(x);
r2 = r1 + rows2 - 1;
r2 = min([r2 rows]);
c2 = c1 + columns2 - 1;
c2 = min([c2, columns]);
plot([c1 c2 c2 c1 c1], [r1 r1 r2 r2 r1], 'r-');
% Paste as much of croppedImage as will fit into the original image.
grayImage(r1:r2, c1:c2) = croppedImage(1:(r2-r1+1), 1:(c2-c1+1));
subplot(2, 2, 4);
imshow(grayImage);
axis on;
title('Region that you defined pasted onto original', 'FontSize', fontSize);

11 comentarios

Hi, can you please refer me to the relevant part of your code where the slanted matrix is extracted into a normal matrix? I'm having trouble finding it. Thanks
Matt J
Matt J el 29 de Sept. de 2013
Editada: Matt J el 29 de Sept. de 2013
I think Image Analyst misunderstood you. The region that his code lets you extract is always a perfectly rectangular box. This is the relevant segment of code
k = waitforbuttonpress;
point1 = get(gca,'CurrentPoint'); % button down detected
finalRect = rbbox; % return figure units
point2 = get(gca,'CurrentPoint'); % button up detected
point1 = point1(1,1:2); % extract x and y
point2 = point2(1,1:2);
The boundaries of the region being extracted are defined via RBBOX.
I know that a matrix is rectangular by definition.My area is a rectangle, it's just slanted. What i'm looking for is a way to extract the rectangular part and straight in it into a matrix that will also be a rectangle.
I edited my question and posted an image so you can see what i mean by slanted rectangle.
Matt J
Matt J el 29 de Sept. de 2013
Editada: Matt J el 29 de Sept. de 2013
It is unclear is what you mean by "extracting" it. The boundaries of your rotated rectangle pass through non-integer locations. It's not clear what rule you use to decide what pixels belong to it and what could gaurantee that it can still be rectangularly reshaped afterward.
Do you only want to include the integer coordinates completely inside that region? A 3x3 rectangle rotated 45 degrees only contains 5 integer coordinates. Since 5 is a prime number, there is no way to reshape it into anything but a 1x5 or 5x1 matrix.
>> A=zeros(5); A(2:4,2:4)=1
A =
0 0 0 0 0
0 1 1 1 0
0 1 1 1 0
0 1 1 1 0
0 0 0 0 0
>> imrotate(A,45,'bilinear','crop')>=1
ans =
0 0 0 0 0
0 0 1 0 0
0 1 1 1 0
0 0 1 0 0
0 0 0 0 0
Maayan
Maayan el 29 de Sept. de 2013
Editada: Matt J el 29 de Sept. de 2013
I can round the indices into integers.
Let's imagine i have this matrix (like in the image i added) and i want only the red rectangle so in this case my matrix will be: 2 0. That's what i want to do and i can round the indices into integers and take the risk to lose some information.Is it clearer now?
Matt J
Matt J el 29 de Sept. de 2013
Editada: Matt J el 29 de Sept. de 2013
Will the extracted matrix be [2,0] or will it be [2;0]? Regardless, as I showed you in my last example, rounding can lead to a set of pixels without a rectangular shape.
The only thing that might work is perhaps to rotate the image (see my latest Answer).
Incidentally, you can now attach images directly to Questions/Answers/Comments. I've been doing that for you.
Image Analyst
Image Analyst el 29 de Sept. de 2013
Editada: Image Analyst el 29 de Sept. de 2013
I didn't misunderstand - I knew the rectangle was slanted and that's why I said that it could easily be adapted . I picked my vertices of the polygon aligned with the axes but I expected maayan to put in her actual vertices which could be anywhere. Since she is using impoly, the vertices are available and they can just be passed in to poly2mask to "cut out" or "extract" that slanted rectangular portion of the image. Of course if the area is not tens of thousand of pixels but just 2 or 10 or 20 pixels, there will be horrible jaggies. Computing means of rows (say this is along the long axis) or means of columns (along a direction perpendicular to the major axis) is really meaningless when you have only 2 pixels. But if you have thousands of pixels it can be done fairly accurately. Perhaps the best way to do that is to rotate the image first as Matt suggested. Then you can simply use the sum() or mean() function.
Did you figure it out? I have the same exact problem for over a month and still could not find any resealable solution for that. my rectangular position changes in every loop and I don't know the angels.
In fact it is part of the swath which is mapped over the earth and since I am just interested in the specific slanted geo-location on those swath, I need to select the slanted rectangular and tilt it as a new matrix which also excludes the arrays outside. And the swath will change in every loop, that's why the slant rectangular will change. So please help me if you already found out the solution.
Matt J
Matt J el 8 de Nov. de 2014
Editada: Matt J el 8 de Nov. de 2014
So please help me if you already found out the solution.
Andrea, The thread has an Accepted answer, involving imrotate and it's not clear why that wouldn't work for you as well. You say you "don't know the angles", but since you know the boundaries of the swath, you should be able to calculate that. If you don't know the boundaries of the swath, you couldn't have any basis for deciding what's to be extracted.
Andrea, I recommend you start a new question after reading this. Post your image(s) and explain whatever information that you know about the image or the geometry about how it was taken. In the meantime, check out the camera calibration capability of the Computer Vision System Toolbox http://www.mathworks.com/products/computer-vision/features.html#camera-calibration which I think can help you.

Iniciar sesión para comentar.

Categorías

Más información sobre Display Image en Centro de ayuda y File Exchange.

Preguntada:

el 15 de Sept. de 2013

Comentada:

el 1 de Jun. de 2023

Community Treasure Hunt

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

Start Hunting!

Translated by