drifterOcean19
drifterOcean19

Reputation: 392

rotation image - different degrees

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

Answers (1)

DasKr&#252;melmonster
DasKr&#252;melmonster

Reputation: 6060

Well, there are two issues:

  1. 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.

  2. 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

Related Questions