首页 分享 MATLAB【数字图像处理】 实验一:图像处理基本操作(平移、放大、缩小、旋转、插值)

MATLAB【数字图像处理】 实验一:图像处理基本操作(平移、放大、缩小、旋转、插值)

来源:花匠小妙招 时间:2026-03-01 10:35
目录 一、实验目的二、实验环境三、实验内容题目相关知识部分核心代码实验结果分析:两种插值法优缺点 四、实验心得

一、实验目的

1、熟悉并掌握MATLAB工具的使用; 
2、实现图像的读取、显示、存储、平移、镜像、放大、缩小及旋转操作;
3、掌握常用的插值方法,并了解其优缺点。

二、实验环境

Matlab 2020B

三、实验内容

题目

1、读入一幅RGB图像,变换为灰度图像和二值图像,并在同一个窗口内分别显示RGB图像和灰度图像,注上文字标题,并将结果以文件形式存到磁盘上。
2、对图像执行平移、镜像(水平镜像、垂直镜像)放大、缩小及旋转操作,其中放大、旋转操作分别采用最近邻插值及双线性插值方法实现,要求根据算法自己编写代码实现,并分析两种插值方法的优缺点。

相关知识

在matlab环境中,调用imread()函数可读入图像,默认的存储方式为的矩阵,分RGB三个通道。值类型为uint8,即取值范围为0~255。

rgb2gray()函数将RGB三个通道存储的图像消除色调和饱和度,保留亮度,将RGB图像转为灰度图。
im2bw(I,level)函数基于阈值将图像转化为二值图像。输入图像可以为RGB图像,也可以为灰度图像。level参数为阈值取值范围为0到1之间的小数,将大于阈值的像素点变为白色(1),其他像素点变为黑色(0)。

图像平移时,设某个像素点坐标为 ( x 0 , y 0 ) (x_0,y_0) (x0​,y0​),经过平移 ( t x , t y ) (t_x,t_y) (tx​,ty​),达到坐标为 ( x 1 , y 1 ) (x_1,y_1) (x1​,y1​)。该关系可记为: { x 1 = x 0 + t x y 1 = y 0 + t y {x1=x0+txy1=y0+ty

{x1​=x0​+tx​y1​=y0​+ty​​,用矩阵形式可以记作: ( x 1 y 1 1 ) = ( x 0 y 0 1 ) ( 1 0 0 0 1 0 t x t y 1 ) (x1y11)=(x0y01)(100010txty1) (x1​​y1​​1​)=(x0​​y0​​1​)

​10tx​​01ty​​001​

​。在实现时,记图像的高为 h h h,宽为 w w w,需要判断 x 1 , y 1 x_1,y_1 x1​,y1​与 h , w h,w h,w的大小关系,不能发生下标越界。

图像水平镜像时,记图像宽为 w w w。则原像素点 ( x 0 , y 0 ) (x_0,y_0) (x0​,y0​)变为 ( w − x 0 , y 0 ) (w-x_0,y_0) (w−x0​,y0​),即: { x 1 = w − x 0 y 1 = y 0 {x1=w−x0y1=y0

{x1​=w−x0​y1​=y0​​。用矩阵形式记作: { x 1 = x 0 + t x y 1 = y 0 + t y {x1=x0+txy1=y0+ty {x1​=x0​+tx​y1​=y0​+ty​​,用矩阵形式可以记作: ( x 1 y 1 1 ) = ( x 0 y 0 1 ) ( − 1 0 0 0 1 0 w 0 1 ) (x1y11)=(x0y01)(−100010w01) (x1​​y1​​1​)=(x0​​y0​​1​)

​−10w​010​001​

​。

图像垂直镜像时,记图像高为 h h h。则原像素点 ( x 0 , y 0 ) (x_0,y_0) (x0​,y0​)变为 ( x 0 , h − y 0 ) (x_0,h-y_0) (x0​,h−y0​),即: { x 1 = x 0 y 1 = h − y 0 {x1=x0y1=h−y0

{x1​=x0​y1​=h−y0​​。用矩阵形式记作: ( x 1 y 1 1 ) = ( x 0 y 0 1 ) ( 1 0 0 0 − 1 0 0 h 1 ) (x1y11)=(x0y01)(1000−100h1) (x1​​y1​​1​)=(x0​​y0​​1​)

​100​0−1h​001​

​。

图像放大分为两个步骤:1.创建新的像素点位。2.给新的像素点位的对应位置赋值。

在使用最近邻插值法时,直接用原图中最近的像素点位给新图赋值。

在使用双线性插值法时,记原图大小 m ∗ n m*n m∗n,新图大小 a ∗ b a*b a∗b,则新图的坐标 ( x 0 ′ , y 0 ′ ) (x_0',y_0') (x0′​,y0′​)对应原图 ( x 0 , y 0 ) = ( x 0 ′ ∗ m / a , y 0 ′ ∗ n / b ) (x_0,y_0)=(x_0'*m/a,y_0'*n/b) (x0​,y0​)=(x0′​∗m/a,y0′​∗n/b)。找到与 ( x 0 , y 0 ) (x_0,y_0) (x0​,y0​)最近的四个整数点位记作 ( x 1 , y 1 ) , ( x 1 , y 2 ) , ( x 2 , y 1 ) , ( x 2 , y 2 ) (x_1,y_1),(x_1,y_2),(x_2,y_1),(x_2,y_2) (x1​,y1​),(x1​,y2​),(x2​,y1​),(x2​,y2​),其对应点位上的灰度值记为 P 11 , P 12 , P 21 , P 22 P_{11},P_{12},P_{21},P_{22} P11​,P12​,P21​,P22​。
则 ( x 0 ′ , y 0 ′ ) (x_0',y_0') (x0′​,y0′​)的灰度值为
y 2 − y 0 y 2 − y 1 ( x 2 − x 0 x 2 − x 1 P 11 + x 0 − x 1 x 2 − x 1 P 21 ) + y 0 − y 1 y 2 − y 1 ( x 2 − x 0 x 2 − x 1 P 12 + x 0 − x 1 x 2 − x 1 P 22 ) frac{y_2-y_0}{y_2-y_1}(frac{x_2-x_0}{x_2-x_1}P_{11}+frac{x_0-x_1}{x_2-x_1}P_{21})+frac{y_0-y_1}{y_2-y_1}(frac{x_2-x_0}{x_2-x_1}P_{12}+frac{x_0-x_1}{x_2-x_1}P_{22}) y2​−y1​y2​−y0​​(x2​−x1​x2​−x0​​P11​+x2​−x1​x0​−x1​​P21​)+y2​−y1​y0​−y1​​(x2​−x1​x2​−x0​​P12​+x2​−x1​x0​−x1​​P22​)

在实现时,可能需要去掉边框上的像素点值,以防止下标越界等情况。若 ( x 0 , y 0 ) = ( x 0 ′ ∗ m / a , y 0 ′ ∗ n / b ) (x_0,y_0)=(x_0'*m/a,y_0'*n/b) (x0​,y0​)=(x0′​∗m/a,y0′​∗n/b)为整数,则直接取该点灰度值赋给 ( x 0 ′ , y 0 ′ ) (x_0',y_0') (x0′​,y0′​)而无需进行双线性插值。

图像缩小算法与放大类似,只要新图像大小 a ∗ b a*b a∗b小于原图像大小 m ∗ n m*n m∗n即可。

在对图像进行旋转时,为了对图像中心进行旋转,需要先把坐标系平移到中心。记原中心点 ( x ′ , y ′ ) = ( 0 , 0 ) (x',y')=(0,0) (x′,y′)=(0,0),则变换后的中心点 ( x , y ) (x,y) (x,y)与原中心点关系为 ( x y 1 ) = ( x ′ y ′ 1 ) ( 1 0 0 0 − 1 0 − 0.5 w 0.5 h 1 ) (xy1)

=(x′y′1)

(1000−10−0.5w0.5h1)

(x​y​1​)=(x′​y′​1​)

​10−0.5w​0−10.5h​001​

​.则旋转分为三个步骤:将 x ′ o ′ y x'o'y x′o′y变成 x o y xoy xoy,将该点顺时针转 α alpha α度,最后将 x o y xoy xoy变回 x ′ o ′ y ′ x'o'y' x′o′y′。则完整的变换为:
( x y 1 ) = ( x ′ y ′ 1 ) = ( 1 0 0 0 − 1 0 − 0.5 w o l d 0.5 h o l d 1 ) ( cos ⁡ α − sin ⁡ α 0 sin ⁡ α cos ⁡ α 0 0 0 1 ) ( 1 0 0 0 − 1 0 − 0.5 w n e w 0.5 h n e w 1 ) (xy1)=(x′y′1)=(1000−10−0.5wold0.5hold1)(cosα−sinα0sinαcosα0001)(1000−10−0.5wnew0.5hnew1) (x​y​1​)=(x′​y′​1​)=

​10−0.5wold​​0−10.5hold​​001​

​cosαsinα0​−sinαcosα0​001​

​10−0.5wnew​​0−10.5hnew​​001​


由于前后图像大小不一定相等。所以需要进行插值处理,可以使用上文中提到的两种插值算法。新图像宽为 w ′ = ∣ cos ⁡ α ∣ ∗ w + ∣ sin ⁡ α ∣ ∗ h w'=|cosalpha|*w+|sinalpha|*h w′=∣cosα∣∗w+∣sinα∣∗h。新图像的高为 h ′ = ∣ sin ⁡ α ∣ ∗ w + ∣ cos ⁡ α ∣ ∗ h h'=|sinalpha|*w+|cosalpha|*h h′=∣sinα∣∗w+∣cosα∣∗h

部分核心代码

I_0=imread("test.jpg"); I_1=rgb2gray(I_0); I_2=im2bw(I_0,0.5); %figure('P1','P2','P3','P4') title("实验1-1") subplot(1,3,1);imshow(I_0);title('原图') subplot(1,3,2);imshow(I_1);title('灰度图') subplot(1,3,3);imshow(I_2);title('二值化') savefig("lab1_1.fig")

python

运行

123456789

完成了读入一幅RGB图像,变换为灰度图像和二值图像,并在同一个窗口内分别显示RGB图像和灰度图像,注上文字标题,并将结果以文件形式存到磁盘上。

I=imread("test.jpg"); [R,C,color]=size(I); res=zeros(R,C,color); for color=1:3 for i=1:R for j=1:C newx=i+60; newy=j+60; if ((newx<=R) && (newy<=C)) res(newx,newy,color)=I(i,j,color); end end end end imshow(uint8(res))

python

运行

123456789101112131415

完成了对图像的平移操作,对图像向右下平移60个像素。对于每个像素点,先平移,再判断下标是否越界,最后将像素点填入。

I=imread("test.jpg"); [R,C,ch]=size(I); res=zeros(R,C,ch); for color=1:3 for i=1:R for j=1:C-1 res(i,j,color)=I(i,C-j,color); end end end imshow(uint8(res))

python

运行

1234567891011

完成了对图像的垂直翻转操作。没有使用矩阵运算。

I=imread("test.jpg"); [R,C,ch]=size(I); res=zeros(R,C,ch); for color=1:3 for i=1:R-1 for j=1:C res(i,j,color)=I(R-i,j,color); end end end imshow(uint8(res))

python

运行

1234567891011

完成了对图像的水平翻转操作。没有使用矩阵运算。

I=imread("test2.jpg"); [h,w,ch]=size(I); height=1500; width=1500; newimg=zeros(height,width); multh=height/h; multw=width/w; for i=1:height for j=1:width for c=1:3 oldi=round(i/multh); oldj=round(j/multw); if (oldi>=1&&oldi<=h&&oldj>=1&&oldj<=w) newimg(i,j,c)=I(oldi,oldj,c); end end end end imshow(uint8(newimg))

python

运行

1234567891011121314151617181920

完成了对图像的放大/缩小操作。使用最近邻插值法。先把新图中的像素点除以放大倍数映射得到其在原图中的位置,将该位置值四舍五入找到最近邻,直接将最近邻的值填入。

I=imread('test2.jpg'); [m,n,ch]=size(I); width=100; height=100; newimg = uint8(zeros(width,height,3)); % 计算放大/缩小倍数 widthScale = m/width; heightScale = n/height; for ch=1:3 for x = 1:width - 1 for y = 1:height - 1 xx = x * widthScale;%新图像位置对应原图像位置 yy = y * heightScale;%新图像位置对应原图像位置 if (xx/double(uint16(xx)) == 1.0) && (yy/double(uint16(yy)) == 1.0) newimg(x,y,ch) = I(int16(xx),int16(yy),ch);%若正好对应到整数点,则直接赋值,不插值 else a = double(uint16(xx));%找整数点 b = double(uint16(yy)); if a==0||b==0||a>=m||b>=n%下标不能越界 continue; end x11 = double(I(a,b,ch)); % x11 = I(a,b) x12 = double(I(a,b+1,ch)); % x12 = I(a,b+1) x21 = double(I(a+1,b,ch)); % x21 =I(a+1,b) x22 = double(I(a+1,b+1,ch)); % x22 = I(a+1,b+1) newimg(x,y,ch) = uint8( (b+1-yy) * ((xx-a)*x21 + (a+1-xx)*x11) + (yy-b) * ((xx-a)*x22 +(a+1-xx) * x12)); end end end end imshow(newimg);

python

运行

12345678910111213141516171819202122232425262728293031

完成了对图像的放大/缩小操作。使用双线性插值法。先把新图中的像素点除以放大倍数映射得到其在原图中的位置,如果是整数则直接填入,如果不是整数则找到与其相邻的四个点,按照上文中的公式进行插值,将该值填入。

I=imread("test2.jpg"); angle=30; [h,w,d]=size(I); theta=angle/180*pi; cos_val = cos(theta); sin_val = sin(theta); w2=round(abs(cos_val)*w+h*abs(sin_val)); h2=round(abs(cos_val)*h+w*abs(sin_val)); img_rotate = uint8(zeros(h2,w2,3)); %像素是整数 for x=1:w2 for y=1:h2 x0 = uint32(x*cos_val + y*sin_val -0.5*w2*cos_val-0.5*h2*sin_val+0.5*w);%展开矩阵乘法 y0 = uint32(y*cos_val - x*sin_val +0.5*w2*sin_val-0.5*h2*cos_val+0.5*h);%展开矩阵乘法 x0=round(x0); %最近邻 y0=round(y0); %最近邻 if x0>=1 && y0>=1&& x0<=w && y0<=h %检测下标不能越界 img_rotate(y,x,:) = I(y0,x0,:); end end end imshow(img_rotate)

python

运行

12345678910111213141516171819202122232425

完成了对图像的旋转操作。对于图像大小会发生变化的情况,使用最近邻插值法处理缩放。同理,按四舍五入方式找到最近邻。

angle=45; I=imread('test2.jpg'); imshow(I); [h,w,d]=size(I); theta=angle/180*pi; M=[cos(theta) -sin(theta) 0;sin(theta) cos(theta) 0;0 0 1]; leftup=[1 1 1]*M; %新图左上角 rightup=[1 w 1]*M; %新图右上角 leftdown=[h 1 1]*M; %新图左下角 rightdown=[h w 1]*M; %新图右下角 cos_val = cos(theta); sin_val = sin(theta); w2=round(abs(cos_val)*w+h*abs(sin_val));%新图宽度 h2=round(abs(cos_val)*h+w*abs(sin_val));%新图高度 img_rotate=uint8(zeros(h2,w2,3)); dy=abs(min([leftup(1) rightup(1) leftdown(1) rightdown(1)])); %取得y方向的负轴超出的偏移量 dx=abs(min([leftup(2) rightup(2) leftdown(2) rightdown(2)])); %取得x方向的负轴超出的偏移量 for i=1-dy:h2-dy for j=1-dx:w2-dx pix=[i j 1]/M; %用变换后图像的点的坐标去寻找原图像点的坐标, yy=pix(1)-floor(pix(1)); xx=pix(2)-floor(pix(2)); if pix(1)>=1 && pix(2)>=1 && pix(1) <= h && pix(2) <= w x11=floor(pix(1)); %四个相邻的点 y11=floor(pix(2)); x12=floor(pix(1)); y12=ceil(pix(2)); x21=ceil(pix(1)); y21=floor(pix(2)); x22=ceil(pix(1)); y22=ceil(pix(2)); value_leftup=(1-xx)*(1-yy); %计算临近四个点在双线性插值中的权重 value_rightup=xx*(1-yy); value_leftdown=(1-xx)*yy; value_rightdown=xx*yy; img_rotate(i+dy,j+dx,:)=value_leftup*I(x11,y11,:)+value_rightup*I(x12,y12,:)+ value_leftdown*I(x21,y21,:)+value_rightdown*I(x22,y22,:); end end end imshow(uint8(img_rotate))

python

运行

123456789101112131415161718192021222324252627282930313233343536373839404142434445

完成了对图像的旋转操作。对于图像大小会发生变化的情况,使用双线性插值法处理缩放。同理,先找到新图中某点坐标对应原图位置(利用矩阵除法),找到其相邻的四个点位,按照上文中的公式进行插值。

实验结果

图1 题目1实验结果
对于题目1,完成了对图片的读取、灰度化、二值化操作。还生成了可以被matlab打开的.fig文件。
图2 平移实验结果
对于平移,正确地实现了图像的平移,并且对其余部分补上黑色边框。
图3 左右翻转实验结果
对于左右镜像翻转,正确地实现了图像的左右镜像翻转。
图4 上下翻转实验结果
对于上下镜像翻转,正确地实现了图像的上下镜像翻转。
图5 放大实验结果
成功将图像放大,利用最近邻插值。可以看到,放大的结果存在一定的锯齿与马赛克的现象。
图6 缩小实验结果
成功将图像缩小,利用最近邻插值。
图7 放大实验结果2
成功将图像放大,利用双线性插值。可以看到,放大的结果比起最近邻插值更为平滑,没有存在严重的锯齿现象。
图8 缩小实验结果2
成功将图像缩小,利用双线性插值。可以看到,利用双线性插值进行缩小时也没有出现失真现象。
在这里插入图片描述
图9、图10 旋转实验结果1、2
利用最近邻插值法与双线性插值法分别对图像进行旋转45°操作,并对其余区域填充为黑色。

分析:两种插值法优缺点

最近邻插值法优点:实现简单,运行速度快。缺点:在放大图像时可能出现锯齿现象,图像中一些曲线的边缘不平滑。在放大后缩小回去还会出现一定的失真现象,使图像看起来变得模糊了,像马赛克。
双线性插值法优点:一定程度上缓解了最近邻插值法缺点出现的情况。放大图像后图像中的一些曲线看起来更平滑,对一张图像反复放大缩小后失真现象不严重,处理效果较好。缺点:处理速度慢,在matlab2020B实验环境中往往需要对一张图像处理约3秒左右。对于图像的最外圈边缘也难以处理。

四、实验心得

相关知识

数字图像处理—图像纹理特征
matlab与数字图像处理
基于数字图像处理的甘蓝虫害识别试验研究
图像处理领域专业术语
matlab实现种子识别、计数
基于数字图像处理的果树病虫害智能化检测
【端到端】:从图像到识别:手写数字识别的完整流程
数字图像处理之椒盐噪声和中值滤波
MATLAB图像去躁
ps怎么放大文件

网址: MATLAB【数字图像处理】 实验一:图像处理基本操作(平移、放大、缩小、旋转、插值) https://www.huajiangbk.com/newsview2576384.html

所属分类:花卉
上一篇: 蜜雪冰城奶茶里喝出一个花飞蛾
下一篇: 守墓人飞蛾怎么获得

推荐分享