Image rotation by Matlab without using imrotate

The reason you have holes in your image is because you are computing the location in imagerot of each pixel in imagepad. You need to do the computation the other way around. That is, for each pixel in imagerot interpolate in imagepad. To do this, you just need to apply the inverse transform, which in the case of a rotation matrix is just the transpose of the matrix (just change the sign on each sin and translate the other way).

Loop over pixels in imagerot:

imagerot=zeros(size(imagepad)); % midx and midy same for both

for i=1:size(imagerot,1)
    for j=1:size(imagerot,2)

         x= (i-midx)*cos(rads)+(j-midy)*sin(rads);
         y=-(i-midx)*sin(rads)+(j-midy)*cos(rads);
         x=round(x)+midx;
         y=round(y)+midy;

         if (x>=1 && y>=1 && x<=size(imagepad,2) && y<=size(imagepad,1))
              imagerot(i,j)=imagepad(x,y); % k degrees rotated image         
         end

    end
end

Also note that your midx and midy need to be calculated with size(imagepad,2) and size(imagepad,1) respectively, since the first dimension refers to the number of rows (height) and the second to width.

NOTE: The same approach applies when you decide to adopt an interpolation scheme other than nearest neighbor, as in Rody’s example with linear interpolation.

EDIT: I’m assuming you are using a loop for demonstrative purposes, but in practice there is no need for loops. Here’s an example of nearest neighbor interpolation (what you are using), keeping the same size image, but you can modify this to produce a larger image that includes the whole source image:

imagepad = imread('peppers.png');
[nrows ncols nslices] = size(imagepad);
midx=ceil((ncols+1)/2);
midy=ceil((nrows+1)/2);

Mr = [cos(pi/4) sin(pi/4); -sin(pi/4) cos(pi/4)]; % e.g. 45 degree rotation

% rotate about center
[X Y] = meshgrid(1:ncols,1:nrows);
XYt = [X(:)-midx Y(:)-midy]*Mr;
XYt = bsxfun(@plus,XYt,[midx midy]);

xout = round(XYt(:,1)); yout = round(XYt(:,2)); % nearest neighbor!
outbound = yout<1 | yout>nrows | xout<1 | xout>ncols;
zout=repmat(cat(3,1,2,3),nrows,ncols,1); zout=zout(:);
xout(xout<1) = 1; xout(xout>ncols) = ncols;
yout(yout<1) = 1; yout(yout>nrows) = nrows;
xout = repmat(xout,[3 1]); yout = repmat(yout,[3 1]);
imagerot = imagepad(sub2ind(size(imagepad),yout,xout,zout(:))); % lookup
imagerot = reshape(imagerot,size(imagepad));
imagerot(repmat(outbound,[1 1 3])) = 0; % set background value to [0 0 0] (black)

To modify the above to linear interpolation, compute the 4 neighboring pixels to each coordinate in XYt and perform a weighted sum using the fractional components product as the weights. I’ll leave that as an exercise, since it would only serve to bloat my answer further beyond the scope of your question. 🙂

Leave a Comment