任务:
选择典型图像(football.jpg)为研究对象
1.显示原图像
2.将图像旋转45°并进行显示(不调用自带函数,利用矩阵变换)
原理:
(原文链接:https://blog.csdn.net/Bryan_Q...)
以坐标原点为中心旋转的原理
$$ \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');