不使用imrotate实现图像旋转(点操作实现)
不使用imrotate函数来实现图像旋转,这其中的原理就是使用点操作变换来实现的。
一般的我们实现图像旋转首先会想到将图像的旋转中心点平移到左上角的原点,经过旋转和平移的操作可以得到旋转之后的图像。
但是,我们如果直接将原图像平移、旋转、平移得到的新图像是有问题的,新图像中会有很多点没有值,使得图像像个蜂窝煤。这里需要使用逆向映射、最邻近插值(或者双线性插值)方法来解决。
逆向映射、最邻近插值(或者双线性插值)(参考资料,自行看懂):
[https://blog.csdn.net/lkj345/article/details/50555870][1]
[http://www.cnblogs.com/mlv5/archive/2012/02/02/2336321.html][2]
[https://blog.csdn.net/glorydream2015/article/details/44873703][3]
[https://www.cnblogs.com/linkr/p/3630902.html][4]
附上我的代码:
%图像旋转
clear;
clc;
src = imread('1.png');
theta = 30;
angle = 30 * pi / 180;
figure;
imshow(src);
%原图片y x对应的r c,计算旋转角度之后新图像的r_new c_new,角度为钝角时会有负值,所以需要加上abs
[r,c,k] = size(src);
r_new = round(abs(r*cos(angle)) + abs(c*sin(angle)));
c_new = round(abs(r*sin(angle)) + abs(c*cos(angle)));
dst = zeros(r_new,c_new);%构造新的图像
dst1 = zeros(r_new,c_new);%构造新的图像
%反向映射,将图像看成从新图像平移,旋转,再平移的结果得到原图像
%而不是从原图像平移旋转平移得到新图像,这样可以解决某些点映射为空的问题
translation1 = [1 0 -c_new/2;0 1 -r_new/2;0 0 1];%新图像的中心点平移到左上角的原点
rotate = [cos(angle) -sin(angle) 0;sin(angle) cos(angle) 0;0 0 1];%旋转angle角度
translation2 = [1 0 c/2;0 1 r/2;0 0 1];%从原点平移回去
%反向映射 从新图像的每个像素点匹配
for i = 1:r_new
for j = 1:c_new
%从新图像映射到原图像中去如果不在原图像中,新图像为0,如果在的,将该点的最邻近取值赋值过来
P = translation2 * (rotate * (translation1* [j;i;1] ));%P(1)为x的值 P(2)为y的值
if(round(P(1))>0 && round(P(1))<c && round(P(2))>0 && round(P(2))<r)
dst(i,j,1) = src(round(P(2)),round(P(1)),1);%取src的最邻近值
dst(i,j,2) = src(round(P(2)),round(P(1)),2);
dst(i,j,3) = src(round(P(2)),round(P(1)),3);
else
dst(i,j) = 0;
end
end
end
figure;
imshow(dst/256);
title('最邻近插值');
%双线性插值算法
for i = 1:r_new
for j = 1:c_new
%从新图像映射到原图像中去如果不在原图像中,新图像为0,如果在的,将该点的最邻近取值赋值过来
P = translation2 * (rotate * (translation1* [j;i;1] ));%P(1)为x的值 P(2)为y的值
x = P(1);
y = P(2);
%四个点进行双线性插值
x_top = ceil(x);
x_bottom = floor(x);
y_top = ceil(y);
y_bottom = floor(y);
%判断条件相应的改变
if(y_top < r && y_bottom >0 && x_bottom > 0 && x_top <c)
%m(i,j) = K(round(P(2,1)),round(P(1,1)));%yx
dst1(i,j,1) = src(y_bottom,x_bottom,1)*(x_top - x)*(y_top - y) + src(y_top,x_bottom,1)*(x_top - x)*(y - y_bottom) + src(y_bottom,x_top,1)*(x - x_bottom)*(y_top - y) + src(y_top,x_top,1)*(x - x_bottom)*(y - y_bottom);
dst1(i,j,2) = src(y_bottom,x_bottom,2)*(x_top - x)*(y_top - y) + src(y_top,x_bottom,2)*(x_top - x)*(y - y_bottom) + src(y_bottom,x_top,2)*(x - x_bottom)*(y_top - y) + src(y_top,x_top,2)*(x - x_bottom)*(y - y_bottom);
dst1(i,j,3) = src(y_bottom,x_bottom,3)*(x_top - x)*(y_top - y) + src(y_top,x_bottom,3)*(x_top - x)*(y - y_bottom) + src(y_bottom,x_top,3)*(x - x_bottom)*(y_top - y) + src(y_top,x_top,3)*(x - x_bottom)*(y - y_bottom);
else
dst1(i,j) = 0;
end
end
end
figure;
imshow(dst1/256);
title('双线性插值');