how can I Rotate the image around the center using transformPointsForward and Getting the coordinates of the four corners of the changed image؟ - matlab

I want to rotate the image arround the center.I usesd transformPointForward function for do this.I want to getting the coordinate of the four corners of the changed image.in below you can see my code.thanks for your help.
theta=+50;
tform = affine2d([cosd(theta) -sind(theta) 0;sind(theta) cosd(theta) 0; 0 0
1]);
A = imread('pout.tif');
corners = [1,1;1,size(A,2);size(A,1),1;size(A,1),size(A,2)];
X = transformPointsForward(tform,corners);
Rin = imref2d(size(A))
Rin.XWorldLimits = Rin.XWorldLimits-mean(Rin.XWorldLimits);
Rin.YWorldLimits = Rin.YWorldLimits-mean(Rin.YWorldLimits);
[out,ref] = imwarp(A,Rin,tform);
figure,
subplot(1,2,1),imshow(A,[])
subplot(1,2,2),imshow(out,[])
X(:,1) = X(:,1) - ref.XWorldLimits(1);
X(:,2) = X(:,2) - ref.YWorldLimits(1);

Related

How to draw a rectangle using 4 corners on an image in Matlab R2018b?

In Matlab, there is rectangle('Position',[x,y,w,h]) to draw a rectangle object, that w and h are a width and a height respectively (This link). While I try to draw a rectangle on an image using 4 corners: min_x, max_x, min_y and max_y that are specified in the following image.
Ex:
min_x = 193; max_x = 220; min_y = 168; max_y = 190;
I saw this link and like that, but they couldn't help me. Is there any way to draw a rectangle with 4 corners?
A = imresize( imread('peppers.png'),0.6);%resizing for better visibility
min_x = 193; max_x = 220; min_y = 168; max_y = 190;
x = min_x;
y = min_y;
w = max_x-min_x;
h = max_y-min_y;
imshow(A)
rectangle('Position',[x,y,w,h],'EdgeColor','r','Linewidth',3);
% Or insert shape to bitmap:
% B = insertShape(A,'rectangle',[x,y,w,h]);
% imshow(B)

How to rotate image around the center of object in matlab?

imrotate function in matlab rotates the image around the center. How to rotate image by custom coordinates?
For example center of blob in binary mask. If using imcrop and place blob in the center, how to reshape that to same as original image?
Code
% create binary mask
clc;
clear;
mask= zeros(400,600,'logical');
positein = [280,480];
L = 40;
x = positein (1);
y = positein (2);
mask(x,y-L:y+L) = 1;
for i =1:8
mask(x+i,y-L:y+L) = 1;
mask(x-i,y-L:y+L) = 1;
end
Angle = 45;
mask_after_rotation = imrotate(mask,-Angle,'crop');
figure,
subplot(1,2,1),imshow(mask),title('before rotation');
subplot(1,2,2),imshow(mask_after_rotation),title('after rotate 45');
This is generally performed by constructing an affine transform which translates the point about which we want to rotate to the origin, then performs a rotation, then translates back.
For example, to rotate by -45 degrees like in your example we could do the following
% create binary mask
mask = zeros(400, 600,'logical');
positein = [480, 200];
W = 40; H = 8;
x = positein(1); y = positein(2);
mask(y-H:y+H, x-W:x+W) = 1;
angle = -45;
% translate by -positein, rotate by angle, then translate back by pt
T = [1 0 0; 0 1 0; -positein 1];
R = [cosd(angle) -sind(angle) 0; sind(angle) cosd(angle) 0; 0 0 1];
Tinv = [1 0 0; 0 1 0; positein 1];
tform = affine2d(T*R*Tinv);
mask_rotated = imwarp(mask, tform, 'OutputView', imref2d(size(mask)));
figure(1); clf(1);
subplot(1,2,1),imshow(mask),title('before rotation');
subplot(1,2,2),imshow(mask_rotated),title('after rotate 45');
Alternatively you can set the reference object so that the desired coordinate is at the origin
% Set origin to positein, then rotate
xlimits = 0.5 + [0, size(mask,2)] - positein(1);
ylimits = 0.5 + [0, size(mask,1)] - positein(2);
ref = imref2d(size(mask), xlimits, ylimits);
R = [cosd(angle) -sind(angle) 0; sind(angle) cosd(angle) 0; 0 0 1];
tform = affine2d(R);
mask_rotated = imwarp(mask, ref, tform, 'OutputView', ref);
You could do a series of transformation to achieve the rotation around an arbitrary point, which are: 1) Move the arbitrary point to the center of the image, 2) Rotate the image by a predefined angle, & 3) Translate it back to the original position. For example, if you want to rotate the mask around the center of the blob in your case, then you could carry out the following steps.
trns_mask = imtranslate(mask, [-180, -80]); % Move to the origin
trns_mask_rotated = imrotate(trns_mask,-Angle,'crop'); % Rotate
mask_after_rotation = imtranslate(trns_mask_rotated, [180, 80]); % Move back
There are options for the function imtranslate() which you could play with to make sure you are not losing any image information during the transformation.

Problems with performing image translation in MATLAB

I'm trying to do image translation using MATLAB, and the image doesn't move at all. My code is:
myPic = imread('pic.jpg');
x = 250;
y = 375;
trans = affine2d([1 0 0; 0 1 0; x y 1]);
outputPic = imwarp(myPic, trans);
imshow(myPic)
axis on
figure()
imshow(outputPic)
axis on
isequal(myPic,outputPic) %evaluates to 1!!!
When I do the same for a rotation affine matrix, it worked. Why doesn't this work?
here's what happens when I print both pics:
In order for this to work, you'll need to define an 'OutputView' parameter.
This parameter sets the size and location of the output image in world coordinate system, using imref2d function.
Example:
myPic = imread('peppers.png');
x = 250;
y = 375;
%defines transformations
trans = affine2d([1 0 0; 0 1 0; x y 1]);
eyeTrans= affine2d([1 0 0; 0 1 0; 0 0 1]);
%initializes imref2d object
outView = imref2d([size(myPic,1)+y,size(myPic,2)+x]);
outputPic1 = imwarp(I,trans,'OutputView',outView)
outputPic2 = imwarp(I,eyeTrans,'OutputView',outView)
%display result
figure,
subplot(1,2,1); imshow(outputPic2); title('original')
subplot(1,2,2); imshow(outputPic1); title('translated')
Result:

How to square the corners of a "rectangle" in a bw image with matlab

I have images of rectangles or deformed rectangles with rounded corners, like this:
or this:
is there a way to make the corners squared with matlab?
And then how can i get the coordinates of those new corners?
Thank you
Explanation
This problem is similar to the following question. My answer will be somehow similar to my answer there, with the relevant modifications.
we want to find the parallelogram corners which fits the most to the given shape.
The solution can be found by optimization, as follows:
find an initial guess for the 4 corners of the shape. This can be done by finding the boundary points with the highest curvature, and use kmean clustering to cluster them into 4 groups.
create a parallelogram given these 4 corners, by drawing a line between each pair of corresponding corners.
find the corners which optimize the Jaccard coefficient of the boundary image and the generated parallelogram map.
The optimization will done locally on each corner, in order to spare time.
Results
Initial corner guess (corners are marked in blue)
final results:
Code
main script
%reads image and binarize it
I = rgb2gray(imread('eA4ci.jpg')) > 50;
%finds boundry of largerst connected component
boundries = bwboundaries(I,8);
numPixels = cellfun(#length,boundries);
[~,idx] = max(numPixels);
B = boundries{idx};
%finds best 4 corners
[ corners ] = optimizeCorners(B);
%generate line mask given these corners, fills the result
linesMask = drawLines(size(I),corners,corners([2:4,1],:));
rectMask = imfill(linesMask,'holes');
%remove biggest CC from image, adds linesMask instead
CC = bwconncomp(I,8);
numPixels = cellfun(#numel,CC.PixelIdxList);
[~,idx] = max(numPixels);
res = I;
res(CC.PixelIdxList{idx}) = 0;
res = res | rectMask;
optimize corners function:
function [ corners] = optimizeCorners(xy)
%finds the corners which fits the most for this set of points
Y = xy(:,1);
X = xy(:,2);
%initial corners guess
corners = getInitialCornersGuess(xy);
boundriesIm = zeros(max(Y)+20,max(X)+20);
boundriesIm(sub2ind(size(boundriesIm),xy(:,1),xy(:,2))) = 1;
%R represents the search radius
R = 7;
%continue optimizing as long as there is no change in the final result
unchangedIterations = 0;
while unchangedIterations<4
for ii=1:4
%optimize corner ii
currentCorner = corners(ii,:);
bestCorner = currentCorner;
bestRes = calcEnergy(boundriesIm,corners);
cornersToEvaluate = corners;
for yy=currentCorner(1)-R:currentCorner(1)+R
for xx=currentCorner(2)-R:currentCorner(2)+R
cornersToEvaluate(ii,:) = [yy,xx];
res = calcEnergy(boundriesIm,cornersToEvaluate);
if res > bestRes
bestRes = res;
bestCorner = [yy,xx];
end
end
end
if isequal(bestCorner,currentCorner)
unchangedIterations = unchangedIterations + 1;
else
unchangedIterations = 0;
corners(ii,:) = bestCorner;
end
end
end
end
function res = calcEnergy(boundriesIm,corners)
%calculates the score of the corners list, given the boundries image.
%the result is acutally the jaccard index of the boundries map and the
%lines map
linesMask = drawLines(size(boundriesIm),corners,corners([2:4,1],:));
res = sum(sum(linesMask&boundriesIm)) / sum(sum(linesMask|boundriesIm));
end
get initial corners function:
function corners = getInitialCornersGuess(boundryPnts)
%calculates an initial guess for the 4 corners
%finds corners by performing kmeans on largest curvature pixels
[curvatureArr] = calcCurvature(boundryPnts, 5);
highCurv = boundryPnts(curvatureArr>0.3,:);
[~,C] = kmeans([highCurv(:,1),highCurv(:,2)],4);
%sorts the corners from top to bottom - preprocessing stage
C = int16(C);
corners = zeros(size(C));
%top left corners
topLeftInd = find(sum(C,2)==min(sum(C,2)));
corners(1,:) = C(topLeftInd,:);
%bottom right corners
bottomRightInd = find(sum(C,2)==max(sum(C,2)));
corners(3,:) = C(bottomRightInd,:);
%top right and bottom left corners
C([topLeftInd,bottomRightInd],:) = [];
topRightInd = find(C(:,2)==max(C(:,2)));
corners(4,:) = C(topRightInd,:);
bottomLeftInd = find(C(:,2)==min(C(:,2)));
corners(2,:) = C(bottomLeftInd,:);
end
function [curvatureArr] = calcCurvature(xy, halfWinSize)
%calculate the curvature of a list of points (xy) given a window size
%curvature calculation
curvatureArr = zeros(size(xy,1),1);
for t=1:halfWinSize
y = xy(t:halfWinSize:end,1);
x = xy(t:halfWinSize:end,2);
dx = gradient(x);
ddx = gradient(dx);
dy = gradient(y);
ddy = gradient(dy);
num = abs(dx .* ddy - ddx .* dy) + 0.000001;
denom = dx .* dx + dy .* dy + 0.000001;
denom = sqrt(denom);
denom = denom .* denom .* denom;
curvature = num ./ denom;
%normalizing
if(max(curvature) > 0)
curvature = curvature / max(curvature);
end
curvatureArr(t:halfWinSize:end) = curvature;
end
end
draw lines function:
function mask = drawLines(imgSize, P1, P2)
%generates a mask with lines, determine by P1 and P2 points
mask = zeros(imgSize);
P1 = double(P1);
P2 = double(P2);
for ii=1:size(P1,1)
x1 = P1(ii,2); y1 = P1(ii,1);
x2 = P2(ii,2); y2 = P2(ii,1);
% Distance (in pixels) between the two endpoints
nPoints = ceil(sqrt((x2 - x1).^2 + (y2 - y1).^2));
% Determine x and y locations along the line
xvalues = round(linspace(x1, x2, nPoints));
yvalues = round(linspace(y1, y2, nPoints));
% Replace the relevant values within the mask
mask(sub2ind(size(mask), yvalues, xvalues)) = 1;
end

3D rotation of a sphere around a fixed point in Matlab

I have a sphere centered on the origin of the axes. I use the rotate3d function to allow its rotation. However, when I rotate it, it seems to move in the space with having a fixed point for the rotation. I would like to fix the origin as rotation center. How can I achieve it?
Here is my code:
function ex
global state;
fh = figure('Menu','none','Toolbar','none','Units','characters',...
'Renderer','OpenGL');
hPanAni = uipanel('parent',fh,'Units','characters','Position',...
[22.6 10.4 53 23],'title','Controls','FontSize',11,...
'FontAngle','italic','FontWeight','bold');
hIniAni = uicontrol(hPanAni,'Style','pushbutton','Units','normalized',...
'Position',[0.14 0.75 0.5 0.12],'String','Spin',...
'FontSize',10,'Callback',#hIniAniCallback);
hFinAni = uicontrol(hPanAni,'Style','pushbutton','Units','normalized',...
'Position',[0.14 0.5 0.5 0.12],'String','Stop',...
'FontSize',10,'Callback',#hFinAniCallback);
hResetAni = uicontrol(hPanAni,'Style','pushbutton','Units','normalized',...
'Position',[0.14 0.25 0.5 0.12],'String','Reset',...
'FontSize',10,'Callback',#hResetAniCallback);
hPantSim = uipanel('Parent',fh,'Units','characters',...
'Position',[107.87 8 157.447 42],'BorderType','none','title',...
'Screen','FontSize',11,'FontAngle','italic',...
'FontWeight','bold');
hPantSimInt = uipanel('Parent',hPantSim,'Units','normalized','Position',...
[0 0 1 1],'BorderType','line','BackgroundColor','k');
axes('units','normalized','position',[0,0,1,1],'Parent',...
hPantSimInt);
stars = rand(60,2);
scatter(stars(:,1),stars(:,2),6,'y','Marker','+');
axis off;
ah4 = axes('Parent',hPantSimInt,'Units','normalized','Position',...
[0 0 1 1],'Color','none','Visible','off','DataAspectRatio',...
[1 1 1],'NextPlot','add');
T1 = 0:pi/1000:2*pi;
Fin = numel(T1);
if (Fin>1000)
Incr = floor(Fin/1000);
else
Incr = 1;
end
Y = zeros(numel(T1),3);
Y(:,1) = 7000*cos(T1);
Y(:,2) = 7000*sin(T1);
R_esf = 6378;
[x_esf,y_esf,z_esf] = sphere(50);
x_esf = R_esf*x_esf;
y_esf = R_esf*y_esf;
z_esf = R_esf*z_esf;
props.FaceColor= 'texture';
props.EdgeColor = 'none';
props.Parent = ah4;
surface(x_esf,y_esf,z_esf,props);
handles.psat = line('parent',ah4,'XData',Y(1,1), 'YData',Y(1,2),...
'ZData',Y(1,3),'Marker','o', 'MarkerSize',10,'MarkerFaceColor','b');
line([0 1.5*R_esf],[0 0],[0 0],'LineWidth',3,'Color','g');
line([0 0],[0 1.5*R_esf],[0 0],'LineWidth',3,'Color','g');
line([0 0],[0 0],[0 1.5*R_esf],'LineWidth',3,'Color','g');
pbaspect([1 1 1]);
axis vis3d;
rotate3d(ah4);
view([atan2(Y(1,2),Y(1,1)),0]);
az = 0;
k = 2;
ind_ini = 0;
state = 0;
function hIniAniCallback(hObject,evt)
tic;
if (ind_ini == 1)
return;
end
ind_ini = 1;
state = 0;
while (k<=Fin)
set(handles.psat,'XData',Y(k,1),'YData',Y(k,2),'ZData',Y(k,3));
pause(0.002);
if (k == Fin)
toc;
end
k = k + Incr;
if (state == 1)
state = 0;
break;
end
end
end
function hFinAniCallback(hObject,evt)
ind_ini = 0;
state = 1;
end
function hResetAniCallback(hObject,evt)
set([handles.psat],'Visible','off');
ind_ini = 0;
state = 1;
az = 0;
k = 2;
handles.psat = line('parent',ah4,'XData',Y(1,1), 'YData',Y(1,2),...
'ZData',Y(1,3),'Marker','o', 'MarkerSize',10,'MarkerFaceColor','b');
end
end
The problem is that the 3d rotation is done with respect to the center of your axes, and not with respect to the origin. After you add the green lines along the axes, the limits of the x,y,z axes is automatically changed, the center of sphere is no longer positioned in the center of the figure. Add the following line after drawing all the lines:
ax_limits = 2*[-R_esf R_esf];
set (ah4, 'xlim', ax_limits, 'ylim', ax_limits, 'zlim', ax_limits)
The '2' factor is just to prevent the sphere from filling your axes tightly. You can set it to whatever value you need.