第3章〓图像基础性运算 本章思维导图 图像处理的过程是对图像像素值进行运算的过程,处理效果不同,运算对应的名称也不同。本章学习在不同的图像处理算法中经常用到的运算,即基础性运算,包括点运算、邻域运算、插值运算、几何变换、代数运算、上采样和下采样。 3.1点运算 对图像进行点运算时,每个像素的输出值只取决于其自身的输入和相关参数,与其他像素无关,是一种常用的处理方法,如灰度级变换、代数运算。 【例3.1】设计程序,增大office.jpg图像的亮度。 解: 程序如下。 clear,clc,close all; Image=im2double(imread('office.jpg')); result=4*Image; subplot(121),imshow(Image),title("原图"); subplot(122),imshow(result),title("增大亮度图"); 运行程序,原图如图31(a)所示,图像整体很暗; 对图像进行点运算,将每个像素的像素值都增大为原来的4倍,处理后的像素值由自身原来的值和增大的倍数决定,与周围像素的值无关。增大亮度图如图31(b)所示,超出像素值表达范围的会被限幅为最大值。 图31点运算示例 3.2邻域运算 邻域运算是每个像素点和其周围邻点共同参与的运算,通常通过模板操作进行,每个像素的输出值由其周围邻域内像素的值和模板中的数值共同决定。模板也叫滤波器、核、掩膜或窗口,用一个小的二维阵列表示(如3×3)。通常把对应的模板上的值称为加权系数。 1. 相关运算 相关运算如图32所示。将模板在图像上移动,每移动到一个位置,即模板的中心对准1像素,模板所覆盖范围内的像素值分别与模板内对应系数相乘,乘积求和即为该像素的输出值,如式(31)所示。模板顺次移动,每个位置处计算出一个值,最终得到一幅新图像,如式(32)所示。 gx,y=∑m,nfx+m,y+nhm,n(31) g=fh(32) 其中,h是模板。 图32相关运算示意图 2. 卷积运算 对式(31)进行变形,将f中的偏移量符号反向,得 gx,y=∑m,nfx-m,y-nhm,n =∑m,nfm,nhx-m,y-n(33) 称为卷积运算。图像的卷积运算表达为 g=fh(34) 由式(31)和式(33)可以看出,卷积运算是将模板进行翻转(上下换位、左右换位)后,再进行相关运算,当模板中心对称时,两者运算结果一致。 邻域运算的效果由模板决定,模板中数据取值不同,处理效果也不同。 3. 边界填塞 当模板中心与图像外围像素点重合时,模板的部分行和列可能会处于图像之外,没有相应的像素值与模板数据进行运算。对于这种问题,需要采用一定的措施来解决。 假设模板是大小为n×n的方形模板,对于图像中行和列方向上距离边缘小于(n-1)/2个像素的区域,根据不同要求,可以采用不同的处理方法。 (1) 不处理该区域中原来的像素。例如,对图像平滑去噪,外围像素即使存在一些噪声,一般不会影响对图像内容的理解,可以保留这些像素值。 (2) 在图像边缘以外再补上(n-1)/2行和(n-1)/2列像素。不同的情况下,有不同的填塞方法,例如,可以将对应的像素值置为零,设为固定的值,复制或者镜像反射外围像素值等方式。 【例3.2】一幅图像为33333 37773 371573 37773 33333,模板为15010111010,进行卷积运算,外围像素保持原像素值不变。 解: 由于模板中心对称,卷积运算和相关运算一致。以模板中心点对准像素15为例,模板覆盖范围内像素值为7777157777,9个数据分别和模板中的9个值对应相乘,乘积相加得8.6,取整,输出图像中该点的值变为9。对图像中每一点进行相同的处理,即卷积运算。 当模板中心点对准外围像素,如左下角像素3,模板覆盖范围内像素值为3733,有5个数据为空,不进行相乘相加运算,保留像素值3不变,其他外围像素同样,输出结果如图33(a)所示。或者将5个数据补充为0,即037033000和模板元素对应相乘再相加,得1.8,取整,输出为2,其他外围像素同样,输出结果如图33(b)所示。两种处理方法仅影响外围像素值。 33333358533898335853333332333235853389833585323332 (a) 保留外围像素不变的计算结果(b) 外围像素外补0的计算结果 图33卷积运算1 例题中对中心像素和上、下、左、右4个邻点取平均,能够实现抑制噪声的功能。 关于模板运算的含义及示例运算过程,请扫二维码,查看讲解。 微课视频 【例3.3】对shape.png图像采用取值全为1/25的5×5模板进行卷积运算,外围像素保持原像素值不变。 解: 程序如下。 clear,clc,close all; Image=rgb2gray(im2double(imread('shape.png'))); [height,width]=size(Image); H=[1 1 1 1 1;1 1 1 1 1;1 1 1 1 1;1 1 1 1 1;1 1 1 1 1;]; H=H/25; %定义5×5的模板 [h,w]=size(H); H=flip(flip(H,1),2); %模板上下、左右翻转 r1=floor(h/2); r2=floor(w/2); %模板半径 result=Image; %将原图赋予result,便于保留边缘像素值 for y=1+r1:height-r1 %模板遍历图像时避开外围像素 for x=1+r2:width-r2 neighbors=Image(y-r1:y+r1,x-r2:x+r2); %获取模板覆盖范围内像素值矩阵 Parray=neighbors.*H; %模板系数和像素值对应相乘 result(y,x)=sum(Parray(:)); %乘积求和作为当前点输出 end end subplot(121),imshow(Image),title('原灰度图'); subplot(122),imshow(result),title('卷积结果图'); 程序运行结果如图34所示。 图34卷积运算2 【例3.4】设计程序,采用MATLAB中的conv2函数实现对shape.png图像的卷积运算,卷积核h=-1-1-1000111。 解: 程序如下。 clear,clc,close all; Image=rgb2gray(im2double(imread('shape.png'))); H=[-1 -1 -1;0 0 0;1 1 1]; result=conv2(Image,H,'same'); subplot(121),imshow(Image),title('原灰度图'); subplot(122),imshow(result),title('卷积结果图'); 程序运行结果如图35所示。 图35卷积运算3 3.3插值运算 在图像处理过程中,可能会产生一些原图中没有的新的像素点,即像素坐标非整数,给这些像素点赋值需要应用插值运算,即利用已知邻近像素点的灰度值产生未知像素点的灰度值。插值效果的好坏将直接影响图像显示的视觉效果。常用的插值方法有最邻近插值(Nearest Neighbor Interpolation)、双线性插值(Bilinear Interpolation)、双三次插值(Bicubic Interpolation)等。 1. 最邻近插值 最邻近插值是最简单的插值方法,将新像素点的像素值设为距离它最近的输入像素的像素值。当图像中邻近像素之间灰度级有较大的变化时,该算法产生的新图像的细节比较粗糙。 2. 双线性插值 双线性插值原理图如图36所示,对于一个插值点x+a,y+b(其中x、y均为非负整数,0≤a,b≤1),则该点的值fx+a,y+b可由原图像中坐标为x,y、x+1,y、x,y+1、x+1,y+1所对应的4个像素的值决定: fx,y+b=fx,y+bfx,y+1-fx,y fx+1,y+b=fx+1,y+bfx+1,y+1-fx+1,y fx+a,y+b=fx,y+b+afx+1,y+b-fx,y+b(35) 可以看出,双线性插值是根据非整数像素距周围4个像素点的距离比,由4个邻点像素值进行线性插值,这种方法具有防锯齿效果,新图像拥有较平滑的边缘。 图36双线性插值原理图 3. 双三次插值 双三次插值是一种较复杂的插值方式,在计算新像素点的值时,要将周围的16个点全部考虑进去。双三次插值图像边缘比双线性插值图像更平滑,同时也需要更大的计算量。 点x+a,y+b处的像素值fx+a,y+b可由式(36)计算。 fx+a,y+b=ABC(36) 其中,A=sa+1sasa-1sa-2 B=fx-1,y-1fx-1,yfx-1,y+1fx-1,y+2fx+0,y-1fx+0,yfx+0,y+1fx+0,y+2fx+1,y-1fx+1,yfx+1,y+1fx+1,y+2fx+2,y-1fx+2,yfx+2,y+1fx+2,y+2 C=sb+1sb+0sb-1sb-2sk=1-2×k2+k3,0≤k<1 4-8×k+5×k2-k3,1≤k<2 0,k≥2 3.4几何变换 几何变换是指对图像进行平移、旋转、镜像、缩放、错切、转置等变换,改变图像的大小、形状和位置,常用于图像变形、几何失真图像的校正、图像配准、影像特技处理等。 3.4.1图像几何变换原理 图像几何变换将图像中任一像素映射到一个新位置,是一种空间变换,关键在于确定变换前后图像中点与点之间的映射关系,明确原图像任意像素点变换后的坐标,或者变换后的图像像素在原图像中的坐标位置,对新图像像素点赋值而产生新图像。 1. 几何变换的齐次坐标表示 用n+1维向量表示n维向量的方法称为齐次坐标表示法。图像空间一个点x,y用齐次坐标表示为xy1,和某个变换矩阵T=abkcdmpqs相乘变为新的点x′y′1,如式(37)所示,这种变换称为几何变换。 x′y′1=abkcdmpqsxy1(37) 若T=abkcdm001,则称这种有6个参数的变换为仿射变换; 若T=abkcdmpq1,称这种有8个参数的变换为投影变换。 二维图像可以表示为3×MN的点集矩阵x1x2…xMNy1y2…yMN11…1,实现二维图像几何变换的一般过程如下: 变换后的点集矩阵=变换矩阵T×变换前的点集矩阵。 2. 图像几何变换过程 图像几何变换可以采用前向映射法和后向映射法实现。前向映射法计算原图像中像素点x,y在新图像中的对应点x′,y′,并给x′,y′赋值fx,y。但是,如果x′,y′为非整数像素,需要将x′,y′取整,然后再复制fx,y,或者使用加权的方法将fx,y分配给周围4个近邻,这些操作会丢失细节; 同时,前向映射会产生裂缝或空洞,即新图像中某些像素没有赋值,需要再用邻近的像素点填补,进一步导致图像模糊,在图像放大时更为明显。 实际几何变换中经常采用后向映射法,后向映射法计算新图像中的像素点在原图像中的对应点,并反向赋值,具体步骤如下。 (1) 根据不同的几何变换公式计算新图像的尺寸。 (2) 根据几何变换的反变换,确定新图像中的每一点在原图像中的对应点。 (3) 按对应关系给新图像中各像素赋值。 ① 若原图像中的对应点存在,直接将其值赋给新图像中的点。 ② 若原图像中的对应点坐标超出图像宽高范围,直接赋背景色。 ③ 若原图像中的对应点坐标在图像宽高范围内,但坐标非整数,采用插值的方法计算该点的值,并赋给新图像。 3.4.2图像平移 图像平移是将一幅图像上的所有点都按照给定的偏移量沿x轴、y轴移动,平移后的图像与原图像相同,内容不发生变化,只是改变了原有景物在画面上的位置。 将点x,y进行平移后,移到点x′,y′处,其中x轴方向的平移量为Δx,y轴方向的平移量为Δy,则平移变换为 x′y′1=10Δx01Δy001xy1(38) 平移变换求逆,得 xy1=10-Δx01-Δy001x′y′1(39) 这样,平移后图像上每一点x′,y′都可在原图像中找到对应点x,y。 如果图像经过平移处理后,不想丢失被移出的部分图像,可将可视区域的宽度扩大Δx,高度扩大Δy。 【例3.5】根据式(38)和式(39),采用后向映射法实现图像平移,分别沿x轴、y轴平移20像素。 解: 程序如下。 clear,clc,close all; Image=im2double(imread('lotus.jpg')); %读取图像并转换为double型 [h,w,c]=size(Image); %获取图像尺寸 NewImage=ones(h,w,c); %新图像初始化 deltax=20; deltay=20; %指定平移量 for x=1:w for y=1:h %循环扫描新图像中的点 oldx=x-deltax; oldy=y-deltay; %确定新图像中点在原图中的对应点 if oldx>0 && oldx<w+1 && oldy>0 && oldy<h+1 NewImage(y,x,:)=Image(oldy,oldx,:); %若对应点在图像内,则赋值 end end end subplot(121),imshow(Image),title('原图'); subplot(122),imshow(NewImage),title('平移后的图像'); 程序运行结果如图37所示。其中,图37(a)为原始图像,图37(b)为分别沿x、y方向平移20像素后的结果,图37(c)在图37(b)的处理结果基础之上把可视区域进行了扩大。 图37图像平移变换实例 由于平移前后的图像相同,而且图像上的像素顺序放置,所以图像的平移也可以通过直接逐行地复制图像实现。 MATLAB中采用affinetform2d函数定义二维仿射几何变换,采用imwarp实现几何变换,理解原理后,可以采用函数实现图像的几何变换。 【例3.6】采用函数imwarp、affinetform2d实现图像的平移变换。 解: 程序如下。 clear,clc,close all; Image=imread('lotus.jpg'); [h,w,c]=size(Image); deltax=20; deltay=20; newh=h+abs(deltay); neww=w+abs(deltax); %平移后图像的尺寸 tform=affinetform2d([1 0 deltax; 0 1 deltay; 0 0 1]); %定义几何变换,参数为变换矩阵 [xLimitsOut,yLimitsOut]=outputLimits(tform,[1 w],[1 h]);%估计输出范围 if deltax<0 xLimitsOut(2)=xLimitsOut(2)+abs(deltax); else xLimitsOut(1)=xLimitsOut(1)-abs(deltax); end if deltay<0 yLimitsOut(2)=yLimitsOut(2)+abs(deltay); else yLimitsOut(1)=yLimitsOut(1)-abs(deltay); end %本段代码调整扩大尺寸的图像中非背景区域的坐标值,以便正确显示 R=imref2d([newh,neww],xLimitsOut,yLimitsOut); %定义扩大尺寸,输出图像对象属性 NewImage=imwarp(Image,tform,'FillValue',255,'OutputView',R);%扩大尺寸几何变换 figure,imshow(Image),title('原图'); figure,imshow(NewImage),title('平移后的图像'); 程序运行结果如图37所示。 3.4.3图像镜像 设图像的分辨率为M×N,采用像素坐标系,图像镜像变换如式(310)所示,可以看出,镜像就是左右、上下或对角对换。 水平镜像: x′y′1=-10M-1010001xy1 垂直镜像: x′y′1=1000-1N-1001xy1(310) 对角镜像: x′y′1=-10M-10-1N-1001xy1 【例3.7】采用MATLAB中的矩阵翻转函数实现图像镜像变换,并将镜像图像拼接成大图。 解: 程序如下。 clear,clc,close all; Image=imread('dog.jpg'); HImage=fliplr(Image); %左右翻转,即水平镜像 VImage=flipud(Image); %上下翻转,即垂直镜像 CImage=flip(HImage,1); %左右翻转后再上下翻转,即对角镜像 mosaic=[Image HImage;VImage CImage]; %拼成一幅大图 imshow(Image),title('原始图像'); figure,imshow(mosaic),title('镜像图像拼接'); 程序运行,镜像拼接效果如图38所示。 图38镜像图像拼接 3.4.4图像旋转 图像旋转是指以图像中的某一点为原点,以逆时针或顺时针方向将图像上的所有像素都旋转一个相同的角度。经过旋转变换后,图像的大小一般会改变,并且图像中的部分像素可能会旋转出可视区域范围,因此需要扩大可视区域范围以显示所有的图像。 图39图像旋转示意图 1. 图像旋转的原理 设原图像中点x,y绕原点逆时针旋转θ角后的对应点为x′,y′,如图39所示。 在旋转变换前,原图像中点x,y的坐标表达式为 x=r·cosα y=r·sinα(311) 逆时针旋转θ角后为 x′=r·cos(α-θ)=x·cosθ+y·sinθ y′=r·sin(α-θ)=-x·sinθ+y·cosθ(312) 则图像旋转变换的矩阵表达为 x′y′1=cosθsinθ0-sinθcosθ0001xy1(313) 若顺时针旋转,则角度θ取负值。 绕原点旋转的反变换为 x=x′cosθ-y′sinθ y=x′sinθ+y′cosθ(314) 图310绕原点逆时针 旋转示意图 2. 图像旋转变换过程 1) 确定旋转后新图像尺寸 绕原点逆时针旋转示意图如图310所示: xOy为原始图像坐标系,图像4个角标注为1、2、3、4,旋转后为1′、2′、3′、4′,新图像坐标系表示为x″O″y″。 设原始图像大小为M×N,以图像起始点作为坐标原点,则原始图像4个角坐标分别为 x1,y1=0,0,x2,y2=M-1,0, x3,y3=M-1,N-1,x4,y4=0,N-1。 按照逆时针旋转公式,即式(312),旋转后,4个点在原坐标系中的坐标为 (x′1,y′1)=(0,0) (x′2,y′2)=((M-1)cosθ,-(M-1)sinθ) (x′3,y′3)=((M-1)cosθ+(N-1)sinθ,-(M-1)sinθ+(N-1)cosθ) (x′4,y′4)=((N-1)sinθ,(N-1)cosθ)(315) 令max x′和min x′分别为坐标值x′1,x′2,x′3,x′4的最大值和最小值,max y′和min y′分别为坐标值y′1,y′2,y′3,y′4的最大值和最小值,则新图像的宽度M′和高度N′为 M′=max x′-min x′+1 N′=max y′-min y′+1(316) 2) 坐标变换 对于新图像中的像素点x″,y″,x″∈0,M′-1,y″∈0,N′-1,先进行平移变换,变换到原像素坐标系 x′=x″+min x′ y′=y″+min y′(317) 3) 旋转反变换 对于每一个点x′,y′,利用旋转变换的反变换式(314),在原图像中找对应点。 4) 给新图像赋值 按对应关系直接给新图像中各像素赋值,或采用插值方法给新图像中各像素赋值。 【例3.8】有一幅图像fx,y=596058615957625655,以图像原点为坐标原点,将其逆时针旋转30°。 解: (1) 确定旋转后新图像的分辨率。按照式(315)计算图像4角点旋转后的坐标为 (x′1,y′1)=(0,0) (x′2,y′2)=(2cos30°,-2sin30°)=(1.732,-1) (x′3,y′3)=(2cos30°+2sin30°,-2sin30°+2cos30°)=(2.732,0.732) (x′4,y′4)=(2sin30°,2cos30°)=(1,1.732) max x′=2.732min x′=0max y′=1.732min y′=-1 计算新图像分辨率为 M′=max x′-min x′+1=3.732≈4 N′=max y′-min y′+1=3.732≈4 所以,新图像中每一点x″,y″满足: x″∈0,3,y″∈0,3。 (2) 对于新图像中的点x″,y″,先进行平移变换,变换到原像素坐标系x′,y′,再利用旋转变换的反变换,在原图像中找对应点x,y,并赋值。对应关系如表31所示。 表31绕原点旋转像素点对应关系 x″,y″ x′,y′ x,y 最邻近点 x″,y″ x′,y′ x,y 最邻近点 (0,0) (0,-1) (0.5,-0.866) (1,-1) (1,0) (1,-1) (1.366,-0.366) (1,0) (0,1) (0,0) (0,0) (0,0) (1,1) (1,0) (0.866,0.5) (1,1) (0,2) (0,1) (-0.5,0.866) (-1,1) (1,2) (1,1) (0.366,1.366) (0,1) (0,3) (0,2) (-1,1.732) (-1,2) (1,3) (1,2) (-0.134,2.232) (0,2) (2,0) (2,-1) (2.232,0.134) (2,0) (3,0) (3,-1) (3.098,0.634) (3,1) (2,1) (2,0) (1.732,1) (2,1) (3,1) (3,0) (2.598,1.5) (3,2) (2,2) (2,1) (1.232,1.866) (1,2) (3,2) (3,1) (2.098,2.366) (2,2) (2,3) (2,2) (0.732,2.732) (1,3) (3,3) (3,2) (1.598,3.232) (2,3) 产生的新图像gx,y为 gx,y=255605825559595725525561565525562255255 在上述运算过程中,原图中的对应点超出图像范围,或新图像中的点在原图像中没有对应点,直接赋背景色255; 未超出图像范围但不是整数像素的对应点按最邻近插值。 为提高图像效果,可以采用双线性插值,如新图像中1,2点,对应原图中(0.366,1.366)点,该点位于0,1、1,1、0,2、1,2四点之间,可以按照式(35)计算0.366,1.366点的值,并赋给新图像中的1,2点。 f0,1.366=f0,1+0.366f0,2-f0,1=61+0.366×62-61=61.366f1,1.366=f1,1+0.366f1,2-f1,1=59+0.366×56-59=57.902f0.366,1.366=f0,1.366+0.366f1,1.366-f0,1.366≈60 微课视频 绕中心点旋转先要将坐标系平移到中心点,再绕原点旋转进行变换,然后平移回原坐标原点。绕任意点旋转与此相同,仅仅是平移量的不同。 关于绕中心点的旋转变换,请扫二维码查看讲解。 3. 图像旋转的实现 图像旋转按照例3.8中所述步骤实现。MATLAB中实现图像旋转的有affinetform2d和imwarp函数组合以及imrotate函数。 【例3.9】采用imrotate函数实现图像旋转。 解: 程序如下。 clear,clc,close all; Image=im2double(imread('dog.jpg')); %读取图像并转换为double型 NewImage1=imrotate(Image,15,'bilinear'); %图像旋转后不剪切 RImage=1-Image; %将原图反色 NewImage2=imrotate(RImage,15,'bilinear','crop');%反色图像旋转后剪切 NewImage2=1-NewImage2; %旋转后图像再反色,将背景置为白色 subplot(131),imshow(Image),title('原图'); subplot(132),imshow(NewImage1),title('不剪切'); subplot(133),imshow(NewImage2),title('剪切'); 程序运行结果如图311所示。imrotate函数将背景色置为黑色,如图311(b)所示; 程序中将原图反色后旋转,旋转后图像再反色得到白色背景色,如图311(c)所示。 图311采用imrotate函数实现图像旋转变换 3.4.5图像缩放 图像缩放是指将给定图像的尺寸在x、y方向分别缩放kx、ky倍,获得一幅新的图像。其中,若kx=ky,即在x轴、y轴方向缩放的比率相同,则称为图像的按比例缩放。若kx≠ky,缩放会改变原始图像像素间的相对位置,产生几何畸变,称为图像的不按比例缩放。进行缩放变换后,新图像的分辨率为kxM×kyN。 图像的缩放处理分为图像的缩小和图像的放大处理: (1) 当0<kx,ky<1,实现图像的缩小处理; (2) 当kx,ky>1,则实现图像的放大处理。 设原图像中点x,y进行缩放处理后,变换到点x′,y′,则缩放处理的矩阵形式可表示为 x′y′1=kx000ky0001xy1(318) 可以根据后向映射法,按照式(318)实现图像缩放。 通过确定变换矩阵,由函数affinetform2d定义几何变换,利用imwarp函数实现图像缩放变换。此外,MATLAB也提供了图像缩放变换函数imresize。 【例3.10】采用函数imresize实现图像缩放变换。 解: 程序如下。 clear,clc,close all; [Image1,MAP1]=imread('kids.tif'); %打开索引图像 Image2=im2double(imread('dog.jpg')); %打开真彩色图像 [NewImage1,MAP2]=imresize(Image1,MAP1,0.6,'bilinear'); %索引图像按比例缩小,双线性插值 NewImage2=imresize(Image2,'Scale',[2.8,1.6]); %不按比例放大,双三次插值 figure,imshow(NewImage1,MAP2),title('按比例缩小'); figure,imshow(NewImage2),title('不按比例放大'); 程序运行结果如图312所示。 图312采用imresize函数实现图像缩放变换 3.4.6图像错切 图像的错切变换是平面景物在投影平面上的非垂直投影。错切变换使图像中的图形产生扭变。这种扭变只在水平或垂直方向上产生时,分别称为水平方向错切和垂直方向错切。 设原图像中点x,y进行错切变换后,变换到点x′,y′,则错切变换的矩阵表达式为 x′y′1=1dx0dy10001xy1(319) 【例3.11】采用函数affinetform2d和imwarp实现图像错切变换。 解: 程序如下。 clear,clc,close all; Image=imread('dog.jpg'); dx=0.5; dy=0.2; %设定错切系数 tform1=affinetform2d([1 dx 0;0 1 0;0 0 1]); %定义水平错切变换 tform2=affinetform2d([1 0 0;dy 1 0;0 0 1]); %定义垂直错切变换 tform3=affinetform2d([1 dx 0;dy 1 0;0 0 1]); %定义同时错切变换 hImage=imwarp(Image,tform1,'FillValue',255); vImage=imwarp(Image,tform2,'FillValue',255); hvImage=imwarp(Image,tform3,'FillValue',255); %错切变换,插值方式缺省,为'linear' subplot(221),imshow(Image),title('原图'); subplot(222),imshow(hImage),title('水平方向错切'); subplot(223),imshow(vImage),title('垂直方向错切'); subplot(224),imshow(hvImage),title('水平、垂直方向同时错切'); 程序运行结果如图313所示。 图313图像错切变换 3.4.7图像转置 图像转置变换是指将图像的行、列坐标互换。设原图像中的点x,y进行转置后,变换到点x′,y′,则转置变换的矩阵表达式为 x′y′1=010100001xy1(320) 图像在MATLAB中用矩阵表达,可以直接通过矩阵转置实现图像转置。 【例3.12】设计程序实现图像转置变换。 解: 程序如下。 clear,clc,close all; Image=im2double(imread('dog.jpg')); [height,width,color]=size(Image); result=zeros(width,height,color); for i=1:color result(:,:,i)=Image(:,:,i)'; %按通道进行矩阵转置 end subplot(121),imshow(Image),title('原图'); subplot(122),imshow(result),title('图像转置'); 程序运行结果如图314所示。 图314图像转置变换 3.5代数运算 图像代数运算是指对两幅或多幅输入图像进行点对点的加、减、乘、除,与、或、非等运算,有时涉及将简单的代数运算进行组合而得到更复杂的代数运算结果。从原理上来讲,代数运算简单易懂,但在实际应用中很常见。 3.5.1加法运算 1. 原理 加法运算将两幅或多幅图像对应点像素值相加,如式(321)所示。 gx,y=f1x,y+f2x,y(321) 式中,f1、f2是同等大小的两幅图像。 进行相加运算,对应像素值的和可能会超出灰度值表达的范围,对于这种情况,可以采用下列方法进行处理。 (1) 截断处理。如果gx,y大于255,仍取255; 但新图像gx,y像素值会偏大,图像整体较亮,后续需要灰度级调整。 (2) 加权求和,即 gx,y=αf1x,y+1-αf2x,y(322) 式中,α∈0,1。这种方法需要选择合适的α。 采用MATLAB编程时,可以用“+”运算符或者函数imadd实现图像相加,采用函数imlincomb实现多幅图像线性组合,要求图像大小相同。 【例3.13】采用函数imadd、imlincomb实现图像相加。 解: 程序如下。 clear,clc,close all; Back=imread('back.jpg'); %背景图,整型数据 Foreground=imread('fore.jpg'); %目标图,整型数据 result1=imadd(Back,Foreground); %截断求和 alpha=0.6; result2=imlincomb(1-alpha,Back,alpha,Foreground); %加权求和 subplot(221),imshow(Back),title('背景图'); subplot(222),imshow(Foreground),title('目标图'); subplot(223),imshow(result1),title('截断求和'); subplot(224),imshow(result2),title('加权求和'); thresh=25; %设定非目标像素容差阈值 pos1=Foreground(:,:,1)<thresh; pos2=Foreground(:,:,2)<thresh; pos3=Foreground(:,:,3)<thresh; pos=pos1 & pos2 & pos3; %确定黑色区域 pos=cat(3,pos,pos,pos); %表达为3维矩阵 Back(~pos)=0; %背景图中对应目标的像素设为0 result3=Back+Foreground; %加法运算 figure,imshow(result3),title('前景覆盖'); 程序运行结果如图315所示。采用不同的方式将图315(a)和图315(b)相加,图315(c)是将和值限幅截断,图315(d)是加权求和,图315(e)是前景目标覆盖背景。 图315加法运算效果 2. 主要应用 1) 多图像平均去除叠加性噪声 假设有一幅混有噪声的图像g(x,y)由原始标准图像f(x,y)和噪声n(x,y)叠加而成,即 gx,y=fx,y+nx,y(323) 若n(x,y)为互不相关的加性噪声,且均值为0。令E[g(x,y)]为g(x,y)的期望值,则有 Egx,y=Efx,y+nx,y=Efx,y=fx,y(324) 对L幅重复采集的有噪声图像进行平均后的输出图像为 g-x,y=1L∑Li=1gix,y≈Egx,y=fx,y(325) 消除了图像中的噪声。 该方法常用于摄像机的视频图像中,用于减少电视摄像机光电摄像管或CCD器件所引起的噪声。 2) 图像合成和图像拼接 将一幅图像的内容经配准后叠加到另一幅图像上,以改善图像的视觉效果,不同视角的图像拼接到一起生成全景图像等,需要加法运算。 3) 在多光谱图像中的应用 在多光谱图像中,通过加法运算加宽波段,如绿色和红色波段图像相加可以得到近似全色图像。 3.5.2减法运算 1. 原理 减法运算将两幅或多幅图像对应点像素值相减,如式(326)所示。 gx,y=f1x,y-f2x,y(326) 式中,f1、f2是同等大小的两幅图像。 进行相减运算,对应像素值的差可能为负数,对于这种情况,可以采用下列方法进行处理。 (1) 截断处理。如果gx,y小于0,仍取0; 但新图像gx,y像素值会偏小,图像整体较暗,后续需要灰度级调整。 (2) 取绝对值,即 gx,y=f1x,y-f2x,y(327) 采用MATLAB编程时,可以用“-”运算符或者函数imsubtract实现两幅图像相减或者图像和常数相减,采用函数imabsdiff求两幅相同大小图像的绝对值差图像。 2. 主要应用 1) 显示两幅图像的差异 将两幅图像相减,灰度或颜色相同部分相减为0,呈现黑色; 相似部分差值很小; 而相异部分差值较大,差值图像中相异部分突显,可用于检测同一场景两幅图像之间的变化,如运动目标检测中的背景减法、视频中镜头边界的检测。 2) 去除不需要的叠加性图案 叠加性图案可能是缓慢变化的背景阴影或周期性的噪声,或在图像上每一个像素处均已知的附加污染等,如电视制作的蓝屏技术。 3) 图像分割 如分割运动的车辆,减法去掉静止部分,剩余的是运动元素和噪声。 4) 生成合成图像 【例3.14】基于MATLAB编程实现两幅图像相减。 解: 程序如下。 clear,clc,close all; Back=imread('hallback.bmp'); Foreground=imread('hallforeground.bmp'); result1=imabsdiff(Back,Foreground); result2=im2double(Foreground)-im2double(Back); subplot(221),imshow(Back),title('背景图'); subplot(222),imshow(Foreground),title('前景图'); subplot(223),imshow(result1),title('差的绝对值图像'); subplot(224),imshow(result2),title('差值图像'); 程序运行结果如图316所示。 图316减法运算结果图 3.5.3乘法运算 乘法运算将两幅或多幅图像对应点像素值相乘,如式(328)所示。 gx,y=f1x,y×f2x,y(328) 式中,f1、f2是同等大小的两幅图像。 乘法运算主要用于图像的局部显示和提取,通常采用二值模板图像与原图像做乘法来实现; 也可以用来生成合成图像。 MATLAB提供了函数immultiply实现两幅图像相乘或者图像和常数相乘,也可以采用矩阵点乘实现。 【例3.15】基于MATLAB编程,将两幅图像相乘,实现目标提取。 解: 程序如下。 clear,clc,close all; Back=im2double(imread('bird.jpg')); Templet=im2double(imread('birdtemplet.bmp')); result1=immultiply(Templet,Back); %图像和模板相乘 result2=Back.*Templet; %大小和类型一致,用矩阵点乘代替 subplot(221),imshow(Back),title('背景图'); subplot(222),imshow(Templet),title('模板'); subplot(223),imshow(result1),title('图像相乘'); subplot(224),imshow(result2),title('矩阵点乘'); 程序运行结果如图317所示。 图317乘法运算结果图 3.5.4除法运算 除法运算将两幅或多幅图像对应点像素值相除,如式(329)所示。 gx,y=f1x,y÷f2x,y(329) 式中,f1、f2是同等大小的两幅图像。 除法运算可以用于消除空间可变的量化敏感函数、归一化、产生比率图像等。 MATLAB提供了函数imdivide实现两幅图像相除或者图像和常数相除,也可以采用矩阵点除实现。 【例3.16】设计程序,将两幅图像相除,实现目标提取。 解: 程序如下。 clear,clc,close all; Back=im2double(imread('bird.jpg')); Templet=im2double(imread('birdtemplet.bmp')); subplot(131),imshow(Back),title('背景图'); subplot(132),imshow(Templet),title('模板'); Templet(Templet~=1)=1000; %模板图像中非模板区值设为较大值1000 result=imdivide(Back,Templet); %图像相除 subplot(133),imshow(result),title('图像相除'); 程序运行结果如图318所示,可以看出,通过合理设置模板图像,除法也实现了模板运算。 图318除法运算结果图 3.5.5逻辑运算 在两幅图像对应像素间进行与、或、非等运算,称为逻辑运算。 非运算: gx,y=255-fx,y,用于获得原图像的补图像,或称反色。 与运算: gx,y=f1x,y&f2x,y,求两幅图像的相交子图,可用于图像的局部显示和提取。 或运算: gx,y=f1x,y|f2x,y,合并两幅图像的子图像,可用于图像的局部显示和提取。 MATLAB提供了一系列逻辑运算的函数,有非运算imcomplement函数,按位求补bitcmp函数,按位求与bitand函数,按位求或bitor函数,按位异或bitxor函数等。此外,需要注意,“&”“|”“~”运算符实现对两个数据的整体逻辑运算,与按位逻辑运算结果不一致。 【例3.17】对两幅图像按位进行逻辑运算。 解: 程序如下。 clear,clc,close all; Back=imread('bird.jpg'); Templet=imread('birdtemplet.bmp'); result1=bitcmp(Back); %求反 result2=bitand(Templet,Back); %求与 result3=bitor(Templet,Back); %求或 result4=bitxor(Templet,Back); %求异或 subplot(221),imshow(result1),title('背景图求反'); subplot(222),imshow(result2),title('与模板相与'); subplot(223),imshow(result3),title('与模板相或'); subplot(224),imshow(result4),title('与模板异或'); 程序运行结果如图319所示。 图319按位逻辑运算结果图 关于图像的局部显示与提取,请扫二维码,查看讲解。 微课视频 3.6上采样和下采样 上采样指增大图像的分辨率,下采样指降低图像的分辨率,常用于生成图像的多分辨率表达,即同一幅图像采用不同大小的分辨率表示,以便实现不同尺度的特征提取,或者用于搜索算法。 上、 下采样有不同的实现方法,可以采用图像缩放变换实现,即将新分辨率图像像素映射到原分辨率图像中,通过插值运算,获取像素值,生成新图像。 上采样也可以通过反卷积的方式实现。通过合理的方式将低分辨率图像补零,再进行卷积,提高分辨率。不同的补零方式,对应不同的反卷积。 图320(a)为2×2的低分辨率图像,在周围补两行两列的零,和图320(b)所示模板进行卷积运算,如图320(c)所示,得4×4的高分辨率图像,如图320(d)所示,这种方法称为转置卷积。 图320转置卷积 图321(a)为2×2的低分辨率图像,在原图像素点周围补零,并和模板进行卷积运算,如图321(c)所示,得3×3的高分辨率图像,如图321(d)所示,这种方法称为微步卷积。 图321微步卷积 下采样也可以仅在某些像素处计算卷积,降低分辨率,如图322所示。 图322下采样 上、下采样方法很多,操作灵活,需要根据具体设计目的选择合适的方法。 3.7综合实例 【例3.18】有一幅蝴蝶的图片、一幅风景图片,试基于MATLAB编程,基于几何、代数和色彩通道运算,实现漫天蝴蝶飞舞的合成图像。 解: 设计思路如下。 对蝴蝶图片进行随机变换后叠加到风景图片上,依次进行的随机变换为三种几何变换、交换两个色彩通道、叠加到风景图片随机位置上。合成图像设计框图如图323所示。 图323合成图像设计框图 程序如下。 clear,clc,close all; Image=imread('butterfly.bmp'); Back=imread('scenery.jpg'); subplot(131),imshow(Image),title('蝴蝶'); subplot(132),imshow(Back),title('背景图'); [h,w,c]=size(Back); population=20; %随机变换出20只蝴蝶 num=3; %拟进行三种几何变换 for k=1:population type=randi(6,1,num); %在缩小、旋转、三种镜像及错切六种几何变换中随机选择三种 NewImage=Image; for n=1:num switch type(n) case 1 %比例变换 scale=rand(); %缩小比例随机生成 NewImage=imresize(NewImage,scale,'bilinear'); %缩小变换,双线性插值 case 2 %旋转变换 angle=round(rand()*100); %逆时针旋转角度随机生成 NewImage=imrotate(NewImage,angle,'bilinear'); %旋转变换,双线性插值 case 3 %错切变换 shear=rand()/2; %错切系数0~0.5 tform1=affinetform2d([1 0 0;shear 1 0; 0 0 1]); tform2=affinetform2d([1 shear 0;0 1 0; 0 0 1]); NewImage=imwarp(NewImage,tform1); NewImage=imwarp(NewImage,tform2); case 4 %水平镜像 NewImage=flip(NewImage,2); case 5 %垂直镜像 NewImage=flip(NewImage,1); case 6 %对角镜像 NewImage=flip(NewImage,2); NewImage=flip(NewImage,1); end end [newh,neww,newc]=size(NewImage); positionx=randi(w-2*neww,1,1); positiony=randi(h-2*newh,1,1); %叠加位置 temp=Back(positiony:positiony+newh-1,positionx:positionx+neww-1,:); colorchange=randi(3,1,2); if colorchange(1)~=colorchange(2) color=NewImage(:,:,colorchange(1)); NewImage(:,:,colorchange(1))=NewImage(:,:,colorchange(2)); NewImage(:,:,colorchange(2))=color; end %色彩通道交换 c=NewImage(:,:,1) & NewImage(:,:,2) & NewImage(:,:,3); pos=find(c(:)==0); NewImage(pos)=temp(pos); NewImage(pos+newh*neww)=temp(pos+newh*neww); NewImage(pos+2*newh*neww)=temp(pos+2*newh*neww); %去除几何变换中产生的背景黑色点 temp=NewImage; Back(positiony:positiony+newh-1,positionx:positionx+neww-1,:)=temp; %叠加 end subplot(133),imshow(Back),title('合成图'); 程序运行结果如图324所示。 图324模板运算结果图 启发: 从图323的设计框图可以看出,无论多复杂的工程问题,都是由一个个的小问题构成的,将任务分解为若干模块,逐个击破,也就解决了复杂问题。同理,再宏大的目标,都可以一点一点完成。从一点一滴做起,每天进步一点点。 习题 3.1编写程序,设计不同的模板,对图像进行卷积运算,尝试采用不同的边界填塞方法。 3.2一幅图像为f=147258369,设kx=2.3,ky=1.6,试编写程序,采用双线性插值法对其进行放大(不采用MATLAB中的图像缩放函数)。 3.3试编写程序,对习题3.2图像逆时针旋转60°,采用双线性插值法(不采用MATLAB中的几何变换函数)。 3.4编写程序,实现手机图像编辑中的裁剪功能。 3.5编写程序,在例3.14中的减法运算程序的基础上,从原图中抠取人物。 3.6编写程序,尝试实现图像的上采样和下采样。