工作:
抉择典型图像(football.jpg)为钻研对象
1. 显示原图像
2. 将图像旋转 45°并进行显示(不调用自带函数,利用矩阵变换)
原理:
(原文链接:https://blog.csdn.net/Bryan_Q…)
以坐标原点为核心旋转的原理
点 p 0绕坐标原点逆时针方向旋转 Θ 角度失去点 p 1
$$
\begin{bmatrix}
cos(θ) & -sinθ & 0\\
sinθ & cos(θ) & 0 \\
0 & 0 & 1
\end{bmatrix}
\begin{bmatrix}
x_0\\
y_0\\
1
\end{bmatrix}
=
\begin{bmatrix}
x_1\\
y_1\\
1
\end{bmatrix}
$$
以任意图形中心点为坐标原点旋转原理
(这合乎 MATLAB 的零碎空间坐标设置,绕核心旋转能够统一化几何变换问题,原点旋转解决具备个体化)
从上图可知,以任意图形核心为坐标原点旋转须要三步:
(1)将坐标系 I 变成坐标系 II
注:坐标系 I 合乎 MATLAB 的零碎空间坐标设置,坐标系 II 中,图形核心是坐标原点。
$$
\begin{bmatrix}
1 & 0 & -0.5w\\
0 & -1 & 0.5h \\
0 & 0 & 1
\end{bmatrix}
\begin{bmatrix}
XI\\
YI\\
1
\end{bmatrix}
=
\begin{bmatrix}
XII\\
YII\\
1
\end{bmatrix}
$$
(2)将坐标系 II 旋转 θ 角
$$
\begin{bmatrix}
cos(θ) & -sinθ & 0\\
sinθ & cos(θ) & 0 \\
0 & 0 & 1
\end{bmatrix}
\begin{bmatrix}
x_0\\
y_0\\
1
\end{bmatrix}
=
\begin{bmatrix}
x_1\\
y_1\\
1
\end{bmatrix}
$$
(3)将坐标系 II 变成坐标系 I
注:MATLAB 中只能以坐标系 I 的模式出现图像,只能显示其 x >0,y>0 的局部。
$$
\begin{bmatrix}
1 & 0 & 0.5nW\\
0 & -1 & 0.5nH \\
0 & 0 & 1
\end{bmatrix}
\begin{bmatrix}
XII\\
YII\\
1
\end{bmatrix}
=
\begin{bmatrix}
XI\\
YI\\
1
\end{bmatrix}
$$
从而将三步联合起来,能够失去以任意图像核心为坐标原地旋转,最初出现残缺图像的变换矩阵:
前向映射
$$
\begin{bmatrix}
1 & 0 & 0.5nW\\
0 & -1 & 0.5nH \\
0 & 0 & 1
\end{bmatrix}
\begin{bmatrix}
cos(θ) & -sinθ & 0\\
sinθ & cos(θ) & 0 \\
0 & 0 & 1
\end{bmatrix}
\begin{bmatrix}
1 & 0 & -0.5w\\
0 & -1 & 0.5h \\
0 & 0 & 1
\end{bmatrix}
\begin{bmatrix}
x_0\\
y_0\\
1
\end{bmatrix}
=
\begin{bmatrix}
x_1\\
y_1\\
1
\end{bmatrix}
$$
它的逆变换为:
后向映射
$$
\begin{bmatrix}
x_0\\
y_0\\
1
\end{bmatrix}
=
\begin{bmatrix}
1 & 0 & -0.5nW\\
0 & -1 & 0.5nH \\
0& 0 & 1
\end{bmatrix}
\begin{bmatrix}
cos(θ) & sin(θ) & 0\\
-sin(θ) & cos(θ) & 0 \\
0 & 0 & 1
\end{bmatrix}
\begin{bmatrix}
1 & 0 & 0.5w \\
0 & -1 & 0.5h\\
0& 0 & 1
\end{bmatrix}
\begin{bmatrix}
x_1\\
y_1\\
1
\end{bmatrix}
$$
向前映射和向后映射的区别
参考博客:[(4 条音讯) 图像变换——向前映射和向后映射_薇洛的打火机 -CSDN 博客](https://blog.csdn.net/glorydr…
总结:
MATLAB 编程实现
(1)MATLAB 自带函数实现图像任意角度旋转
旋转函数介绍:
B = imrotate(A,angle,method,bbox)
angle: 旋转角度,单位为度,逆正顺负。
method:指定插值办法,邻点插值、双线性插值、双三次插值,(默认邻点插值)
bbox:定义输入图像大小的边界框
I=imread('football.jpg');
I1=imrotate(I,-45); % 旋转 45°
I2=imrotate(I,-45,'crop'); % 旋转 45°,并剪切图像,使失去的图像和原图像大小统一
I3=imrotate(I,-45,'bilinear','crop');% 双线性插值法旋转 45°,并剪切图像,使失去的图像和原图像大小统一
figure,subplot(2,2,1),imshow(I);
title('srcImage');
subplot(2,2,2),imshow(I1);
title('I1');
subplot(2,2,3),imshow(I2);
title('I2');
subplot(2,2,4),imshow(I3);
title('I3');
(2)自编 myimrotate()函数实现图像任意角度旋转
function [A] = new_myimrotate(B,degree) % 定义旋转函数,degree 要旋转的角度
[h,w,d]=size(B); % 获取输出图像 B 的行(高)h、列(宽)w 和通道数 d, 为了旋转彩色图像所以有必要失去通道数 d
nH=round(h*abs(cosd(degree))+w*abs(sind(degree))); % 旋转图像后失去的新高度,“round()函数四舍五入“,“abs()函绝对值和复数的模”,“cosd()以度为单位的参数的余弦”nW=round(w*abs(cosd(degree))+h*abs(sind(degree))); % 旋转图像后失去的新宽度
A=zeros(nH,nW,d); % 定义生成指标图像的行列以及通道数
M1=[1 0 -0.5*nW;0 -1 0.5*nH;0 0 1]; % 坐标系变换矩阵 M1
M2=[cosd(degree) sind(degree) 0;-sind(degree) cosd(degree) 0;0 0 1]; % 角度旋转变换矩阵 M2,我用的是顺时针方向
M3=[1 0 0.5*w;0 -1 0.5*h;0 0 1]; % 坐标系变换矩阵 M3
for i=1:nW
for j=1:nH
temp=M1*M2*M3*[i;j;1]; % 失去旋转前的矩阵 temp
y=temp(2,1); %y 取矩阵 temp 的第一行第二列,y 对应 j,为高度
x=temp(1,1); %x 取矩阵 temp 的第一行第一列,x 对应 i,为宽度
y=round(y); %y 四舍五入取整, 邻近插值法
x=round(x); %x 四舍五入取整,邻近插值法
if(x>=1&&x<=w)&&(y>=1&&y<=h) % 判断的失去的 (x,y) 点是否在原图像上
A(j,i,:)=B(y,x,:); % 将原图像的像素点赋值给对应的旋转后图像上的点
end %(”会纳闷为啥不是 A(i,j,:)=B(x,y,:); 因为 i,x 对应的是列,即宽,而 j,y 对应的是行,即高“)end % 要弄清楚元素坐标与元素在矩阵中地位的转换关系
end
end
主程序
I=imread('football.jpg');
I1=myimrotate(I,45); % 调用 myimrotate()函数旋转 45°
I2=myimrotate(I,-45); % 调用 myimrotate()函数旋转 -45°
figure,subplot(1,3,1),imshow(I);
title('srcImage');
subplot(1,3,2),imshow(uint8(I1)); %matlab 中读入图像的数据类型是 uint8,而在图像矩阵运算的时候,应用的数据类型却是 double 类型
title('旋转 45°:I1');
subplot(1,3,3),imshow(uint8(I2));
title('旋转 -45°:I2');
程序运行后果: