自己写的Matlab 旋转+双线性插值图像函数效果图:
源码:
clear all;
I = imread('original.jpg');
[Height,Width,RGB] = size(I);
II = I;%当角度为0时直接输出
%本程序是以左上角为坐标原点
%angle_j是旋转角度,正值是按顺时针旋转,负值时按逆时针旋转
angle_j = 181;
%angle是弧度
angle = 2*pi*angle_j/360;
%将angle转成正值
while(angle < 0)
angle = 2 * pi + angle;
end
%约束在0-2π内
while(angle > 2 * pi)
angle = angle - 2 * pi;
end
%tag是判断下面的while循环有没有执行过
tag = 0;
while(angle > 0)
%超过90度的旋转,都先旋转90度,直到角度在0°-90°之间
%原理是旋转90度整数倍时,信息是不丢失的
if angle >= pi/2
a = pi/2;
angle = angle - pi/2;
elseif 0 < angle < pi/2
a = angle;
angle = 0;
end
if tag == 0
tag = 1;
else
I = II;
[Height,Width,RGB] = size(I);%在旋转后的图像上继续旋转,从而实现大于90°的旋转
end
%正向变换用
sina = sin(a);
cosa = cos(a);
%逆向变换用_m == _minus
sina_m = sin(-a);
cosa_m = cos(-a);
%旋转后图像的长度和宽度
II_height = round(sina * Width + cosa * Height);
II_width = round(sina * Height + cosa * Width);
II = ones(II_height,II_width,3);
%先转成unit8。
或者下面赋值0-1规划一下。
否则imshow全是白色。
II = im2uint8(II);
%%%%%%%%%%%%%%%%%%%%正向映射%%%%%%%%%%%%%%%%%%%%%%%%
for i = 1 : Height
for j = 1 : Width
%旋转后点的坐标
New_height = round( i * cosa + j * sina);
New_width = round(-i * sina + j * cosa + (Height + 1) *
sina );% + (Height + 1) * sina + 0.5是防止y坐标为非正
II(New_height,New_width,:) = I(i,j,:);
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%正向映射有个bug,当角度与pi/4的整数倍相差很小时,在图片边缘容易出现一条黑边
%%%%%%%%%%%%%%%%%%%%%%逆向映射%%%%%%%%%%%%%%%%%%%%%%
for i = 1 : II_height
for j = 1 : II_width
if II(i,j,:) == 255 %如果全白,就是信息丢失的点
Ori_height = ( i * cosa_m + (j-1) * sina_m) + Height * sina * sina;%Ori_ == Original
%H eight * sina * sina防止x坐标为负
Ori_width = (-i * sina_m + (j-1) * cosa_m) - Height * cosa * sina;%(j - 1) 是为了修正正向映射的 + 1偏差
if Ori_height > 1 && Ori_height < Height && Ori_width > 1 && Ori_width < Width %如果逆映射后在I原图内部
II(i,j,:) = (...%--------------------------------------------------------
I(floor(Ori_height),floor(Ori_width),:)... %top-left点
* abs(Ori_width -
ceil(Ori_width)) ... %乘以权重,由于权重和为1,就不用除了
+
I(floor(Ori_height),ceil(Ori_width),:)... %top-right点
* abs(Ori_width -
floor(Ori_width))... %乘以权重
)...%--------------------------------------------------------
* abs(Ori_height -
ceil(Ori_height)) ... %第二次取权重
+ ...
(...%--------------------------------------------------------
I(ceil(Ori_height),floor(Ori_width),:)... %bottom-left点
* abs(Ori_width - ceil(Ori_width))...
+
I(ceil(Ori_height),ceil(Ori_width),:)... %bottom-right点
* abs(Ori_width - floor(Ori_width))...
)...%--------------------------------------------------------
* abs(Ori_height -
floor(Ori_height)); %第二次取权重
%elseif Ori_height >= 1 && Ori_height < Height &&
Ori_width > 1 && Ori_width < Width %如果逆映射后在I原图边缘
end
end
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end %---while循环的end
figure;
subplot(1,3,1);imshow('original.jpg');title('original');
subplot(1,3,2);imshow(II);title('Myimrotate');
subplot(1,3,3),imshow(255 - imrotate(255-imread('original.jpg'),-
angle_j,'bilinear'));title('System imrotate');。