Reputation: 392
I am trying to do my own algorithm of rotating an image without using imrotate.
clear all
img1 = imread('image1.jpg');imshow(img1);
[m,n,p]=size(img1);
thet = pi/6;
m1=round(m*1.5);
n1=round(n*1.5);
rotatedImg = zeros(m1,n1);
for i=1:m
for j=1:n
t = uint16((i)*cos(thet)-(j)*sin(thet)+m+100);
s = uint16((i)*sin(thet)+(j)*cos(thet));
if i>0 && j>0 && i<=m && j<=n
try rotatedImg(t,s,1)=img1(i,j,1);
catch
a=1;
end
end
end
end
figure;
imshow(rotatedImg);
However for some reasons, at a certain angle, some parts of the image is clipped, so not the whole image is on the window. I can't seem to work out how to do it properly. It seems like i need to make the window bigger each time at different angle so the image won't be clipped.
Also my image turns out to be full of black spots which I assume I need to do some sort of interpolation. How do I go about that?
*The image I'm using is (https://i.sstatic.net/kDdx5.jpg) and rotating with these angles - pi/6, pi/2 , ((pi/6)*4) *
Upvotes: 0
Views: 542
Reputation: 6060
Well, there are two issues:
The rotation as always around the origin. That's the reason you need to adjust the offset (100) for each angle. Better solution is to rotate around the image center.
You are not doing any kind of interpolation. While that is not the reason per se, it could happen that you don't hit every pixel in the destination image due to rounding errors. It's better to iterate through the destination image and grab the correct pixel from the source.
Here is my solution:
clear all
img1 = imread('ngc6543a.jpg');
imshow(img1);
[m,n,p]=size(img1);
thet = pi/6;
m1=round(m*1.5);
n1=round(n*1.5);
rotatedImg = zeros(m1,n1, 3, 'uint8');
tic
for i=1:m1
for j=1:n1
p = [i; j] - [m1/2; n1/2];
source = [cos(thet), sin(thet); -sin(thet), cos(thet)] * p;
source = source + [m/2; n/2];
t = int16(source(1));
s = int16(source(2));
if t>0 && s>0 && t<=m && s<=n
rotatedImg(i,j,:) = img1(t,s,:);
end
end
end
toc
figure;
imshow(rotatedImg);
And while that looks okay, I'd definitely recommend bilinear interpolation.
I see, so you images are not quadratic. IN that case, it is not sufficient to callculate the new dimensions as old*1.5, but more exact (or more generous).
Here is the final solution that should work for all angles and arbitary images. Matlab is a bit fiddly because the indexing is (y,x) but otherwise the code should be fine.
clear all
img1 = imread('kDdx5.jpg');
imshow(img1);
[orgHeight,orgWidth,p]=size(img1);
thet = pi/7;
matrix = [cos(thet), -sin(thet); sin(thet), cos(thet)];
p1 = abs(matrix * [orgWidth/2; orgHeight/2]);
p2 = abs(matrix * [orgWidth/2; -orgHeight/2]);
corner = [max(p1(1), p2(1)); max(p1(2), p2(2))];
newWidth = ceil(2*corner(1));
newHeight = ceil(2*corner(2));
rotatedImg = zeros(newHeight, newWidth, 3, 'uint8');
tic
for i=1:newWidth
for j=1:newHeight
p = [i; j] - [newWidth/2; newHeight/2];
source = matrix * p;
source = source + [orgWidth/2; orgHeight/2;];
t = int16(source(1));
s = int16(source(2));
if t>0 && s>0 && s<=orgHeight && t<=orgWidth
rotatedImg(j,i,:) = img1(s,t,:);
end
end
end
toc
figure;
imshow(rotatedImg);
Upvotes: 2