天天育儿网,内容丰富有趣,生活中的好帮手!
天天育儿网 > 【数字图像处理】【Matlab】【作业六】几何变换(平移 缩放 旋转 镜像 转置等)

【数字图像处理】【Matlab】【作业六】几何变换(平移 缩放 旋转 镜像 转置等)

时间:2018-11-20 11:54:07

相关推荐

【数字图像处理】【Matlab】【作业六】几何变换(平移 缩放 旋转 镜像 转置等)

注意事项:

1.使用软件:Matlaba。

2.使用图像来自网络。

3.所以坐标系均采用竖直为x轴,水平为y轴(与matlab矩阵对应)。

4.初学者代码仅供参考,可自行简化或添加自己想要的部分。

5.祝大家码代码快乐!

图像的几何变换

1.图像平移1.1. 原理1.2. 算法1.3. 代码1.4. 结果截图2.图像缩放2.1. 原理2.3. 代码2.4. 结果截图3.图像旋转3.1. 原理3.3. 代码3.4. 结果截图4.图像镜像4.1. 原理4.2. 算法4.3. 代码4.4. 结果截图5.图像转置5.1. 原理5.2. 算法5.3. 代码5.4. 结果截图6.图像剪切7.图像的整体切变

1.图像平移

1.1. 原理

图像平移是将图像中所有的点都按照指定的平移量,进行水平、垂直移动。

设初始坐标为(x0,y0)(x0,y0)(x0,y0)的点经过平移(tx,ty)(tx,ty)(tx,ty)后坐标变为(x1,y1)(x1,y1)(x1,y1)

{x1=x0+txy1=y0+ty\begin{cases}x1=x0+tx\\y1=y0+ty\end{cases}{x1=x0+txy1=y0+ty​

图1-1 图像平移原理

1.2. 算法

获取原图像的宽高。

输入偏移量move_x,move_y。

新建一个同样大小的图像空白矩阵。

对原图依次循环每个像素,每读入一个像素点(x0,y0),根据它的坐标,找到目标图像的位置(x1=x0-move_x,y1=y0-move_y) ,将像素( x0,y0) 处的灰度值值赋给新图中的(x1,y1)。

根据平移量正负,分为如下4种情况:

图1-2 图像平移算法

1.3. 代码

【mymove.m】

% 函数mymove:实现图像的上下左右平移% 输入参数:I为原图像% move_x,move_y为竖直,水平位移大小% 输出参数:平移变换后的图像OUT% 使用函数:double(I):增大精度,便于图像的计算% size(J):求矩阵的宽高% zeros():生成全零矩阵% inf:无穷大(白色)function OUT = mymove(I,move_x,move_y)J=double(I);HW=size(J);%获取原图像大小OUT=zeros(HW);%新建新的图像矩阵OUT(1:HW(1),1:HW(2))=inf;%初始为全白图像if((move_x>=0) && (move_y>=0))OUT(move_x+1:HW(1),move_y+1:HW(2))=J(1:HW(1)-move_x,1:HW(2)-move_y);elseif((move_x>0) && (move_y<0))OUT(move_x+1:HW(1),1:HW(2)+move_y)=J(1:HW(1)-move_x,1-move_y:HW(2));elseif((move_x<0) && (move_y>0))OUT(1:HW(1)+move_x,move_y+1:HW(2))=J(1-move_x:HW(1),1:HW(2)-move_y); elseif((move_x<0) && (move_y<0))OUT(1:HW(1)+move_x,1:HW(2)+move_y)=J(1-move_x:HW(1),1-move_y:HW(2));endOUT=uint8(OUT);end

【main.m】

%主函数close all;clear all; %#ok<*CLALL>clc;%% RGB->灰度图像 RGB=imread('test.png'); %图像读入I=rgb2gray(RGB); %把 RGB 图像转换成灰度图像%% 图像的平移(Image translation)move_x=100;%竖直位移(默认向下)move_y=60;%水平位移(默认向右)OUT_1_1=mymove(I,move_x,move_y);move_x=100;move_y=-60;OUT_1_2=mymove(I,move_x,move_y);move_x=-100;move_y=60;OUT_1_3=mymove(I,move_x,move_y);move_x=-100;move_y=-60;OUT_1_4=mymove(I,move_x,move_y);move_x=1050;move_y=-60;%超出图像范围的情况OUT_1_5=mymove(I,move_x,move_y);figure,suptitle('【图像平移】');subplot(2,3,1),imshow(I),axis on,title('原图像'); subplot(2,3,2),imshow(OUT_1_1),axis on,title('平移变换1');subplot(2,3,3),imshow(OUT_1_2),axis on,title('平移变换2');subplot(2,3,4),imshow(OUT_1_3),axis on,title('平移变换3');subplot(2,3,5),imshow(OUT_1_4),axis on,title('平移变换4');subplot(2,3,6),imshow(OUT_1_5),axis on,title('平移变换5(平移距离超出原图像坐标范围)');

1.4. 结果截图

图1-3 图像平移结果

2.图像缩放

2.1. 原理

假设图像X轴方向缩放比率是kxkxkx, Y轴方向缩放比率是kykyky,

{x1=x0∗kxy1=y0∗ky\begin{cases}x1=x0*kx\\y1=y0*ky\end{cases}{x1=x0∗kxy1=y0∗ky​

当kx>1kx>1kx>1且ky>1ky>1ky>1时,原图像被放大。放大图像时, 产生了新的像素, 可通过插值算法来近似处理。

当kx<1kx<1kx<1且ky<1ky<1ky<1时,原图像被缩小。

当kx=kykx=kykx=ky时,图象被等比例放缩;当kx≠kykx≠kykx​=ky时,图像被非比例放缩,图像会发生变形,且这种变形是不可逆转的。

2.2. 算法

获取原图像的宽高。

输入缩放比例:zoom_x,zoom_y。

得到新图像的宽度和高度。

每个目标点的坐标依次循环。计算该象素在原图像中的坐标,使用双线性插值算法,算出像素值赋给目标点。

最终输出放缩后的图像,无论是放大还是缩小,画布的大小都不变,这样更易观察图像的变换情况。

双线性插值算法具体步骤:

①先按要求缩放原图像,得出缩放后的坐标,再由缩放后的坐标(i,j)(i,j)(i,j)求出该坐标在原图像上的位置,即(x,y)=(izoomx,jzoomy)(x,y)=(\frac{i}{zoom_x},\frac{j}{zoom_y})(x,y)=(zoomx​i​,zoomy​j​),即为上图所示的M点([x]+u,[y]+v)([x]+u,[y]+v)([x]+u,[y]+v)。其中(u,v)(u,v)(u,v)表示小数部分的坐标。

②设原图像中有4个点,分别为 R1(a1,b1),R2(a1,b2),R3(a2,b1),R4(a2,b2)R1(a1,b1),R2(a1,b2),R3(a2,b1),R4(a2,b2)R1(a1,b1),R2(a1,b2),R3(a2,b1),R4(a2,b2),其中这四点为相邻点,即

a2−a1=1;b2−b1=1;a2-a1=1;b2-b1=1;a2−a1=1;b2−b1=1;

而图中M点([x]+u,[y]+v)为缩放图像所要插入的点。

③根据双线性插值的算法,先在x方向上进行线性插值,即有

{f(M1)=u∗f(R1)+(1−u)∗f(R2);f(M2)=u∗f(R3)+(1−u)∗f(R4);\begin{cases}f(M1)=u*f(R1)+(1-u)*f(R2);\\ f(M2)=u*f(R3)+(1-u)*f(R4);\end{cases}{f(M1)=u∗f(R1)+(1−u)∗f(R2);f(M2)=u∗f(R3)+(1−u)∗f(R4);​

④再在y方向上进行线性插值,即有

f(M)=v∗f(M1)+(1−v)∗f(M2);f(M)=v*f(M1)+(1-v)*f(M2);f(M)=v∗f(M1)+(1−v)∗f(M2);

⑤综上,有:f(M)=uvf(R1)+(1−u)vf(R2)+u(1−v)f(R3)+(1−u)(1−v)f(R4);f(M)=uvf(R1)+(1-u)vf(R2)+u(1-v)f(R3)+(1-u)(1-v)f(R4);f(M)=uvf(R1)+(1−u)vf(R2)+u(1−v)f(R3)+(1−u)(1−v)f(R4);

图2-1 图像缩放双线性插值法

2.3. 代码

目前myimresize存在问题:对于图像像素大小为奇数的图像无法处理!!暂未修改

【myimresize.m】

% 函数myimresize:采用双线性插值法对图像进行缩放处理% 输入参数:I为原图像% zoom_x,zoom_y表示缩放的倍数% 输出参数:平移变换后的图像OUT% 使用函数:floor(x):向下取整% ceil(x):向上取整% round(x):取最接近的整数function OUT=myimresize(I,zoom_x,zoom_y)J=double(I); %二维矩阵转为双精度类型HW=size(J);%获取原图像大小OUT=zeros(HW);%新建新的图像矩阵OUT(1:HW(1),1:HW(2))=inf;%初始为空白rHW=[round(HW(1)*zoom_y),round(HW(2)*zoom_x)];%新的图像高宽for i = 1 : rHW(1) %缩放后的图像的(i,j)位置对应原图的(x,y)for j = 1 : rHW(2)x = i / zoom_y ;y = j / zoom_x ;u = x - floor(x);v = y - floor(y); %得到小数部分坐标if x < 1 %图像的边界处理x = 1;endif y < 1y = 1;end%用原图的四个真实像素点来双线性插值获得“虚”像素的像素值OUT(i, j) = J(floor(x), floor(y)) * u * v + ...J(floor(x), ceil(y)) * (1-u) * v + ...J(ceil(x), floor(y)) * u * (1-v) + ...J(ceil(x), ceil(y)) *(1-u) * (1-v);endendOUT=uint8(OUT(1:HW(1),1:HW(2)));end

【main.m】

%主函数close all;clear all; %#ok<*CLALL>clc;%% RGB->灰度图像 RGB=imread('test.png'); %图像读入I=rgb2gray(RGB); %把 RGB 图像转换成灰度图像%% 图像的缩放(Image scaling)zoom_x=0.5;zoom_y=0.5;%等比缩小OUT_2_1=myimresize(I,zoom_x,zoom_y);zoom_x=2;zoom_y=2;%等比放大OUT_2_2=myimresize(I,zoom_x,zoom_y);zoom_x=0.5;zoom_y=0.8;%非比例缩小OUT_2_3=myimresize(I,zoom_x,zoom_y);zoom_x=1.8;zoom_y=1;%非比例放大OUT_2_4=myimresize(I,zoom_x,zoom_y);figure,suptitle('【图像缩放1】');subplot(1,3,1),imshow(I),axis on,title('原图像') subplot(1,3,2),imshow(OUT_2_1),axis on,title('等比缩小变换');subplot(1,3,3),imshow(OUT_2_2),axis on,title('等比放大变换');figure,suptitle('【图像缩放2】');subplot(1,3,1),imshow(I),axis on,title('原图像') subplot(1,3,2),imshow(OUT_2_3),axis on,title('非比例缩小变换');subplot(1,3,3),imshow(OUT_2_4),axis on,title('非比例放大变换');

2.4. 结果截图

图2-2 图像等比例放缩图2-3 图像非比例放缩

3.图像旋转

3.1. 原理

必须指明图像绕着什么旋转。 一般图像的旋转是以图像的中心为原点, 旋转一定的角度。

旋转后, 一般会改变图像的大小。

设原始图像的任意点A0(x0,y0)经逆时针旋转角度β以后到新的位置A(x,y),为表示方便,采用极坐标形式:

{x0=rcos(β)y0=rsin(β)\begin{cases}x0=rcos(β)\\y0=rsin(β)\end{cases}{x0=rcos(β)y0=rsin(β)​

逆时针旋转变换后的坐标为:

{x1=x0cos(β)−y0sin(β)y1=x0sin(β)+y0cos(β)\begin{cases}x1=x0cos(β)-y0sin(β)\\y1=x0sin(β)+y0cos(β)\end{cases}{x1=x0cos(β)−y0sin(β)y1=x0sin(β)+y0cos(β)​

变换如下图所示:

图3-1 图像旋转原理

3.2. 算法

获取原图像的宽高。

输入旋转角度:alphaalphaalpha,进行如下处理:

①将旋转角度转换到0~360之间计算;

②得到旋转弧度;

图3-2 图像旋转角度范围

由此可将旋转角度分为以上4个区间,每个区间对应的变换不同。

得到新图像的宽度和高度。

为了确保旋转后的图像都能够在画布内,不会被切点,初始化的画布设置为最大,所以用到了abs(x)abs(x)abs(x)取绝对值和ceil(x)ceil(x)ceil(x)向上取整两个函数。

nHW(1)=ceil(HW(1)*abs(cos(abs(alpha)))+HW(2)*abs(sin(abs(alpha))));nHW(2)=ceil(HW(1)*abs(sin(abs(alpha)))+HW(2)*abs(cos(abs(alpha))));

每个目标点的坐标依次循环。

①计算该象素在原图像中的坐标:

这个地方尤其注意由于我们默认设置为逆时针变换,而计算时是由新图像的坐标点(i,j)(i,j)(i,j)换算出其在原图像所在的位置(x,y)(x,y)(x,y)所以转换矩阵应该反过来才对,即转换矩阵如下:

{x=icos(β)+jsin(β)y=−isin(β)+jcos(β)\begin{cases}x=icos(β)+jsin(β)\\y=-isin(β)+jcos(β)\end{cases}{x=icos(β)+jsin(β)y=−isin(β)+jcos(β)​

为了使得到的图像都能显示在画布的正中心,根据角度alphaalphaalpha的四个区间分为4种情况,每种情况的位移量不同,由此得到不同的4个计算公式。

②然后使用双线性插值算法,(具体步骤和图像缩放时的一样)算出像素值赋给目标点。最终输出放缩后的图像,无论是放大还是缩小,画布的大小都不变,这样更易观察图像的变换情况。

3.3. 代码

【myimrotate.m】

%函数myimrotate:采用双线性插值法实现图像旋转%输入参数:I原图像% alpha:旋转的角度(>0为逆时针)%输出参数:OUT旋转变换后的图像%使用函数:mod(m,n):对m/n取余% abs(x):取绝对值% ceil(x):向上取整% pi:3.1415926......可直接使用% floor(x):向下取整function OUT=myimrotate(I,alpha)J=double(I);HW=size(J);%获取原图像大小alpha=mod(alpha,360);%将旋转角度转换到0~360之间计算alpha=alpha*pi/180;%得到旋转弧度%确保旋转后的图片还在坐标系内nHW(1)=ceil(HW(1)*abs(cos(abs(alpha)))+HW(2)*abs(sin(abs(alpha))));%新图像的高heighth   nHW(2)=ceil(HW(1)*abs(sin(abs(alpha)))+HW(2)*abs(cos(abs(alpha))));%新图像的宽width OUT=zeros(nHW);%新建新的图像矩阵OUT(1:nHW(1),1:nHW(2))=inf;%初始为空白u0=HW(2)*sin(alpha);u2=HW(1)*cos(alpha);%竖直方向的相关平移量u1=HW(1)*sin(alpha);u3=HW(2)*cos(alpha);%水平方向的相关平移量T=[cos(alpha),sin(alpha);-sin(alpha),cos(alpha)];%变换矩阵for i = 1:nHW(1)%(i,j)是新图像坐标,变换到原图像坐标(x,y)中。          for j=1:nHW(2)if(alpha>=0 && alpha<=pi/2)XY=T*([i;j]-[u0;0]);%保证输出在图像的中心elseif(alpha>pi/2 && alpha<=pi)XY=T*([i;j]-[u0-u2;-u3]);%保证输出在图像的中心 elseif(alpha>pi && alpha<=3*pi/2)XY=T*([i;j]-[-u2;-u3-u1]);%保证输出在图像的中心elseif(alpha>3*pi/2 && alpha<=2*pi)XY=T*([i;j]-[0;-u1]);%保证输出在图像的中心endx=XY(1);%变换得到的原坐标y=XY(2);if x>=1 && x<=HW(1) && y>=1 && y<=HW(2) %若变换出的x和y在原图像范围内               u = x - floor(x);v = y - floor(y); %得到小数部分坐标%用原图的四个真实像素点来双线性插值获得“虚”像素的像素值OUT(i, j) = J(floor(x), floor(y)) * u * v + ...J(floor(x), ceil(y)) * (1-u) * v + ...J(ceil(x), floor(y)) * u * (1-v) + ...J(ceil(x), ceil(y)) *(1-u) * (1-v);endendendOUT=uint8(OUT);end

【main.m】

%主函数close all;clear all; clc;%% RGB->灰度图像 RGB=imread('test.png'); %图像读入I=rgb2gray(RGB); %把 RGB 图像转换成灰度图像%% 图像的旋转(Image rotation)alpha=30;%默认>0为逆时针旋转OUT_2_1=myimrotate(I,alpha);alpha=120;OUT_2_2=myimrotate(I,alpha);alpha=-30;%默认<0为顺时针旋转OUT_2_3=myimrotate(I,alpha);alpha=-100;OUT_2_4=myimrotate(I,alpha);figure,suptitle('【图像逆时针旋转】');subplot(1,3,1),imshow(I),axis on,title('原图像');subplot(1,3,2),imshow(OUT_2_1),axis on,title('图像旋转1');subplot(1,3,3),imshow(OUT_2_2),axis on,title('图像旋转2');figure,suptitle('【图像顺时针旋转】');subplot(1,3,1),imshow(I),axis on,title('原图像');subplot(1,3,2),imshow(OUT_2_3),axis on,title('图像旋转3');subplot(1,3,3),imshow(OUT_2_4),axis on,title('图像旋转4');

3.4. 结果截图

图3-3 图像逆时针旋转结果图3-4 图像顺时针旋转结果

4.图像镜像

4.1. 原理

分为两种:一种是水平镜像,另一种是垂直镜像。

设图像高度为HeightHeightHeight, 宽度为WidthWidthWidth;

图像的水平镜像操作是以原图像的垂直中轴线为中心,将图像分为左右两部分进行对称变换;

{x1=x0y1=width+1−y0\begin{cases}x1=x0\\y1=width+1-y0\end{cases}{x1=x0y1=width+1−y0​

图像的垂直镜像操作是以原图像的水平中轴线为中心,将图像分为上下两部分进行对称变换。

{x1=height+1−x0y1=y0\begin{cases}x1=height+1-x0\\y1=y0\end{cases}{x1=height+1−x0y1=y0​

镜像变换后图的高和宽都不变。

4.2. 算法

获取原图像的宽高。输入choice。新建一个同样大小的图像空白矩阵。根据choice选择是水平镜像还是垂直镜像。

4.3. 代码

【mymirror.m】

%函数mymirror:实现图像镜像%输入参数:I原图像% choice选择水平或垂直镜像%输出参数:OUT镜像变换后的图像%使用函数:strcmp(a,b):比较两个字符串是否相等function OUT=mymirror(I,choice)J=double(I);HW=size(J);%获取原图像大小OUT=zeros(HW);%新建新的图像矩阵OUT(1:HW(1),1:HW(2))=inf;%初始为空白for i = 1:HW(1)for j=1:HW(2)if strcmp(choice,'level')OUT(i, j) = J(i, HW(2)+1-j);elseif strcmp(choice,'vertical')OUT(i, j) = J(HW(1)+1-i, j);endendendOUT=uint8(OUT);end

【main.m】

%主函数close all;clear all; %#ok<*CLALL>clc;%% RGB->灰度图像 RGB=imread('test.png'); %图像读入I=rgb2gray(RGB); %把 RGB 图像转换成灰度图像%% 4.图像的镜像变换(Image mirror transformation)OUT_4_1=mymirror(I,'level');%选择参数'level'即为水平镜像OUT_4_2=mymirror(I,'vertical');%选择参数'vertical'即为垂直镜像figure,suptitle('【图像镜像变换】');subplot(1,3,1),imshow(I),axis on,title('原图像');subplot(1,3,2),imshow(OUT_4_1),axis on,title('水平镜像');subplot(1,3,3),imshow(OUT_4_2),axis on,title('垂直镜像');

4.4. 结果截图

图4-1 图像镜像变换结果

5.图像转置

5.1. 原理

将图像像素的x坐标和y坐标互换。 将改变图像的高度和宽度,转置后图像的高度和宽度将互换。

{x1=y0y1=x0\begin{cases}x1=y0\\y1=x0\end{cases}{x1=y0y1=x0​

5.2. 算法

获取原图像的宽高。新建一个同样大小的图像空白矩阵。将原图像转置后对应的点赋值给新图像的点。

5.3. 代码

【mytranspose.m】

%函数mytranspose:实现图像转置%输入参数:I原图像%输出参数:OUT转置变换后的图像function OUT=mytranspose(I)J=double(I);HW=size(J);%获取原图像大小OUT=zeros(HW(2),HW(1));%新建新的图像矩阵OUT(1:HW(2),1:HW(1))=inf;%初始为空白for i = 1:HW(2)for j=1:HW(1)OUT(i, j) = J(j,i);endendOUT=uint8(OUT);end

【main.m】

%主函数close all;clear all; %#ok<*CLALL>clc;%% RGB->灰度图像 RGB=imread('test.png'); %图像读入I=rgb2gray(RGB); %把 RGB 图像转换成灰度图像%% 5.图像的转置(Image transpose)OUT_5_1=mytranspose(I);figure,suptitle('【图像转置变换】');subplot(1,2,1),imshow(I),axis on,title('原图像');subplot(1,2,2),imshow(OUT_5_1),axis on,title('转置变换');

5.4. 结果截图

图5-1 图像转置变换结果

6.图像剪切

很简单!

J=double(I);OUT_6=J(500:1000,200:300);OUT_6=uint8(OUT_6);

7.图像的整体切变

id=maketform('affine',[1 4 0;2 1 0;0 0 1]');%创建图像整体切变参数结构体id=imtransform(i,id,'FillValues',255);%实现图像整体切变

(使用maketformmaketformmaketform也可以实现以上其他变换,大家可自行尝试)

好了,本次学习就到这里,嘻嘻~~码代码去了

如果觉得《【数字图像处理】【Matlab】【作业六】几何变换(平移 缩放 旋转 镜像 转置等)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。