Sorry for my bad English.
I'm learning Matlab for image processing so I tried to clone the default "imrotate" function.
The first version I wrote involved using for-loop to traverse the whole matrix so it's very very slow.
Then I read this thread: Image rotation by Matlab without using imrotate and try to vectorize my program and it became "much" faster.
But it is still very slow compared to the default imrotate implementation consuming more than 1 second to rotate the image(resolution is 1920x1080), while the default implementation do the job in less than 50 millisecond.
So I wonder there would be still something wrong with my code or it is "normal" in matlab? Here is my code:
(P.S. there is some ugly code (value11=...;value12=...value21=...) because I am not familiar with Matlab and unable to figure out shorter code not using loop.
function result=my_imRotate(image,angel,method)
function result=my_imRotateSingleChannel(image,angel,method)
angel=-angel/180*pi; %transform the angel from deg to rad
[height,width]=size(image); %get the image size
trMatrix=[cos(angel),-sin(angel);sin(angel),cos(angel)]; %the transformation matrix
imgSizeVec=[width,height;width,-height]; %the "size vector" to be transformed to caluclate the new size
newImgSizeVec=imgSizeVec*trMatrix;
newWidth=ceil(max(newImgSizeVec(:,1)));
newHeight=ceil(max(newImgSizeVec(:,2))); %caluculate the new size
[oldX,oldY]=meshgrid(1:newWidth,1:newHeight);
oldX=oldX-newWidth/2;
oldY=oldY-newHeight/2;
temp=[oldX(:) oldY(:)]*trMatrix;
oldX=temp(:,1);
oldY=temp(:,2);
oldX=oldX+width/2;
oldY=oldY+height/2;
switch(method)
case 'nearest'
oldX=round(oldX);
oldY=round(oldY);
condition=( oldX>=1 & oldX<=width & oldY>=1 & oldY<=height );
result(condition)=image((oldX(condition)-1)*height+oldY(condition));
result(~condition)=0;
result=reshape(result,newHeight,newWidth);
case 'bilinear'
x1=floor(oldX);
x2=x1+1;
y1=floor(oldY);
y2=y1+1;
condition11=(x1>=1&x1<=width&y1>=1&y1<=height);
condition12=(x1>=1&x1<=width&y2>=1&y2<=height);
condition21=(x2>=1&x2<=width&y1>=1&y1<=height);
condition22=(x2>=1&x2<=width&y2>=1&y2<=height);
value11(condition11)=double(image((x1(condition11)-1)*height+y1(condition11)));
value12(condition12)=double(image((x1(condition12)-1)*height+y2(condition12)));
value21(condition21)=double(image((x2(condition21)-1)*height+y1(condition21)));
value22(condition22)=double(image((x2(condition22)-1)*height+y2(condition22)));
value11(~condition11)=0;
value12(~condition12)=0;
value21(~condition21)=0;
value22(~condition22)=0;
result=uint8(value22.'.*(oldX-x1).*(oldY-y1)+value11.'.*(x2-oldX).*(y2-oldY)+value21.'.*(oldX-x1).*(y2-oldY)+value12.'.*(x2-oldX).*(oldY-y1));
result=reshape(result,newHeight,newWidth);
otherwise
disp('Sorry, unsupported algorithm. Only nearest/bilinear is supported.');
end
end
imageInfo=size(image);
imageType=size(imageInfo);
if(imageType(2)==2)
result=my_imRotateSingleChannel(image,angel,method);
elseif(imageType(2)==3&&imageInfo(3)==3)
temp=my_imRotateSingleChannel(image(:,:,1),angel,method);
[newHeight,newWidth]=size(temp);
result=temp(:);
temp=my_imRotateSingleChannel(image(:,:,2),angel,method);
result=[result temp(:)];
temp=my_imRotateSingleChannel(image(:,:,2),angel,method);
result=[result temp(:)];
result=reshape(result,newHeight,newWidth,3);
else
disp('Sorry, unsupported input matrix. Only grey/rgb image is supported.');
end
end