Get a relationship between position vector return by getposition method in matlab - matlab

I wrote a code for image cropping. I used imrect to draw a rectangle on the image and then get the position of it by using the method getposition. I wrote a function which uses image pixel coordinates for cropping operation. How can I create a relationship between values return by getposition method and image pixel coordinates.My code for cropping is as follows,
[rnum cnum dim]=size(img);
for h=1:dim
for i=1:width
for j=1:height
negative(i,j,h)=img(xmin+i,ymin+j,h);
end
end
end
width,height,xmin,ymin have to found from getposition method

Like you said, imrect's getPosition method will return:
[xmin ymin width height] = getPosition( h );
The first two values are the top-left corner of the rectangle, and the next two values are the length of the sides of the rectangle. These should all be in pixel coordinates if you are using imrect.
To crop an image based on these position values, you will start at the top-left corner of (xmin, ymin) and go to the bottom-right corner at (xmin+width-1, ymin+height-1).
You should not use for loops to get the pixel data, you can take advantage of MATLAB's vectorization characteristics and do the following:
CroppedImageMatrix = OriginalImageMatrix( [ymin : 1 : ymin+height-1],
[xmin : 1 : xmin+width-1],
: );
This will immediately "crop" the image and place the cropped data into the new matrix. You can do this because you are using a rectangular crop and all of the indices correspond to create a rectangular lattice of points. It would be "trickier" if this was not a rectangular crop.
This also will work the same for color or grayscale images because you do not need to index the channel dimension, you just take the values from every available channel.
P.S. - Documentation page for imrect: http://www.mathworks.com/help/images/ref/imrect.html

Related

How can I draw the rectangle including the surfPoints object on the image?

I have a grayscale image I want to extract the regions of interest using detectSURFFeatures(). Using this function I get a surfPoints object.
by displaying this object on the image I get circles as regions of interest.
For my case I want the rectangular areas encompassing these circles.
To be more clear i have a image 1:
I want to extract Region of Interest (ROI) using : detectSURFFeatures(), we obtain the image
if you can see we have circular region, and for my case i want the rectangular ROI that contains the circular region :
It looks like the radius is fully determined by the points.Scale parameter.
% Detection of the SURF features:
I = imread('cameraman.tif');
points = detectSURFFeatures(I);
imshow(I); hold on;
% Select and plot the 10 strongest features
p = points.selectStrongest(10)
plot(p);
% Here we add the bounding box around the circle.
c = 6; % Correction factor for the radius
for ii = 1:10
x = p.Location(ii,1); % x coordinate of the circle's center
y = p.Location(ii,2); % y coordinate of the circle's center
r = p.Scale(ii); % Scale parameter
rectangle('Position',[x-r*c y-r*c 2*r*c 2*r*c],'EdgeColor','r')
end
And we obtain the following result:
In this example the correction factor for the radius is 6. I guess that this value correspond to half of the default Scale propertie's value of a SURFPoints object (which is 12.0). But since there is no information about that in the documentation, I can be wrong. And be carreful, the scale parameter of each ROI is not the same thing as the scale propertie of a SURFPoints object.

Geometrical transformation of a polygon to a higher resolution image

I'm trying to resize and reposition a ROI (region of interest) correctly from a low resolution image (256x256) to a higher resolution image (512x512). It should also be mentioned that the two images cover different field of view - the low and high resolution image have 330mm x 330mm and 180mm x 180mm FoV, respectively.
What I've got at my disposal are:
Physical reference point (in mm) in the 256x256 and 512x512 image, which are refpoint_lowres=(-164.424,-194.462) and refpoint_highres=(-94.3052,-110.923). The reference points are located in the top left pixel (1,1) in their respective images.
Pixel coordinates of the ROI in the 256x256 image (named pxX and pxY). These coordinates are positioned relative to the reference point of the lower resolution image, refpoint_lowres=(-164.424,-194.462).
Pixel spacing for the 256x256 and 512x512 image, which are 0.7757 pixel/mm and 2.8444 pixel/mm respectively.
How can I rescale and reposition the ROI (the binary mask) to correct pixel location in the 512x512 image? Many thanks in advance!!
Attempt
% This gives correctly placed and scaled binary array in the 256x256 image
mask_lowres = double(poly2mask(pxX, pxY, 256., 256.));
% Compute translational shift in pixel
mmShift = refpoint_lowres - refpoint_highres;
pxShift = abs(mmShift./pixspacing_highres)
% This produces a binary array that is only positioned correctly in the
% 512x512 image, but it is not upscaled correctly...(?)
mask_highres = double(poly2mask(pxX + pxShift(1), pxY + pxShift(2), 512.,
512.));
So you have coordinates pxX, and pxY in pixels with respect to the low-resolution image. You can transform these coordinates to real-world coordinates:
pxX_rw = pxX / 0.7757 - 164.424;
pxY_rw = pxY / 0.7757 - 194.462;
Next you can transform these coordinates to high-res coordinates:
pxX_hr = (pxX_rw - 94.3052) * 2.8444;
pxY_hr = (pxY_rw - 110.923) * 2.8444;
Since the original coordinates fit in the low-res image, but the high-res image is smaller (in physical coordinates) than the low-res one, it is possible that these new coordinates do not fit in the high-res image. If this is the case, cropping the polygon is a non-trivial exercise, it cannot be done by simply moving the vertices to be inside the field of view. MATLAB R2017b introduces the polyshape object type, which you can intersect:
bbox = polyshape([0 0 180 180] - 94.3052, [180 0 0 180] - 110.923);
poly = polyshape(pxX_rw, pxY_rw);
poly = intersect([poly bbox]);
pxX_rw = poly.Vertices(:,1);
pxY_rw = poly.Vertices(:,2);
If you have an earlier version of MATLAB, maybe the easiest solution is to make the field of view larger to draw the polygon, then crop the resulting image to the right size. But this does require some proper calculation to get it right.

How to get the size of a rotated image knowing only the angle of rotation and the size of the original image using Matlab?

I have an image Im of size 50x129 :
It is a part of big cercle in yellow, and a space with blue color.
I rotated this image Im using imrotate() with an angle of -45°, I get ImR :
I would like to compute the new size of the image ImR ?
One way to do this is to use the function axis of ImR :
axises = axis;
w1=axises(2)-axises(1);
h1=axises(4)-axises(3);
but I want to be independent from the resulting image ... I mean I would like to, knowing the size of original image and the angle of rotation, get the size of the rotated image.
Update
I intend to use this code which rotate the point A with an angle t around the Origin point.
function Af = rotate(A,t,Origin)
% Definition of the rotation matrix (rotation around origin)
R=[ ...
cosd(t) -sind(t)
sind(t) cosd(t)
];
% translation
At = A - Origin;
% rotation of the points A and B
Ar = R*At;
Compute the position of the corners of the rotated image using your rotation matrix. And put them all in a matrix as follows:
rotImgCorners = [
x_topLeft , y_topleft;
x_top_right , y_top_right;
%//... bottom left ...
%//... bottom right ...
]
Then the size of your new image would be:
%// [horizontal size, vertical size] - you can switch it around if you whish
newImgSize = max(rotImgCorners, [], 1) - min(rotImgCorners, [], 1);

How to crop face section from an image with given corner points. MATLAB

I want to crop a face section from an image but face image is not straight/vertically aligned. I am having four pixel points to crop it..
Problem is that,
If i will transform image first the pixel points cannot be used thereafter to crop the facial section out of it.
Or in other case I am not having an exact bounding box to crop the image directly using imcrop as facial sections are somewhat tilted left or right.
The four pixel points are at forehead , chin and ears of the face to be cropped.
You should look at poly2mask. This function produces a mask image from your given x and y coordinates:
BW = poly2mask(x,y,m,n);
where x and y are your coordinates, and the produced BW image is m by n. You can then use this BW image to mask your original image I by doing
I(~BW) = 0;
If you actually want to crop, then you could get the bounding box (either through the regionprops function or the code below):
x1 = round(min(x));
y1 = round(min(y));
x2 = round(max(x));
y2 = round(max(y));
and then crop the image after you have used the BW as a mask.
I2 = I(x1:x2,y1:y2);
Hope that helps.

MATLAB: Display image inside circle

As part of a circle recognition program, I have a background image with a geometrical circle with known coordinates and radius. I want the inside part of the circle filled by an image and the outside left alone. My best idea is some sort of circular mask, but I am not sure this is the best approach. Any suggestions?
X = imread('X.jpg'); % Background image jpg
Y = imread('Y.jpg'); % Filling image jpg
cent = [100,100]; % Center of circle
rad = 20; % Circle radius
% Fill circle ?
...
I have not provided the extended code, due to confidentiality.
I think the hard part was done by whomever authored this: http://matlab.wikia.com/wiki/FAQ#How_do_I_create_a_circle.3F
Assumptions:
I'm assuming you're not going to specify points that are out of range of the image (i.e. I'm not adding validation here).
I use the background image to relate the "center" of your circle to the coordinates.
I'm assuming radius is in pixels.
I didn't create a background image with a circle of known radius because I don't think that's necessary to create the filling effect you're looking for (unless I'm missing something).
Code:
X = imread('rdel_x.png'); % Background image jpg (I used a random image but this can be your blank + geometric circle)
Y = imread('rdel_y.png'); % Filling image jpg
cent = [100,150]; % Center of circle
rad = 70; % Circle radius
% make a mesh grid to provide coords for the circle (mask)
% taken from http://matlab.wikia.com/wiki/FAQ#How_do_I_create_a_circle.3F
[columnsInImage rowsInImage] = meshgrid(1:size(X,2), 1:size(X,1));
% circle points in pixels:
circlePixels = (rowsInImage - cent(1)).^2 ...
+ (columnsInImage - cent(2)).^2 <= rad.^2;
circlePixels3d=repmat(circlePixels,[1 1 3]); % turn into 3 channel (assuming X and Y are RGB)
X((circlePixels3d)) = Y((circlePixels3d)); % assign the filling image pixels to the background image for pixels where it's the desired circle
imagesc(X);
axis image off
Result: from left to right, background image, filling image, result from above code.
Edit: you might not even need the background image if everything is encapsulated in your coordinates. e.g. try appending this to the above code...
Z=zeros(size(X),'uint8'); % same size as your background
Z(circlePixels3d) = Y(circlePixels3d);
figure; % new fig
imagesc(Z);
axis image off