I would like to rotate a non-squared image with Matlab:
- without using the
imrotate
function, since it is part of the Image Processing Toolbox, - with the
loose
parameter, which means the size of the output differs from the size of the input image, - and with a not too slow function compared to
imrotate
.
I have already found a function in order to do this (just replace imshow
and bestblk
with your own functions in order not to use the toolbox), yet it is really slow for large images. My approach would try to avoid making loops and relying as much as possible on interp2
.
The signature of the function would be:
imOutput = my_imrotate(imInput, theta_degres, interpolation, bbox)
where:
interpolation
would bebilinear
,bicubic
ornearest
,bbox
would becrop
, orloose
.
Crop
I already have a good result with the crop
parameter, but I cannot manage to find the offset for the loose
parameter.
Here is the code for the crop
parameter, where Z
is the input and Zi
is the output:
Z = double(imInput);
sz = size(Z);
[X,Y] = meshgrid(1:sz(2), 1:sz(1));
%# Center
c = sz(end:-1:1)/2;
%# Angle
t = theta_degres*pi/180;
%# Rotation
ct = cos(t);
st = sin(t);
Xi = c(1) + ct*(X-c(1))-st*(Y-c(2));
Yi = c(2) + st*(X-c(1))+ct*(Y-c(2));
%# Rotation
Zi = interp2(X, Y, Z, Xi, Yi);
Loose
My idea is to compute the size of a frame which would contain the original image as well as the rotated image, and then:
- pad the original image so as to have an image whose size is the size of the frame,
- use
interp2
on the padded image, - crop the resulting image so as to have the rotated image without the remains of the padding.
To get the size of the rotated image with the loose
parameter, I compute the rotation_matrix
and call rotate_points
on the coordinates of the corners p
of the input image:
rotation_matrix = [ct, -st; st, ct];
rotate_points = @(p) bsxfun(@plus, c', rotation_matrix * bsxfun(@minus, p, c)')';
Any help would be highly appreciated.
Edit: Using the solution provided in the answer below, and the following code, it seems to work quite right:
%# See the answer below
[sz1,sz2] = size(Z);
sz1New = sz1*cos(t)+sz2*sin(t);
sz2New = sz2*cos(t)+sz1*sin(t);
[Xi,Yi] = meshgrid(-(sz2New-1)/2:(sz2New-1)/2,-(sz1New-1)/2:(sz1New-1)/2);
%# now all that's left is rotating Xi,Yi - I have already subtracted the center
%# My little piece of additional code
Xii = (1+sz2)/2 + ct*Xi - st*Yi;
Yii = (1+sz1)/2 + st*Xi + ct*Yi;
Zi = interp2(X, Y, Z, Xii, Yii);