第3章〓数字图像的基本运算 数字图像处理从本质上讲,就是通过对图像施加某种运算,来满足人或机器视觉的应用需求。数字图像的基本运算通常是指对图像的代数运算和几何运算。从运算原理及运算的简单性来说,图像的灰度反转、对数变换和直方图(统计)显然应该属于图像的基本代数运算。 本章首先介绍图像的灰度反转和对数变换; 然后介绍图像直方图及其有关运算方法; 接着介绍图像的代数运算方法; 最后介绍图像的几何运算方法,包括图像的平移变换、图像的旋转变换、图像镜像、图像的转置、图像的缩小与放大等。 3.1灰 度 反 转 黑白图像的灰度反转(grayscale inversion)就是使灰度值为1的像素值变成0,使灰度值为0的像素值变成1。 对于256灰度级图像来说,图像的灰度反转值就是用255分别减去原图像f(x,y)的各个像素的灰度值。一般地,设图像的灰度级为L,则图像的灰度反转可表示为 g(x,y)=L-1-f(x,y)(3.1) 256灰度级图像的灰度反转原理如图3.1(a)所示,灰度图像反转示例如图3.1(b)和图3.1(c)所示。 图3.1灰度图像反转原理及图例 【例3.1】灰度反转MATLAB程序,程序运行结果如图3.1所示。 clc; clear all; close all; img0=imread('d:\0_matlab图像课编程\lena.bmp'); result_img=256-1-img0; % 图像阵列中的所有像素的灰度值反转 subplot(1,2,1); imshow(img0); title('原图像'); % 显示原图像 subplot(1,2,2); imshow(result_img); title('灰度反转图像(负片)'); 3.2对 数 变 换 对原图像f(x,y)进行对数变换(logarithmic transformation)的解析式可表示为 g(x,y)=c·log(1+f(x,y))(3.2) 其中,c是一个常数。 对数变换的作用是对原图像的灰度值动态范围进行压缩,主要用于调高输入图像的低灰度值。比如对于傅里叶频谱来说,要显示的值的范围往往比较大,而傅里叶频谱要显示的重点是突出最亮的像素(对应于低频成分),在8比特的显示系统中会损失掉频谱图像中的低灰度值部分(对应于高频成分)。在这种情况下,可以依据式(3.2)对频谱进行变换(这时c=1),调高频谱图像的低灰度值而对高灰度值又尽可能地影响最小。傅里叶频谱一般都是通过这种方式的调整来进行显示。 【例3.2】对数图像进行对数变换运算的MATLAB程序,程序运行结果如图3.2所示。 clc; clear all; close all; img0=imread('d:\0_matlab图像课编程\fft_img.jpg') % 读取灰度图像 img1=double(img0); log_img=log(1+img1); %对图像进行对数运算 subplot(1,2,1); imshow(img0); title('原傅里叶频谱图像'); subplot(1,2,2); imshow(log_img); title('提升低频成分后的傅里叶频谱图像'); 图3.2利用对数变换对傅里叶频谱图像进行调整示例 例3.2中的相关函数及功能说明如下。 log(x): MATLAB中提供的求自然对数函数,对x求以e为底的对数。当x为向量时,对x的元素逐个进行以e为底的对数运算。 3.3灰度直方图 在数字图像处理中,灰度图像的直方图(简称灰度直方图,gray histogram)是一种描述一幅灰度图像中灰度级内容的最简单且最有用的工具,也是对灰度图像进行多种处理的基础。 3.3.1灰度图像直方图与灰度图像的对比度 1. 灰度图像直方图 灰度图像的直方图是关于灰度级分布的函数,描述的是灰度图像中的各灰度级及其出现的频数(该灰度级的像素数目)的统计关系,是一种表示数字图像中灰度级分布函数关系的柱状图表示形式。灰度直方图的横坐标表示灰度级(即亮度级别),取值范围为0~255; 灰度直方图的纵坐标表示图像中各灰度级的像素数目(即统计的各灰度级像素的个数)。灰度图像直方图定义为 h(rk)=nkk=0,1,2,…,L-1 H(P)=[h(r1),h(r2),…,h(rL-1)] (3.3) 其中,rk表示第k级灰度; nk表示图像中灰度级为rk的像素的个数; H(P)是灰度图像的直方图函数。在有些文献中所提及的一维直方图即是本节所讲的灰度图像的直方图。 理解和观看直方图的规则一是“左黑右白”或“左暗右亮”; 二是横轴上各(亮度值)点对应的柱状高度就是分布在该亮度的像素个数; 三是当柱状接近分布在整个横轴上,且至少有一个峰值时,图像的对比度较好。 2. 灰度图像的对比度 灰度图像的对比度是对一幅图像中最亮的白和最暗的黑之间亮度层级的测量,一般用图像画面中最大的灰度值(最白亮度)与最小的灰度值(最黑亮度)的比值来表示。因此,白色越亮、黑色越暗,对比度就越高(大); 对比度越大,图像越清晰醒目; 对比度越小,图像越不清晰。 对比度直观地反映了图像中目标之内或目标与周围背景之间的亮度差别。如果成像系统在物体成像过程中的对比度选取得比较低,那么该物体所成的像(目标)看起来就比实际物体要暗一些; 如果对比度降至0,则物体将会从图像中消失。 3. 图像直方图的分布特征及其与图像对比度的关系 下面用一组图像及其直方图的示例,说明图像直方图的分布特征及其与图像对比度的关系。图3.3是具有4种基本图像类型(暗且低对比度、亮且低对比度、低对比度、高对比度)的图像及其灰度直方图。 图3.34种基本图像类型(暗、亮、低对比度、高对比度)图像及其灰度直方图 图3.3(续) 图3.3说明了4种基本图像类型图像的直方图分布特征: 当图像比较暗时,图像中的各像素的灰度值都比较小,所以直方图中的灰度分布主要集中在低像素极一端(左端); 由于图像中最大“白像素”和最小“黑像素”的比值较小,所以该类直方图的图像的对比度也较低。当图像比较亮时,图像中的各像素的灰度值都比较大,所以直方图中的灰度分布主要集中在高像素极一端(右端); 同理由于图像中最大“白像素”和最小“黑像素”的比值较小,所以该类直方图的图像的对比度也较低。当图像的对比度比较差(低)时,说明图像中多数较亮像素的灰度值与图像中多数较暗像素的灰度值的差别比较小,所以图像的直方图中的灰度分布就比较集中地分布在某个灰度值差较小的范围内,即图像直方图会聚集在某些灰度值范围内。当图像的对比度较好(高)时,图像的直方图中的灰度就会相对比较均匀地分布在整个灰度级范围内。 3.3.2灰度直方图的特征 灰度图像直方图具有如下一些特征。 (1) 灰度直方图仅能反映灰度图像中具有不同灰度值的像素出现的次数(或频次),不能反映出灰度图像中各像素所在的(空间)位置信息。 (2) 灰度图像与灰度图像直方图之间存在着多对一的映射关系,即任一特定的灰度图像都有唯一对应的直方图,但不同的灰度图像可能有相同的直方图。 (3) 对于空间分辨率为M×N,且灰度级范围为[0,L-1]的图像,有关系式 ∑L-1j=0h(j)= M×N(3.4) (4) 如果一幅图像由两个不连接的区域组成,则整幅图像的直方图等于两个不连接的区域的直方图之和。 3.3.3归一化灰度图像直方图 由于式(3.3)所定义的灰度直方图反映的是图像中各灰度的实际出现频数,这样当某个灰度值的频数(计数值)远远大于其他灰度值的频数时,根据图像的某个或某些像素出现的最大频数来确定直方图的纵坐标的最大尺度既不方便也不太现实。也就是说,可能会由于直方图的纵坐标与横坐标尺寸过于悬殊而难于直观显示完整直方图的情况。为了能完整地显示任何形式的图像的直方图,通常采用归一化形式的直方图,即将直方图的横坐标取值和纵坐标取值变换到区间[0,1]。通常,如不加特殊说明,人们提到的直方图都是指归一化的直方图。 设rk为图像f(x,y)的第k级灰度,nk是图像f(x,y)中灰度级为rk的像素个数,n=∑L-1k=1nk是图像f(x,y)的像素总数,则图像f(x,y)的(归一化)灰度直方图定义为 P(rk)=nkn0≤rk≤1;k=0,1,…,L-1 H(P)=[P(r1),P(r2),…,P(rL-1)] (3.5) 有关直方图的应用,将会在后续相关的章节中介绍。 【例3.3】编写MATLAB程序生成灰度图像的灰度直方图,并与由MATLAB直方图函数得到的灰度直方图进行比较,程序运行结果如图3.4所示。 clc; clear all; close all; %清除命令窗口和工作空间,关闭figure窗口 img0=imread('d:\0_matlab图像课编程\lena.jpg') ; %读入图像文件 [h,w]=size(img0); %获取图像的大小(高度h,宽度w) gray_num =zeros(1,256); %创建一个1~256的数组记录各像素值出现的频数 imshow(img0); title('原图像'); %显示原图像 for i=1:h for j=1:w for k=0:255 %统计各像素值出现的频数 if img0(i,j)==k gray_num(k+1)= gray_num(k+1)+1; %MATLAB矩阵的第一个元素下标应是1 end end end end figure; subplot(1,2,1); %在另一个figure窗口显示直方图 bar(gray_num); % 创建显示窗口,画直方图 title('编程画的图像灰度直方图'); xlabel('灰度级'); ylabel('出现个数'); subplot(1,2,2); imhist(img0); %用MATLAB的直方图函数显示直方图 title('MATLAB函数画的图像灰度直方图'); 图3.4编程画图像灰度直方图运行结果 在例3.3的程序中,统计各个灰度级出现个数时是按灰度级的范围0~255进行的,但在MATLAB中,数组的个数是从1开始算起的。程序的实现语句如下。 for k=0:255 if img0(i,j)==k gray_num(k+1)= gray_num(k+1)+1; end end 例3.3中的相关函数及功能说明如下。 (1) bar(Y): 当Y为矢量(本例即是)时,将其中的每个元素在窗口中绘制为一个条形。 (2) xlabel(x): 该函数用于在绘图窗口中的横轴(x轴)方向上显示一个“标签”(即一个字符串),这个字符串用于表明x轴的意义。例如,本例中横轴为灰度值坐标,所以其标签为xlabel('灰度级')。 (3) ylabel(y): 该函数用于在绘图窗口中的纵轴(y轴)方向上显示一个“标签”,用于表明y轴的意义。例如,本例中纵轴为各灰度级出现的频数,所以其标签为ylabel('出现个数')。 (4) imhist(I): MATLAB中提供的默认显示256灰度级图像I的直方图的函数。当格式为imhist(I,n)时,n用于指定图像I的灰度级数目。 3.4图像的代数运算 图像的代数运算包括两幅图像的相加运算和相减运算。 3.4.1图像的相加运算 图像相加是通过对两幅大小相同的图像对应位置像素的相加运算,以产生一幅新的含有两幅图像信息的图像的方法。图像相加也称为图像合成。设f1(x,y)和f2(x,y)分别表示大小为M×N的两幅输入图像,图像f1(x,y)和图像f2(x,y)相加后得到的结果输出图像为g(x,y),且x∈[0,M-1],y∈[0,N-1],则两幅图像的相加运算可表示为 g(x,y)=f1(x,y)+f2(x,y)(3.6) 图像相加运算的实现方法主要有以下两种。 1. 两幅图像内容的相加/合成 两幅256灰度级图像对应坐标位置像素值的相加,其结果必然会超过其最大的灰度表示范围256,最常用的处理方法是将两幅图像像素灰度值相加后的平均值作为相加结果,如式(3.7)所示。 g(x,y)=IntegerRound12f1(x,y)+12f2(x,y)(3.7) 其中,IntegerRound为四舍五入取整函数,即将相加运算的结果置为整数值。由于数字图像的灰度值都是整数,所以严格来说有关图像的任何相加、相减、相乘和相除运算,对其运算结果都应用函数IntegerRound进行四舍五入的取整处理。但为了简化起见,本书后续有关图像灰度值的运算公式,均略去了IntegerRound函数。 图3.5给出了一个两幅灰度图像按式(3.7)相加的示例。图3.5(a)和图3.5(b)是两幅不同的输入图像,图3.5(c)是由两幅输入图像进行相加运算后的合成图像(彩色图像详见文前彩插)。 图3.5图像的相加运算示例 式(3.7)可以推广到两幅灰度图像按不同比例灰度值的叠加/合成,如式(3.8)所示。 g(x,y)=αf1(x,y)+βf2(x,y)(3.8) 其中,α+β=1。 两幅灰度图像相加还有另一种典型方式,根据两幅图像所有像素灰度值相加结果的最小值和最大值情况,将其等比例缩小到结果图像灰度值符合0~255的灰度值范围。这样做可以使图像的亮度分布到整个256灰度区间。 两幅灰度图像及彩色图像的相加/合成运算,也可以推广到多幅图像的相加/合成。 【例3.4】图像相加(合成)运算的MATLAB程序,程序运行结果如图3.5所示。 clc; clear all; close all; f1=imread('d:\0_matlab图像课编程\parrot.jpg'); f2=imread('d:\0_matlab图像课编程\sea_cloud.jpg'); f3=0.5*f1+0.5*f2; subplot(1,3,1); imshow(f1); title('鹦鹉图像'); subplot(1,3,2); imshow(f2); title('湖面图像'); subplot(1,3,3); imshow(f3); title('合成结果图像'); 2. 多幅图像的叠加去加性噪声 利用多幅灰度图像的叠加运算可以去除加性(additive)随机噪声。 图像的加性噪声可以简单地理解为在图像的背景中,与其相邻像素的灰度值相比,那些有明显差异的一些随机的、离散的和孤立的像素点,最容易理解的是黑区域上叠加的白点或白区域上叠加的黑点。 由于噪声产生的随机性,从同一场景获取的多幅图像中的噪声不可能完全相同。因此,可以通过对同一场景的多幅图像的灰度值求平均值,实现消除图像叠加噪声的目的。 当噪声互不相关且均值为零时,利用式(3.9)的N幅灰度图像的均值定义式可以降低噪声的影响。 g(x,y)=1N∑Ni=1fi(x,y)(3.9) 图3.6(a)是由于闪电、雷击、大气中的电暴等而使获取的天文图像有加性噪声,图3.6(b)是类似于图3.6(a)的两幅图像的去加性噪声的结果,图3.6(c)是类似于图3.6(a)的4幅图像的去加性噪声的结果,图3.6(d)是类似于图3.6(a)的16幅图像的去加性噪声的结果。可见,叠加的图像幅数越多,去除加性噪声的效果越明显。 图3.6利用图像叠加运算去加性噪声效果示例 3.4.2图像的相减运算 设f1(x,y)和f2(x,y)表示大小为M×N的两幅输入图像,从图像f1(x,y)中的各位置的像素值中减去图像f2(x,y)的相应位置的像素值后,得到的结果输出图像为g(x,y),且x∈[0,M-1],y∈[0,N-1],则两幅图像的相减运算可表示为 g(x,y)=f1(x,y)-f2(x,y)(3.10) 当两幅256灰度级图像对应坐标位置像素值相减的结果大于或等于零时,则取其为结果图像中对应位置像素的灰度值; 当相减结果小于零时,一般都是取零为结果值。当然,对于某些特殊的应用目的,也可以取其绝对值为结果值。 图像相减运算的典型应用是图像的变化检测。例如,在目前得到广泛应用的图像监控系统中,通过定时地将图像监控系统拍摄的现场图像与该现场初始情况下的图像进行相减运算,就可以判定被监控场景是否有异样情况出现。如图3.7所示,图3.7(a)是监控系统某时刻拍摄的现场监控图像,图3.7(b)是被监控现场的初始图像,图3.7(c)是从图3.7(a)中减去图3.7(b)后的结果图像。 图3.7图像的相减运算示例 需要注意的是,图像的灰度级是一个已有约定的有限大小的整数。以256的灰度级图像为例,图像代数运算的结果理应要求像素值不能大于255,也不能为负数。所以在有关的应用中一般都有对运算结果中不符合要求的像素值的处理约定。例如,对运算结果为负的像素值取0值或取其绝对值,对运算结果大于255的像素值取255或取关于256的模运算(MOD)结果等。 【例3.5】图像相减运算(图像变化检测)的MATLAB程序,程序运行结果如图3.7所示。 clc; clear all; close all; f1=imread('d:\0_matlab图像课编程\nopeson.jpg'); f2=imread('d:\0_matlab图像课编程\haspeson.jpg'); f3=f1-f2; subplot(1,3,1); imshow(f1); title('某时刻监控图像');%无人的楼道图像 subplot(1,3,2); imshow(f2); title('现场初始图像'); %有人的楼道图像 subplot(1,3,3); imshow(f3); title('相减结果图像');%变化检测结果图像 3.5图像的几何运算 图像的几何运算又称为图像的几何变换,用于使原图像产生大小、形状和位置等变化效果。 图像的几何运算包括图像的平移变换、 图3.8平移原理图 图像的旋转变换、图像镜像、图像转置和图像的缩放等。 3.5.1图像平移变换 图像平移(Image Translation)变换,是指将一幅图像或一幅图像的子图像块(以下简称为图像块)中的所有像素点,都按指定的x方向和y方向的偏移量Δx和Δy进行移动。 设初始坐标为(x0,y0)的像素平移(Δx,Δy)后的坐标为(x1,y1),如图3.8所示,则有 x1=x0+Δx y1=y0+Δy (3.11) 图像平移变换式(3.11)的矩阵形式为 x1y11=10Δx 01Δy 001x0y01(3.12) 图像的平移一般分为以下两种情况。 (1) 图像块平移。即将一幅图像中的某个子图像块平移到另一处。例如,在图3.9中,lena图像中lena眼部的一个子图像块被平移到了该图像的右下角,该子图像块同时覆盖掉了新位置上原来的那些图像内容。 图3.9图像(图像子块)平移示例 (2) 整幅图像平移。整幅图像平移后,相对于原来图像(位置)来说,如果完整保持被平移的原图像内容,形成的新结果图像的幅面就被放大了; 如果平移后的结果图像仍保持原来图像的幅面大小,被移出的部分就要被截掉。 【例3.6】原图像在x方向平移dx(设为20)个像素位置、在y方向平移dy(设为40)个像素位置,整幅图像平移后不放大而将移出的部分截断,程序运行结果如图3.10所示。 clc; clear; close all; img0=imread('d:\0_matlab图像课编程\lena.jpg'); [h,w]=size(img0); %获取图像矩阵行数h和列数w img1=zeros(h,w);%建立大小为h×w的零值矩阵,暂存平移结果 dx=20; dy=40; %在x方向和y方向的平移距离(像素个数)初值 h1=h-dx; %行方向下移dx个像素位置 w1=w-dy; %列方向右移dy个像素位置 for i=1:h1 for j=1:w1 x = i + dx; %计算平移后像素的行坐标 y = j + dy; %计算平移后像素的列坐标 img1(x,y)=img0(i,j); %将(i,j)处的像素点平移到(x,y)处 end end result_img=uint8(img1); subplot(1,2,1); imshow(img0); title('平移前原图像'); %显示原图像 subplot(1,2,2); imshow(result_img); title('平移后结果图像'); 图3.10例3.6的整幅图像平移截断移出部分结果 3.5.2图像旋转变换 图像旋转(image rotation)变换,是指以图像的中心为原点,将图像中的所有像素(即整幅图像)旋转一个相同的角度。 与图像平移变换类似,图像旋转变换的结果图像也分为两种情况: 一是旋转后的图像幅面被放大(按外接矩形尺寸),如图3.11所示; 二是保持图像旋转前后的幅面大小,把旋转后图像被转出原幅面大小的部分截断。 图3.11整幅图像旋转后图像幅面放大示例 1. 旋转后图像幅面放大的图像旋转变换 通常情况下,当一幅图像旋转后且要保留原图像中的所有画面时,按旋转后的外接矩形尺寸度量的该图像一定会变大许多。从分析图像的旋转原理角度,下面的讨论假设原图像旋转后的图像幅面仍小于屏幕大小,即不考虑因图像幅面变大而超出屏幕大小需要截断的情况。 实现图像旋转变换的实质是以显示屏上的图像中心为原点,将图像中的所有像素(即整幅图像)旋转一个相同的角度。图像旋转变换公式的推导分为两步,第一步是先把待旋转图像的中心看作是图像平面的xOy显示坐标系的原点(由于是基于显示屏上的图像旋转,所以按图像显示坐标,横坐标为y轴,纵坐标为x轴),并基于该图像平面的xOy显示坐标系推导出图像上像素点旋转变换公式; 第二步再把第一步推导的变换公式映射到原点位于屏幕左上角的图像显示坐标,由此得出在显示坐标下的图像旋转变换公式。 1) 基于图像平面xOy坐标系原点的旋转变换 在图3.12中,待旋转图像的中心是图像平面的xOy坐标系的原点,并设位于(x0,y0)处的点(为了全文表示上的一致,像素点坐标x和y的顺序不变)到坐标原点的直线r与y轴的夹角为α,当线段r沿顺时针(如图3.12(a)所示)或逆时针(如图3.12(b)所示)旋转β角度后,就使位于(x0,y0)处的点被旋转至(x1,y1)处。 图3.12基于图像平面xOy坐标系原点的旋转原理示意图 下面以图3.12(a)的顺时针旋转β角度为例,说明旋转变换的原理及公式。 显然,在旋转前 x0=rsinα y0=rcosα(3.13) 旋转后 x1=rsin(α-β)=rsinαcosβ-rcosαsinβ y1=rcos(α-β)=rcosαcosβ+rsinαsinβ(3.14) 将式(3.13)代入式(3.14)中,得到 x1=x0cosβ-y0sinβ y1=x0sinβ+y0cosβ(3.15) 由式(3.15)即可得到基于图像平面xOy坐标系原点的顺时针旋转变换的矩阵表示形式为 x1y11=cosβ-sinβ0 sinβcosβ0 001x0y01(3.16) 同理,依据图3.12(b)的逆时针旋转示意图可推出基于图像平面xOy坐标系原点的逆时针旋转变换的矩阵表示形式为 x1y11=cosβsinβ0 -sinβcosβ0 001x0y01 (3.17) 图3.13图像的像素点与图像的显示坐标 和xOy平面坐标的关系示例 2) 基于图像显示坐标的图像像素点的顺时针旋转变换 由于图像像素点的旋转变换是在原点位于屏幕左上角的图像显示坐标实现的,所以还需要将式(3.16)的顺时针变换矩阵表示形式映射到图像的显示坐标中。图3.13给出了图像的像素点与图像的显示坐标及图像平面xOy坐标关系的图示说明。 假设图像的宽度width用w表示,图像的高度high用h表示,则由图3.13可知: 在原点O′位于左上角,x′轴方向朝下,y′轴方向朝右的图像显示坐标x′O′y′中,如果用(x′0,y′0)表示(x0,y0)在图像显示坐标x′O′y′中的位置,用(x′1,y′1)表示(x1,y1)在图像显示坐标x′O′y′中的位置,则有 x′0=0.5h-x0 y′0=0.5w+y0(3.18) x′1=0.5h-x1 y′1=0.5w+y1(3.19) 由式(3.18)可得其逆变换的矩阵表达式为 x0y01=-10-0.5h 010.5w 001x′0y′01(3.20) 由式(3.19)可得其矩阵表示形式为 x′1y′11=-100.5h 010.5w 001x1y11 (3.21) 将式(3.16)和式(3.20)依次代入式(3.21)中,即可得到图像像素点的旋转变换公式为 x′1y′11=-100.5h 010.5w 001 cosβ-sinβ0 sinβcosβ0 001 -10-0.5h 010.5w 001 x′0y′01 化简计算上式,并用x1和x0分别代替x′1和x′0,用y1和y0代替y′1和y′0,可得 x1y11= cosβsinβ0.5h-0.5h×cosβ-0.5w×sinβ -sinβcosβ0.5w+0.5h×sinβ+0.5w×cosβ 001 x0y01 (3.22) 需要注意的是,在利用式(3.22)进行图像旋转变换时,计算得到的坐标值x1和y1一般不会是整数,但数字图像旋转后的坐标值必须是整数,因此应尽可能地取与x1和y1最接近的整数值。也正是因为这种近似,所以图像旋转后会有一定的改变,但这种改变并不明显。 【例3.7】图像旋转后,保持原图像幅面大小(不截断),即结果图像变大,程序运行结果如图3.14所示。 图3.14旋转后幅面放大的图像旋转变换结果 clc; clear all; close all; img=imread('d:\0_matlab图像课编程\girl.jpg'); [h w]=size(img); jiaodu=30; %顺时针旋转角度的初值,本次为30° theta=jiaodu/180*pi; %将旋转角度转换为弧度 rot=[cos(theta) -sin(theta) 0;sin(theta) cos(theta) 0;0 0 1]; %顺时针旋转 %rot=[cos(theta) sin(theta) 0;-sin(theta) cos(theta) 0;0 0 1]; %逆时针旋转 pix1=[1 1 1]*rot; %求变换后的新图像左上角像素(1, 1)的坐标 pix2=[1 w 1]*rot; %求变换后的新图像右上角像素(1, w)的坐标 pix3=[h 1 1]*rot; %求变换后的新图像左下角像素(h, 1)的坐标 pix4=[h w 1]*rot; %求变换后的新图像右下角像素(h, w)的坐标 %变换后图像的高度 height=round(max([abs(pix1(1)-pix4(1))+0.5 abs(pix2(1)-pix3(1))+0.5])); %变换后图像的宽度 width=round(max([abs(pix1(2)-pix4(2))+0.5 abs(pix2(2)-pix3(2))+0.5])); imgn=zeros(height,width); %生成变换后图像的0 值像素阵列,结果图像阵列初值 %取得x方向的负轴超出的偏移量 delta_x=abs(min([pix1(1) pix2(1) pix3(1) pix4(1)])); %取得y方向的负轴超出的偏移量 delta_y=abs(min([pix1(2) pix2(2) pix3(2) pix4(2)])); for i=1-delta_x:height-delta_x for j=1-delta_y:width-delta_y pix=[i j 1]/rot; %用变换后图像的点的坐标去寻找原图像点的坐标 %否则有些变换后的图像的像素点无法完全填充 float_X=pix(1)-floor(pix(1)); float_Y=pix(2)-floor(pix(2)); if pix(1)>=1 && pix(2)>=1 && pix(1) <= h && pix(2) <= w pix_up_left=[floor(pix(1)) floor(pix(2))];%4个相邻的点 pix_up_right=[floor(pix(1)) ceil(pix(2))]; pix_down_left=[ceil(pix(1)) floor(pix(2))]; pix_down_right=[ceil(pix(1)) ceil(pix(2))]; value_up_left=(1-float_Y)*(1-float_X);%计算相邻4个点的权重 value_up_right=float_Y*(1-float_X); value_down_left=(1-float_Y)*float_X; value_down_right=float_Y*float_X; imgn(i+delta_x,j+delta_y)=value_up_left*img(pix_up_left(1),pix_up_left(2))+... value_up_right*img(pix_up_right(1),pix_up_right(2))+ ... value_down_left*img(pix_down_left(1),pix_down_left(2))+ ... value_down_right*img(pix_down_right(1),pix_down_right(2)); end end end imshow(img); title('原图像'); figure; imshow(uint8(imgn)); title('旋转后图像'); 对例3.7中的相关编程思路和程序代码解译如下。 (1) 程序语句rot=[cos(theta) -sin(theta) 0; sin(theta) cos(theta) 0; 0 0 1]的含义为 rot=cos(theta)-sin(theta)0 sin(theta)cos(theta)0 001 (2) 语句pix1=[111]*rot的功能是求变换后结果图像左上角像素的坐标,计算结果是一个一维向量,其中pix1(1)是高度坐标,pix1(2)是宽度坐标值。 pix1=111cos(theta)-sin(theta)0 sin(theta)cos(theta)0 001 =cos(theta)+sin(theta)-sin(theta)+cos(theta)1] … 语句pix4=[h w 1]*rot的功能是求变换后结果图像右下角像素的坐标,计算结果是一个一维向量,其中pix4(1)是高度坐标,pix4(2)是宽度坐标值。 pix4=hw1cos(theta)-sin(theta)0 sin(theta)cos(theta)0 001 =[h·cos(theta)+w·sin(theta)-h·sin(theta)+w·cos(theta)1] (3) 语句height=round(max([abs(pix1(1)-pix4(1))+0.5 abs(pix2(1)-pix3(1))+0.5]))和语句width=round(max([abs(pix1(2)-pix4(2))+0.5 abs(pix2(2)-pix3(2))+0.5]))含义是: 当图像旋转一定角度后,把图像的四个角的像素点pix1、pix2、pix3、pix4中互为对角的两个顶点pix1和pix3的x(高度)值相减取绝对值再加0.5,并四舍五入取整作为旋转后结果图像的高; 把互为对角的两个顶点pix2和pix4的y(宽度)值相减取绝对值再加0.5,并四舍五入取整作为旋转后结果图像的宽。 例3.7中的相关函数及功能说明如下。 (1) round(x): 四舍五入取整。 (2) y=floor(x): 对x向下取整(即取不大于x的最大整数),值y为不大于取整后的x的最大整数。 (3) ceil(x): 返回不小于x的最小整数值,即向正无穷方向取整。 (4) max(x): ①若x是一个向量,则返回x中元素的最大值; 若x是一个矩阵,则以行的形式返回每一列元素的最大值。②max(x,[],2)以列的形式返回每一行元素的最大值; max(x,[],1)以行的形式返回每一列元素的最大值。③max(x,y)返回数值x与y中较大者。 (5) min(x): 求向量x中元素的最小值,其他格式类似于max。 (6) abs(x): 求x的绝对值。 2. 旋转前后幅面大小保持不变的图像旋转变换 设原图像被旋转角度β(弧度制)后,原图像中位于(x0,y0)处的像素点被移位至(x1,y1)处。在不考虑图像旋转后图像幅面是否超出原幅面大小的情况下,横轴为y轴、竖轴为x轴的xoy平面的旋转变换公式(3.16)即为图像顺时针旋转的图像变换公式。 x1y11=cosβ-sinβ0 sinβcosβ0 001x0y01 (3.23) 对应地,式(3.17)即为图像逆时针旋转的图像变换公式。 x1y11=cosβsinβ0 -sinβcosβ0 001x0y01(3.24) 在根据式(3.23)或式(3.24)对原图像进行旋转变换时,需要判断变换后的每个像素的坐标(x1,y1)是否超出了原图像的尺寸范围。只有那些x1 值和y1 值都没有超出图像尺寸范围的像素才得以保留,而其他像素由于其坐标超出了原图像尺寸而无法显示,所以要将其丢弃。 另外需要注意的是,当图像旋转的角度值为负值时,利用式(3.23)运算的结果相当于沿逆时针旋转; 利用式(3.24)运算的结果相当于沿顺时针旋转。 【例3.8】保持原图像尺寸大小不变(超出原图像大小部分被截断)的图像旋转MATLAB程序。 clc; clear; close all; img0=imread('d:\0_matlab图像课编程\girl.jpg'); %读入原始图像 [h,w,m] = size(img0);%获取图像大小 img1 = 255*ones(h,w,m); %构造结果矩阵,每个像素点默认初始化为255(白色) alfa = 15 * 3.1415926 / 180.0; % 旋转角度赋值(设为15°),并将其转换为弧度 tras=[cos(alfa) -sin(alfa) 0; sin(alfa) cos(alfa) 0; 0 0 1]; %顺时针旋转变换矩阵 %tras=[cos(alfa) sin(alfa) 0; -sin(alfa) cos(alfa) 0; 0 0 1];%逆时针旋转变换矩阵 for i = 1:h for j = 1:w temp = [i; j; 1]; %数学坐标(x=j,y=i) temp = tras * temp; %坐标变换,变换后像素坐标向量=变换矩阵×变换前坐标向量 x = uint16(temp(1, 1));%取出i值并转换成16位的无符号数据 y = uint16(temp(2, 1));%取出j值并转换成16位的无符号数据 %判断变换后的像素坐标是否越界,只保留原图像幅面大小范围内的像素值 if (x <= h) & (y <= w) & (x >= 1) & (y >= 1) img1(i, j,:) = img0(x, y,:); end end end; subplot(1,2,1); imshow(img0);%显示原图像 subplot(1,2,2); imshow(uint8(img1)); %显示旋转结果图像 例3.8的程序运行结果如图3.15(b)所示。当把程序中的第6行语句改成注释(在该行前面添加%),而执行程序中的第7行语句(去掉该行前面的%)时,运行结果如图3.15(c)所示。 图3.15旋转后幅面保持不变的图像旋转变换结果 例3.8中的相关函数及功能如下。 (1) ones(h,w,m): 建立一个大小为h×w,元素值为double类型的全1值矩阵。 (2) uint16(x): 将x映射到无符号16位范围内。 3.5.3图像镜像变换 图像镜像(image mirroring)变换分为图像水平镜像变换和图像垂直镜像变换两种。 1. 图像水平镜像 图像水平镜像(horizontal mirroring)是指以原图像为参照,使原图像和水平镜像结果图像与虚拟的垂直轴成对称关系,如图3.16(a)和图3.16(b)所示。 图3.16图像水平镜像结果示例 设图像的高度height为h,宽度width为w。在显示坐标中,原图像中位于(x0,y0)处的像素点,经水平镜像后在水平镜像结果图像上的对应像素点为(x1,y1)。根据图3.17的映射关系,则图像水平镜像变换可表示为 x1=x0 y1=w-y0+1(3.25) 图3.17图像水平镜像映射关系 式(3.25)的矩阵表示形式为 x1y11=100 0-1w+1 001 x0y01(3.26) 【例3.9】图像水平镜像MATLAB程序,程序运行结果如图3.16所示。 % 图像水平镜像MATLAB程序(horizontal_mirroring33.m) clc; clear; close all; img0=imread('d:\0_matlab图像课编程\lena.bmp'); [h,w]=size(img0);%获取矩阵的行数h和列数w for x0=1:h%把原图像最(偏)右边的列移到新图像的最(偏)左边 for y0=1:w result_img(x0,w-y0+1)=img0(x0,y0);%根据式(3.25)进行坐标变换 end end subplot(1,2,1);imshow(img0);title('原图像');%显示原图像 subplot(1,2,2);imshow(result_img);title('水平镜像结果图像'); 2. 图像垂直镜像 图像垂直镜像(vertical mirroring)是指以原图像为参照,使原图像和垂直镜像结果图像与虚拟的水平轴成对称关系,如图3.18所示。 设图像的高度height为h,宽度width为w。在显示坐标中,原图像中位于(x0,y0)处的像素点,经垂直镜像后在垂直镜像结果图像上的对应像素点为(x1,y1)。根据图3.19的映射关系,则图像垂直镜像变换可表示为 x1=h-x0+1 y1=y0(3.27) 式(3.27)的矩阵表示形式为 x1y11=-10h+1 010 001x0y01(3.28) 图3.18图像垂直镜像结果示例 图3.19图像垂直镜像映射关系 【例3.10】图像垂直镜像MATLAB程序,程序运行结果如图3.18所示。 clc; clear; close all; img0=imread('d:\0_matlab图像课编程\lena.bmp'); [h,w]=size(img0);%获取图像矩阵的行数h和列数w for x0=1:h% 把原图像最/偏下边的行移到新图像最/偏上边的行 for y0=1:w result_img(h-x0+1,y0)=img0(x0,y0);%根据式(3.27)进行坐标变换 end end subplot(2,1,1); imshow(img0); % 显示原图像 subplot(2,1,2); imshow(result_img); % 显示垂直镜像结果图像 3.5.4图像转置变换 图像转置(image transpose)变换是指将图像显示坐标的x轴与y轴对换,显示效果示例如图3.20所示。 设原图像位于(x0,y0)处的像素点,经图像转置变换后在转置变换结果图像上的对应像素点为(x1,y1)。根据图3.21的映射关系,则图像转置变换可表示为 x1=y0 y1=x0 (3.29) 式(3.29)的矩阵表示形式为 x1y11=010 100 001x0y01(3.30) 图3.20图像转置变换示例 图3.21图像转置映射关系 需要特别注意的是,图像的转置变换与图像的旋转变换是不一样的。原图像不论是顺时针旋转90°,还是逆时针旋转90°,都不会得到图像转置后的结果。 【例3.11】图像转置MATLAB程序,程序运行结果如图3.20所示。 clc; clear; close all; img0=imread('d:\0_matlab图像课编程\lena.bmp'); [h,w]=size(img0);% 获取图像的行数h和列数w for i=1:h for j=1:w result_img(j,i) = img0(i,j);%根据式(3.29)进行坐标变换 end end subplot(1,2,1); imshow(img0); title('转置前原图像'); %显示原图像 subplot(1,2,2); imshow(result_img); title('转置后的图像'); %显示转置结果图像 3.5.5图像缩小与放大 图像缩放(image scaling)是指对图像进行缩小或放大,即对数字图像的大小进行调整的过程。图像缩放是一种非平凡的过程,需要在处理效率以及结果的平滑度(smoothness)和清晰度(sharpness)上做一个权衡。 设原图像中位于(x0,y0)处的像素点,经对原图像的行和列按相同比例r缩放后,在缩放后的结果图像上的对应像素点为(x1,y1),则图像缩放前后像素点的坐标可表示为 x1=rx0 y1=ry0(3.31) 图像缩放的矩阵表示形式为 x1y11=r00 0r0 001x0y01(3.32) 其中,当01时为放大原图像。 1. 缩小图像 缩小图像(shrink image)的目的一般有两个: 一是为了使缩小后的图像符合显示区域的大小要求; 二是为了生成被缩小图像(原图像)的缩略图。缩小后的图像的平滑度和清晰度相对于原图像都有所增强。 缩小图像也称为下采样(subsampled)或降采样(downsampled)。对于一般的行数和列数都为偶数的图像来说,一种方法是只取原图像偶数行和偶数列交叉处的像素,如图3.22所示; 另一种方法是只取原图像奇数行和奇数列交叉处的像素,如图3.23所示。这种缩小图像方法的结果从整体上看,就是将原图像缩小到原来大小的1/4。 图3.22仅取偶数行和偶数列像素缩小原图像 图3.23仅取奇数行和奇数列像素缩小原图像 如果要再将缩小后的图像缩小为原来的1/4,只要在前述缩小的图像的基础上,采用原来方法进行即可。当然还有其他一些不按整数比例缩小图像的方法,限于篇幅,此处不再赘述。 【例3.12】仅取奇数行和奇数列像素的图像缩小MATLAB程序,程序运行结果如图3.24所示。 % 按整倍数缩小图像的MATLAB程序 clc; clear; close all; img0=imread('d:\0_matlab图像课编程\lena.jpg'); [h,w]=size(img0); N=2;% 图像缩小倍数(每N行/列留1行/列) result_row = round(h/N);result_col = round(w/N); % 结果图像行数和列数 temp_img = zeros(result_row,result_col);%生成全零值结果图像阵列 x1 =1;%保留的行方向的初始行数值 for x0 = 1:N:h%行数按步长N=2循环,即去掉偶数行 y1=1;%保留地列方向的初始列数值 for y0 = 1:N:w%列数按步长N=2循环,即去掉偶数列 temp_img(x1,y1) = img0(x0,y0);%像素值赋值 y1 = y1+1; end x1 = x1+1; end result_img=uint8(temp_img);%转换成8位图像 figure; imshow(img0); title('原图像');%显示原图像 figure; imshow(result_img); title('缩小1倍后的图像'); 2. 最近邻域插值放大图像方法 放大图像(enlarge image)的目的一般是为了使放大后的图像更好地显示在更高分辨率的显示设备上。放大图像的方法相对比较多,也相对复杂一些,从了解图像放大原理的角度,下面介绍最基本也是最典型的最近邻域插值图像放大方法。 1) 按整数倍数放大图像的最近邻域插值法 按整数倍数放大图像(比如将图像放大两倍)的最近邻域插值法的基本思想是: 将原图像中的每一个原像素原封不动地复制映射到放大后的新图像的4个像素中。该方法的原理如图3.25所示。 图3.24例3.12程序运行结果 图3.25按最近邻域插值法将图像放大4倍示例 2) 按非整数倍数放大图像的最近邻域插值法 设放大前的图像称为原图像,其在显示坐标的x方向和y方向的坐标值分别用xold和yold表示,图像高度(x方向)用hold表示,图像宽度(y方向)用wold表示。放大后的图像称为目标(新)图像,其在显示坐标的x方向和y方向的坐标值分别用xnew和ynew表示,图像高度(x方向)用hnew表示,图像宽度(y方向)用wnew表示。则按非整数倍数放大图像的最近邻域插值法的原图像和目标图像的坐标关系可表示为 xold=IntegerRound(xnew×(hold/hnew)) yold=IntegerRound(ynew×(wold/wnew)) (3.33) 当已知图像放大系数m时,由m=hnew/hold和xold=xnew×(hold/hnew)=xnew/(hnew/hold)=xnew/m得 xold=IntegerRound(xnew/m) yold=IntegerRound(ynew/m)(3.34) 下面用一个例子来说明按非整数倍数放大图像的最近邻域插值法的应用方法。 【例3.13】设已知有一个3×3的灰度图像,如图3.26(a)所示。利用按非整数倍数放大图像的最近邻域插值法将该图像放大为 4×4的图像,如图3.26(b)所示。 图3.26按非整数倍放大图像的最近邻域插值法的放大结果示例 解: 在插值放大后的目标图像中根据式(3.31)逐个地计算从(0,1)至(3,3)的每个像素的值。 对于目标图像中坐标为(0,0)处的像素,因为有 xold=xnew×(hold/hnew)=0×(3/4)=0 yold=ynew×(wold/wnew)=0×(3/4)=0 即目标图像中位于(0,0)处的像素值应是原图像中位于(0,0)处的像素值,该值为234。 对于目标图像中坐标为(0,1)处的像素,因为有 xold=xnew×(hold/hnew)=0×(3/4)=0 yold=ynew×(wold/wnew)=1×(3/4)=0.75≈1 即目标图像中位于(0,1)处的像素值应是原图像中位于(0,1)处的像素值,该值为38。 同理,可得目标图像中位于(0,2)处和(0,3)处的像素值都是22; 位于(1,0)处、(1,1)处、(1,2)处和(1,3)处的像素值分别是67、44、12和12; 位于(2,0)处、(2,1)处、(2,2)处和(2,3)处的像素值分别是89、65、63和63; 位于(3,0)处、(3,1)处、(3,2)处和(3,3)处的像素值分别是89、65、63和63。放大后的结果图像如图3.19(b)所示。 需要注意的是,由于MATLAB的阵列下标是从(1,1)开始算起的,上述的新图像坐标范围就会是(1∶4,1∶4)而不是(0∶3,0∶3),加上下标的四舍五入取整影响,得到的放大后的新图像为图3.26(c)。 【例3.14】以任意倍数m放大图像的MATLAB程序,程序运行结果如图3.27所示。 clc; clear all; close all; img=imread('d:\0_matlab图像课编程\girl.jpg'); [h_old, w_old]=size(img); m = input('\n请输入任意值的图像放大倍数 k=');%整数、小数或分数值 h_new = round(m*h_old);%确保非整数的k倍放大后,图像大小为整数 w_new = round(m*w_old); for i =1:h_new%逐一为像素点赋值 for j=1:w_new %变换公式(3.33),x_old=x_new*(h_old/h_new),y_old=y_new*(h_old/h_new) x_old = round(i/m); ifx_old>h_old x_old = h_old; else x_old(x_old<1) = 1; end y_old = round(j/m); y_old(y_old>w_old) = w_old; y_old(y_old<1) = 1; img1(i,j) = img(x_old,y_old); end end figure, imshow(img); axis on; title(['原图像(大小:',num2str(h_old),'×',num2str(w_old),')']); figure; imshow(img1); axis on; title(['放大后的图像(大小:',num2str(h_new),'×',num2str(w_new),')']); 图3.27最邻近插值图像放大2倍程序运行结果 在例3.14 中,ifelseend语句为 ifx_old>h_old x_old = h_old; else x_old(x_old<1) = 1; end 如果用以下语句代替,将会使程序显得更简洁(这就是MATLAB不同于其他程序语言的独特之处)。 x_old(x_old>h_old) = h_old; x_old(x_old<1) = 1; 例3.14中的相关函数及功能说明如下。 (1) axis on: 显示坐标轴上的标记、单位和格栅。 最近领域插值法放大的图像可保留图像中所有的原始信息,但是会产生锯齿现象和马赛克现象。为了克服最近领域插值法的不足,人们进一步提出了双线性插值法、三次样条插值和基于边缘的图像插值方法等,下面介绍双线性插值法,其余方法感兴趣的读者可以参考有关文献。 (2) a=input('...'): 接收用户输入,输入可以是一个值,也可以是一个矩阵(用一对方括号括住,不同的行用分号分隔),并把输入值(或矩阵值)保存到变量a中。引号里是提示信息,可以根据输入格式加入一定的换行(\n)符号。 3. 双线性插值放大图像方法 双线性插值法通过输入图像到输出图像的映射,即通过计算输出像素被映射到输入图像中4个像素之间的非整数位置的像素点灰度值,并将具有该灰度值的像素点插入该位置,来实现对输入图像的放大。 已知像素点(0,0)、(0,1)、(1,0)和(1,1)如图3.28(a)所示,要插值的点为(x,y)。双线性插值的基本思路是: 首先在x方向上线性插值,在(0,0)和(1,0)两个点之间插入点(x,0),在(0,1)和(1,1)两个点之间插入点(x,1); 然后在y方向线性插值,即通过计算出的点(x,0)和(x,1),在y方向上插值计算出点(x,y)。在单位正方形顶点的值已知的情况下,正方形内任意点f(x,y)的值可由如下的双线性方程得到。 f(x,y)=ax+by+cxy+d(3.35) 其中,a、b、c和d是待定常数,其值由正方形4个顶点的值确定。 图3.28双线性插值运算图示 双线性插值运算如图3.28(b)所示。首先,在x方向上作线性插值,对上端的两个点(0,0)和(1,0)进行线性插值可得 f(x,0)=f(0,0)+x[f(1,0)-f(0,0)](3.36) 同理,对低端的两个点(0,1)和(1,1)进行线性插值可得 f(x,1)=f(0,1)+x[f(1,1)-f(0,1)](3.37) 然后,在y方向上作线性插值,有 f(x,y)=f(x,0)+y[f(x,1)-f(x,0)](3.38) 将式(3.36)和式(3.37)代入式(3.38),有 f(x,y)=f(0,0)+x[f(1,0)-f(0,0)]+ y[f(0,1)+x[f(1,1)-f(0,1)]-f(0,0)-x[f(1,0)-f(0,0)]] 整理上式,即可得双线性插值公式为 f(x,y)=[f(1,0)-f(0,0)]x+[f(0,1)-f(0,0)]y+ [f(1,1)+f(0,0)-f(0,1)-f(1,0)]xy+f(0,0) (3.39) 基于上述算法原理,就可以在一幅输入图像上,根据各像素的4个相邻点的灰度值,分别在x和y方向上进行二次线性插值,得到结果图像的过程示意如图3.29所示。 图3.29利用双线性插值算法对图像进行插值过程示例 【例3.15】双线性插值放大图像的MATLAB程序,程序运行结果如图3.30所示。 clc; clear all; close all; img=imread('d:\0_matlab图像课编程\girl.jpg'); zmf=2; %放大因子(倍数)赋初值,应该大于1,这里设为2 [h,w,c] = size(img); %扩展原图像img的像素阵列的边缘,得到临时图像img1 img2 = zeros(h+2,w+2,c); %创建全零值的结果图像,结果图像赋初值 img1(1,2:w+1)=img(1,:);%给扩展图像img1的最上一行赋值 img1(1,1)=img(1,1); %给扩展图像img1的左上角像素赋值 img1(1,w+2)=img(1,w);%给扩展图像img1的右上角像素赋值 img1(2:h+1,1)=img(:,1);%给扩展图像img1的最左一列赋值 img1(2:h+1,2:w+1)=img(1:h,1:w); %扩展图像img1的中间赋值原图像的像素值 img1(2:h+1,w+2)=img(:,w); %给扩展图像img1的最右一列赋值 img1(h+2,2:w+1)=img(h,:); %给扩展图像img1的最下一行赋值 img1(h+2,1)=img(h,1);%给扩展图像img1的左下角像素赋值 img1(h+2,w+2)=img(h,w);%给扩展图像img1的右下角像素赋值 %figure; imshow(img1);title('四周扩展后的原图像'); %根据缩放因子得到新图像的大小,并创建新图像 h1 = round(h*zmf);%计算放大后的图像高度,就近取整 w1 = round(w*zmf);%计算放大后的图像宽度,就近取整 img2 = zeros(h1,w1,c); %创建全零值的结果图像,结果图像赋初值 %将新图像的某个像素(i,j)映射到原始图像(i0,j0)处,并插值 for j = 1:w1%对新图像按列逐个元素扫描 for i = 1:h1 i0 = (i-1)/zmf; j0 = (j-1)/zmf; ii = floor(i0); jj = floor(j0);%向下取整 u = i0 - ii; v = j0 - jj; ii = ii + 1; jj = jj + 1; img2(i,j,:) = (1-u)*(1-v)*img1(ii,jj,:) +(1-u)*v*img1(ii,jj+1,:)... + u*(1-v)*img1(ii+1,jj,:) +u*v*img1(ii+1,jj+1,:); end end img2 = uint8(img2); %显示原图像与放大后图像,并显示坐标轴上的标记和单位 figure, imshow(img); axis on; title(['原图像(大小: ',num2str(h),'×',num2str(w),'×',num2str(c),')']); figure; imshow(img2); axis on; title(['放大后的图像(大小: ',num2str(h1),'×',num2str(w1),'×',num2str(c)',')']); 图3.30双线性插值放大2倍图像程序运行结果 在例3.15中,第6行至第14行语句的功能是让(h+2)×(w+2)得到img1图像,中间是h*w的原图像,并把原图像的最外一行和最外一列像素赋值给img1的最外一行和最外一列。其中,第10行的语句img1(2:h+1,2:w+1)=img(1:h,1:w)的功能相当于下列双层for循环的功能。由此可以进一步体会MATLAB强大的语句表达能力。 for i=1:h for j=1:w img1(i+1,j+1)=img(i,j); end end 习题3 1. 解释下列名词概念。 (1) 灰度图像的对比度(2) 归一化直方图 (3) 图像镜像(4) 图像转置 2. 在有些图像处理系统中,为什么要对输入图像的像素亮度进行对数运算处理? 3. 什么是图像直方图?灰度直方图有哪些性质? 4. 设有一灰度图像的直方图,请回答下列问题: (1) 当该直方图偏左时,该图像的亮度和对比度有什么特征? (2) 当该直方图偏右时,该图像的亮度和对比度有什么特征? (3) 当该直方图挤在某个狭小区域时,该图像的对比度有什么特征? 5. 简述图像变化检测的原理及其应用领域。 6. 假设要把一幅图像放大为原来大小的两倍,请简述其放大原理或实现方法。 7. 已知有如图3.31所示的原图像: 1246 5423 4321 5678 图3.31习题3.7图 (1) 请给出该图像的水平镜像结果图像。 (2) 请给出该图像的垂直镜像结果图像。 (3) 请给出该图像转置后的结果图像。 (4) 请给出该图像向左旋转90°后的结果图像。 8. 编写一个实现图像水平镜像功能的MATLAB程序,并显示原图像和镜像结果图像。