Image rotation in matlab using bilinear-interpolation - image

clear
I = imread('256.jpg');
%imshow(I);
center = 128;
[x, y] = size(I); % declare image size array
Original = [x, y];
Rotated_I = zeros(x,y); %declare size of array to store pixel
theta = 90;
for row = 1:y
for column = 1:x
x_original = (column - 128) * cos(theta) - (row - 128)*sin(theta);
y_original = (column - 128) * sin(theta) + (row - 128)*cos(theta); % reverse rotate
p = floor(x_original);
q = floor(y_original);
a = y_original - p;
b = x_original - q; %
Rotated_I(column, row) = (1-a)*((1-b)*Original(p,q)+b*Original(p,q+1))+a*((q-b)*Original(p+1,q)+b*Original(p+1,q+1)); % Find pixel using bilinear interpolation
end
end
imshow(Rotated_I);
I tried to rotate image using reverse rotate and bilinear interpolation, but only i see is error message. It says "the first index exceeds array". Is there anything wrong in my code?

Here is a working version with a number of changes. The main difference is that it checks whether a coordinate exists in the original image before adding that to the rotate image. This allows for arbitrary rotations, like 45 degrees. Also, images in MATLAB have y as the first dimension and x as the second, so are accessed as I(y, x) or I(row, column).
clear
I = imread('256.jpg');
% imshow(I);
center = 128;
[y, x] = size(I); % in MATLAB, images are y-by-x in size (ie. y is dimension 1)
Original = I; % Original needs to be the image I
Rotated_I = zeros(y, x);
theta = 90;
for row = 1:y
for column = 1:x
x_original = (column - center) * cosd(theta) - (row - center)*sind(theta) + center; % theta is in degrees so use cosd and sind
y_original = (column - center) * sind(theta) + (row - center)*cosd(theta) + center; % also add center back on
p = floor(y_original); % x_original and y_original were swapped here
q = floor(x_original); % x_original and y_original were swapped here
a = y_original - p;
b = x_original - q;
% check if the coordinate is in the original image to prevent errors
if p > 0 && p <= y && q > 0 && q <= x
Rotated_I(row, column) = Rotated_I(row, column) + (1-a)*(1-b)*Original(p,q);
end
if p > 0 && p <= y && q+1 > 0 && q+1 <= x
Rotated_I(row, column) = Rotated_I(row, column) + (1-a)*b*Original(p,q+1);
end
if p+1 > 0 && p+1 <= y && q > 0 && q <= x
Rotated_I(row, column) = Rotated_I(row, column) + a*(1-b)*Original(p+1,q);
end
if p+1 > 0 && p+1 <= y && q+1 > 0 && q+1 <= x
Rotated_I(row, column) = Rotated_I(row, column) + a*b*Original(p+1,q+1);
end
end
end
% convert to uint image so it displays properly (double expects values from 0 to 1)
imshow(uint8(Rotated_I));

I do not know if you necessarily want to have your own implementation or not. But if not, you could always use imrotate:
Rotated_I = imrotate(I, 90, 'bilinear', 'crop');
90 => Degrees of rotation
'bilinear' => Bilinear interpolation (alternatives: nearest, bicubic)
'crop' => Maintain the pixel size of the rotated image the same as the input image
imrotate is part of the Image Processing Toolbox.

Related

Kaczmarz animation

i am asking for help.. I want to animate the Kaczmarz method on Matlab. It's method allows to find solution of system of equations by the serial projecting solution vector on hyperplanes, which which is given by the eqations of system.
And i want make animation of this vector moving (like the point is going on the projected vectors).
%% System of equations
% 2x + 3y = 4;
% x - y = 2;
% 6x + y = 15;
%%
A = [2 3;1 -1; 6 1];
f = [4; 2; 15];
resh = pinv(A)*f
x = -10:0.1:10;
e1 = (1 - 2*x)/3;
e2 = (x - 2);
e3 = 15 - 6*x;
plot(x,e1)
grid on
%
axis([0 4 -2 2])
hold on
plot(x,e2)
hold on
plot(x,e3)
hold on
precision = 0.001; % точность
iteration = 100; % количество итераций
lambda = 0.75; % лямбда
[m,n] = size(A);
x = zeros(n,1);
%count of norms
for i = 1:m
nrm(i) = norm(A(i,:));
end
for i = 1:1:iteration
j = mod(i-1,m) + 1;
if (nrm(j) <= 0), continue, end;
predx = x;
x = x + ((f(j) - A(j,:)*x)*A(j,:)')/(nrm(j))^2;
p = plot(x);
set(p)
%pause 0.04;
hold on;
if(norm(predx - x) <= precision), break, end
end
I wrote the code for this method, by don't imagine how make the animation, how I can use the set function.
In your code there are a lot of redundant and random pieces. Do not call hold on more than once, it does nothing. Also set(p) does nothing, you want to set some ps properties to something, then you use set.
Also, you are plotting the result, but not the "change". The change is a line between the previous and current, and that is the only reason you'd want to have a variable such as predx, to plot. SO USE IT!
Anyway, this following code plots your algorithm. I added a repeated line to plot in green and then delete, so you can see what the last step does. I also changed the plots in the begging to just plot in red so its more clear what is each of the things.
Change your loop for:
for i = 1:1:iteration
j = mod(i-1,m) + 1;
if (nrm(j) <= 0), continue, end;
predx = x;
x = x + ((f(j) - A(j,:)*x)*A(j,:)')/(nrm(j))^2;
plot([predx(1) x(1)],[predx(2) x(2)],'b'); %plot line
c=plot([predx(1) x(1)],[predx(2) x(2)],'g'); %plot it in green
pause(0.1)
children = get(gca, 'children'); %delete the green line
delete(children(1));
drawnow
% hold on;
if(norm(predx - x) <= precision), break, end
end
This will show:

Inverse image rotation

I have written the following code without any Matlab built-in functions to rotate an image. I tried to write another loop to invert the rotation. the image does rotate back but I still get the size of the previously rotated image. How can I get rid of the black parts in the image?
INPUT_IMAGE = 'forest.png';
img_in=double(imread(INPUT_IMAGE))./255;
h=size(img_in,1);
w=size(img_in,2);
R=[cos(th) -sin(th) 0 ; sin(th) cos(th) 0 ; 0 0 1];
T=[1 0 (-w/2) ; 0 1 (-h/2) ; 0 0 1];
F=inv(T)*R*T;
img_out=zeros(h,w,3);
%Rotate image
for i=1:w
for j=1:h
a = [i ; j ; 1];
b = inv(F) * a;
x = b(1)/b(3);
y = b(2)/b(3);
x = floor(x);
y = floor(y);
if (x>0 & x<=W & j>0 & j<=H)
img_out(y,x,:)=img_in(j,i,:);
end
end
end
img_out2=zeros(h,w,3);
%invert rotation
for i=1:w
for j=1:h
a = [i ; j ; 1];
b = F * a;
x = b(1)/b(3);
y = b(2)/b(3);
x = floor(x);
y = floor(y);
if (x>0 & x<=W & j>0 & j<=H)
img_out2(y,x,:)=img_out(j,i,:);
end
end
end
The result:
I know the image has black gaps due to the forward mapping but I'm not concerned about that as I'm trying to implement a code without built-in functions that would only rotate the image back so I can calculate the error.
Instead of iterating the source image, inverse transformation matrix, and iterate destination image.
Iterating destination image guarantees to have no holes (each pixel gets a value).
The code you have posted is not working, please fix it...
I based my answer on your previous post: Matlab image rotation
I used 'peppers.png' instead of 'forest.png' (I can't find 'forest.png', next time, please add the image to your post).
The example code do the following:
Rotate input image (You may treat it as "reverse transformation").
Rotate result image back (using inverse transformation matrix).
Display absolute difference of original image and result image.
close all;
clear all;
img_in = 'peppers.png';
img_in =double(imread(img_in))./255;
orig_in = img_in;
h=size(img_in,1);
w=size(img_in,2);
th = pi/4;
R=[cos(th) -sin(th) 0 ; sin(th) cos(th) 0 ; 0 0 1];
T=[1 0 (-w/2) ; 0 1 (-h/2) ; 0 0 1];
F=inv(T)*R*T;
img_out=zeros(h,w,3);
%Rotate image
for i=1:w
for j=1:h
x = [i ; j ; 1];
y = F * x;
a = y(1)/y(3);
b = y(2)/y(3);
a = round(a);
b = round(b);
if (a>0 && a<=w && b>0 && b<=h)
img_out(j,i,:)=img_in(b,a,:);
end
end
end
figure;imshow(img_out);
%Rotate back
%---------------------------------------------------------
img_in = img_out;
img_out = zeros(h,w,3);
%Inverse transformation matrix.
F = inv(F);
%Rotate image (back)
for i=1:w
for j=1:h
x = [i ; j ; 1];
y = F * x;
a = y(1)/y(3);
b = y(2)/y(3);
a = round(a);
b = round(b);
if (a>0 && a<=w && b>0 && b<=h)
img_out(j,i,:)=img_in(b,a,:);
end
end
end
figure;imshow(img_out);
img_diff = abs(orig_in - img_out);
figure;imshow(img_diff);
img_diff image:

Find area of two overlapping circles using monte carlo method

Actually i have two intersecting circles as specified in the figure
i want to find the area of each part separately using Monte carlo method in Matlab .
The code doesn't draw the rectangle or the circles correctly so
i guess what is wrong is my calculation for the x and y and i am not much aware about the geometry equations for solving it so i need help about the equations.
this is my code so far :
n=1000;
%supposing that a rectangle will contain both circles so :
% the mid point of the distance between 2 circles will be (0,6)
% then by adding the radius of the left and right circles the total distance
% will be 27 , 11 from the left and 16 from the right
% width of rectangle = 24
x=27.*rand(n-1)-11;
y=24.*rand(n-1)+2;
count=0;
for i=1:n
if((x(i))^2+(y(i))^2<=25 && (x(i))^2+(y(i)-12)^2<=100)
count=count+1;
figure(2);
plot(x(i),y(i),'b+')
hold on
elseif(~(x(i))^2+(y(i))^2<=25 &&(x(i))^2+(y(i)-12)^2<=100)
figure(2);
plot(x(i),y(i),'y+')
hold on
else
figure(2);
plot(x(i),y(i),'r+')
end
end
Here are the errors I found:
x = 27*rand(n,1)-5
y = 24*rand(n,1)-12
The rectangle extents were incorrect, and if you use rand(n-1) will give you a (n-1) by (n-1) matrix.
and
first If:
(x(i))^2+(y(i))^2<=25 && (x(i)-12)^2+(y(i))^2<=100
the center of the large circle is at x=12 not y=12
Second If:
~(x(i))^2+(y(i))^2<=25 &&(x(i)-12)^2+(y(i))^2<=100
This code can be improved by using logical indexing.
For example, using R, you could do (Matlab code is left as an excercise):
n = 10000
x = 27*runif(n)-5
y = 24*runif(n)-12
plot(x,y)
r = (x^2 + y^2)<=25 & ((x-12)^2 + y^2)<=100
g = (x^2 + y^2)<=25
b = ((x-12)^2 + y^2)<=100
points(x[g],y[g],col="green")
points(x[b],y[b],col="blue")
points(x[r],y[r],col="red")
which gives:
Here is my generic solution for any two circles (without any hardcoded value):
function [ P ] = circles_intersection_area( k1, k2, N )
%CIRCLES_INTERSECTION_AREA Summary...
% Adnan A.
x1 = k1(1);
y1 = k1(2);
r1 = k1(3);
x2 = k2(1);
y2 = k2(2);
r2 = k2(3);
if sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)) >= (r1 + r2)
% no intersection
P = 0;
return
end
% Wrapper rectangle config
a_min = x1 - r1 - 2*r2;
a_max = x1 + r1 + 2*r2;
b_min = y1 - r1 - 2*r2;
b_max = y1 + r1 + 2*r2;
% Monte Carlo algorithm
n = 0;
for i = 1:N
rand_x = unifrnd(a_min, a_max);
rand_y = unifrnd(b_min, b_max);
if sqrt((rand_x - x1)^2 + (rand_y - y1)^2) < r1 && sqrt((rand_x - x2)^2 + (rand_y - y2)^2) < r2
% is a point in the both of circles
n = n + 1;
plot(rand_x,rand_y, 'go-');
hold on;
else
plot(rand_x,rand_y, 'ko-');
hold on;
end
end
P = (a_max - a_min) * (b_max - b_min) * n / N;
end
Call it like: circles_intersection_area([-0.4,0,1], [0.4,0,1], 10000) where the first param is the first circle (x,y,r) and the second param is the second circle.
Without using For loop.
n = 100000;
data = rand(2,n);
data = data*2*30 - 30;
x = data(1,:);
y = data(2,:);
plot(x,y,'ro');
inside5 = find(x.^2 + y.^2 <=25);
hold on
plot (x(inside5),y(inside5),'bo');
hold on
inside12 = find(x.^2 + (y-12).^2<=144);
plot (x(inside12),y(inside12),'g');
hold on
insidefinal1 = find(x.^2 + y.^2 <=25 & x.^2 + (y-12).^2>=144);
insidefinal2 = find(x.^2 + y.^2 >=25 & x.^2 + (y-12).^2<=144);
% plot(x(insidefinal1),y(insidefinal1),'bo');
hold on
% plot(x(insidefinal2),y(insidefinal2),'ro');
insidefinal3 = find(x.^2 + y.^2 <=25 & x.^2 + (y-12).^2<=144);
% plot(x(insidefinal3),y(insidefinal3),'ro');
area1=(60^2)*(length(insidefinal1)/n);
area3=(60^2)*(length(insidefinal2)/n);
area2= (60^2)*(length(insidefinal3)/n);

How can i convert image velocity to object velocity in matlab?

I am using for my project the "LucasKanade" code in matlab. It gives me as output 2 matrices (u and v). These are(i believe so) the velocities of the image in the x and y axes respectively. Now how can i convert these velocities to object velocities(eg in meters/second)?
Thanks in advance
"LucasKanade" code:
function [u, v] = LucasKanade(im1, im2, windowSize);
%LucasKanade lucas kanade algorithm, without pyramids (only 1 level);
%REVISION: NaN vals are replaced by zeros
[fx, fy, ft] = ComputeDerivatives(im1, im2);
u = zeros(size(im1));
v = zeros(size(im2));
halfWindow = floor(windowSize/2);
for i = halfWindow+1:size(fx,1)-halfWindow
for j = halfWindow+1:size(fx,2)-halfWindow
curFx = fx(i-halfWindow:i+halfWindow, j-halfWindow:j+halfWindow);
curFy = fy(i-halfWindow:i+halfWindow, j-halfWindow:j+halfWindow);
curFt = ft(i-halfWindow:i+halfWindow, j-halfWindow:j+halfWindow);
curFx = curFx';
curFy = curFy';
curFt = curFt';
curFx = curFx(:);
curFy = curFy(:);
curFt = -curFt(:);
A = [curFx curFy];
U = pinv(A'*A)*A'*curFt;
u(i,j)=U(1);
v(i,j)=U(2);
end;
end;
u(isnan(u))=0;
v(isnan(v))=0;
%u=u(2:size(u,1), 2:size(u,2));
%v=v(2:size(v,1), 2:size(v,2));
%%
function [fx, fy, ft] = ComputeDerivatives(im1, im2);
%ComputeDerivatives Compute horizontal, vertical and time derivative
% between two gray-level images.
if (size(im1,1) ~= size(im2,1)) | (size(im1,2) ~= size(im2,2))
error('input images are not the same size');
end;
if (size(im1,3)~=1) | (size(im2,3)~=1)
error('method only works for gray-level images');
end;
fx = conv2(im1,0.25* [-1 1; -1 1]) + conv2(im2, 0.25*[-1 1; -1 1]);
fy = conv2(im1, 0.25*[-1 -1; 1 1]) + conv2(im2, 0.25*[-1 -1; 1 1]);
ft = conv2(im1, 0.25*ones(2)) + conv2(im2, -0.25*ones(2));
% make same size as input
fx=fx(1:size(fx,1)-1, 1:size(fx,2)-1);
fy=fy(1:size(fy,1)-1, 1:size(fy,2)-1);
ft=ft(1:size(ft,1)-1, 1:size(ft,2)-1);

finding max width of blob

I'm trying to find the maximum width of the blob by counting the number of white pixels of each line in the blob I wrote the code, however, it never stops. how it can be fixed?
For y = 0 To bmp.ScaleHeight - 1
sum = 0
For x = 0 To bmp.ScaleWidth - 1
pixel1 = bmp.Point(x, y)
If pixel1 = vbWhite Then
sum = sum + 1
If bmp.Point(x + 1, y) = vbBlack Then
If sum > max Then
Lmax = sum
y1 = y
x2 = x
x1 = x2 - sum
End If
End If
End If
Next x
Next y

Resources