utilize matlab to implement the image processing (1)

来源:互联网 发布:js初学者 编辑:程序博客网 时间:2024/05/29 18:05


//source:http://www.ilovematlab.cn/forum.php?mod=viewthread&tid=164340&page=1&authorid=275675

基本概念一点通
从理论上讲,图像是一种二维的连续函数,然而在计算机上对图像进行数字处理的时候,首先必须对其在空间和亮度上进行数字化,这就是图像的采样和量化的过程。空间坐标(x,y)的数字化称为图像采样,而幅值数字化称为灰度级量化。
对一幅图像采样时,若每行(横向)采样数为M,每列(纵向)采样数为N,则图像大小为M*N个像素, f(x,y)表示点(x,y) 处的灰度值,则F(x,y)构成一个M*N 实数矩阵
****************************
经验分享:“像素”的英文为“pixel”,它是“picture”和“element”的合成词,表示图像元素的意思。我们可以对“像素”进行如下理解:像素是一个面积概念,是构成数字图像的最小单位。
****************************
把采样后所得的各像素灰度值从模拟量到离散量的转换称为图像灰度的量化。量化是对图像幅度坐标的离散化,它决定了图像的幅度分辨率。
量化的方法包括:分层量化、均匀量化和非均匀量化。分层量化是把每一个离散样本的连续灰度值只分成有限多的层次;均匀量化是把原图像灰度层次从最暗至最亮均匀分为有限个层次,如果采用不均匀分层就称为非均匀量化。
当图像的采样点数一定时,采用不同量化级数的图像质量不一样。量化级数越多,图像质量越好;量化级数越少,图像质量越差。量化级数小的极端情况就是二值图像。
****************************
经验分享:“灰度”可以认为是图像色彩亮度的深浅。图像所能够展现的灰度级越多,也就意味着图像可以表现更强的色彩层次。如果把黑——灰——白连续变化的灰度值量化为256个灰度级,灰度值的范围为0~255,表示亮度从深到浅,对应图像中的颜色为从黑到白。
****************************
因此,对数字图像进行处理,也就是对特定的矩阵进行处理。在C语言中,对M×N数字图像处理的核心代码如下:
for (j=1;j<N+1;j++)
   for(i=1;i<M+1;i++)
   { 对I(i,j)的具体运算
};
在Matlab中,对M×N数字图像处理的核心代码如下:
for i=1:N
    for j=1:M
      对I(i,j)的具体运算
    end
end




一幅数字图像可以用一个矩阵来表示,对数字图像进行处理,实质上就是对特定的图像矩阵进行变换的过程,因此,图像变换是数字图像处理技术的基础。
图像变换的方法林林总总,多种多样。包括空间域变换、频率域变换、时频域变换、基于经典数学理论的变换、基于现代数学理论的变换。
以下程序段是用于图像放缩(空间变换)的MATLAB源程序:
*********************************************************************
function newImage=resample1(image,newRow,newCol)
% 功能:对图像进行缩放
% 输入:image-需要进行缩放的灰度图像;
% newRow-缩放后新图像的行数;
% newCol-缩放后新图像的列数;
% 输出:newImage-缩放后的图像。

[row,col]=size(image);
image_larger=zeros((row+1),(col+1));
image_larger(1:row,1:col)=image;
image=image_larger;
newImage=zeros(newRow,newCol);
for i=0:(newRow-1)
for j=0:(newCol-1)
x=j*(col-1)/(newCol-1);
y=i*(row-1)/(newRow-1);
fx=floor(x);
fy=floor(y);

area_ul=(x-fx)*(y-fy);
area_ur=(fx+1-x)*(y-fy);
area_bl=(x-fx)*(fy+1-y);
area_br=(fx+1-x)*(fy+1-y);

newImage(i+1,j+1)=...
image(fy+1,fx+1)*area_br+...
image(fy+1,fx+2)*area_bl+...
image(fy+2,fx+1)*area_ur+...
image(fy+2,fx+2)*area_ul;
end
end
*********************************************************************
在MATLAB中,图像的缩放也可以调用imresize函数来实现。imresize函数的调用格式如下:
B = imresize(A,m,method)
imrersize函数使用由参数method指定的插值运算来改变图像的大小。method的几种可选值: 'nearest'(默认值)最近邻插值; 'bilinear'双线性插值; 'bicubic'双三次插值; B = imresize(A,m)表示把图像A放大m倍。




(1)图像文件的读取
利用imread函数可以完成图像文件的读取操作。常用语法格式为:
I=imread(‘filename’,‘fmt’)或I=imread(‘filename.fmt’);
其作用是将文件名用字符串filename表示的、扩展名用字符串fmt(表示图像文件格式)表示的图像文件中的数据读到矩阵I中。当filename中不包含任何路径信息时,imread会从当前工作目录中寻找并读取文件。要想读取指定路径中的图像,最简单的方法就是在filename中输入完整的或相对的地址。 MATLAB支持多种图像文件格式的读、写和显示。因此参数fmt常用的可能值有:
‘bmp’ Windows位图格式
‘jpg’or‘jpeg’ 联合图像专家组格式
‘tif’or‘tiff’ 标志图像文件格式
‘gif’ 图形交换格式
‘pcx’ Windows画刷格式
‘png’ 可移动网络图形格式
‘xwd’ X Window Dump格式
例如,命令行
>>I=imread(‘lena.jpg’);
将JPEG图像lena读入图像矩阵I中。
(2) 图像文件的写入(保存)
利用imwrite完成图像的输出和保存操作,也完全支持也完全支持上述各种
图像文件的格式。其语法格式为:
imwrite(I,‘filename’,‘fmt’)或imwrite(I,‘filename.fmt’);
其中的I、filename和fmt的意义同上所述。
注意事项:当利用imwrite函数保存图像时,MATLAB默认的保存方式是将其简化为uint8的数据类型。与读取文件类型类似,MATLAB在文件保存时还支持16位的PNG和TIFF图像。所以,当用户保存这类文件时,MATLAB就将其存储在uint16中。
(3)图像文件的显示
图像的现实过程是将数字图像从一组离散数据还原为一幅可见图像的过程。
MATLAB的的图像处理工具箱提供了多种图像显示技术。例如imshow可以直接从文件显示多种图像;image函数可以将矩阵作为图像 ;colorbar函数可以用来显示颜色条;montage函数可以动态显示图像序列。这里仅对常用的显示函数进行介绍。
①图像的显示
imshow函数是最常用的显示各种图像的函数,其调用格式如下:
imshow(I,N);
imshow(I,N)用于显示灰度图像,其中I为灰度图像的数据矩阵,N为灰度级数目,默认值为256。
例如下面的语句用于显示一幅灰度图像:
>> I=imread(‘lena.jpg’);
>> imshow(I);
如果不希望在显示图像之前装载图像,那么可以使用以下格式直接进行图像文件的显示:
imshow filename
其中,filename为要显示的图像文件的文件名。
注意事项:该文件名必须带有合法的扩展名(指明文件格式),且该图像文件必须保存在当前目录下,或在MATLAB默认的目录下。
②添加色带
colorbar函数可以给一个坐标轴对象添加一条色带。如果该坐标轴对象包含一个图像对象,则添加的色带将指示出该图像中不同颜色的数据值。这对于了解被显示图像的灰度级特别有用。其调用格式为:
colorbar
③显示多幅图像
显示多幅图像最简单的方法就是在不同的图形窗口中显示它们。imshow总是在当前窗口中显示一幅图像,如果用户想连续显示两幅图像,那么第二幅图像就会替代第一幅图像。为了避免图像在当前窗口中的覆盖现象,在调用imshow函数显示下一幅图像之前可以使用figure命令来创建一个新的窗口。例如:
imshow(I1);
figure, imshow(I2);
figure, imshow(I3);
有时为了便于在多幅图像之间进行比较,需要将这些图像显示在一个图形窗口中。达到这一目的有两种方法:一种方法是联合使用imshow和subplot函数,但此方法在一个图形窗口只能有一个调色板;另一种方法是联合使用subimage和subplot函数,此方法可在一个图形窗口内使用多个调色板。
subplot函数将一个图形窗口划分为多个显示区域,其调用格式如下:
subplot(m,n,p)
subplot函数将图形窗口划分为m(行)×n(列)个显示区域,并选择第p个区域作为当前绘图区。
(4) 图像文件信息的查询
imfinfo函数用于查询图像文件的有关信息,详细地显示出图像文件的各种属性。其语法格式为:
info=imfinfo(‘filename’,‘fmt’)或info=imfinfo(‘filename.fmt’)
或imfinfo filename.fmt
imfinfo函数获取的图像文件信息依赖于文件类型的不同而不同,但至少应包
含以下内容:
文件名。如果该文件不在当前目录下,还包含该文件的完整路径。
文件格式。
文件格式的版本号。
文件最后一次修改的时间。
文件的大小。以字节为单位。
图像的宽度。
图像的高度。
每个像素所用的比特数。也叫像素深度。
图像类型。即该图像是真彩色图像、索引图像还是灰度图像。



数字图像处理的方法有两类:空间域处理法和频域法。频域法首先是要将图像从空间域变换到频率域,然后在频率域对图像进行各种处理,再将所得到的结果进行反变换,从而达到图像处理的目的,频域法具有很多明显的优点。目前,频域变换被广泛运用于图像特征提取、图像增强、图像复原、图像数据压缩和图像识别等领域。
(1)离散傅立叶变换(DFT)
离散傅立叶变换(DFT)在数字信号处理和数字图像处理中应用十分广泛。使用离散傅立叶变换的根本原因有二:一是DFT的输入、输出均为离散形式的,这使得计算机非常容易操作;二是因为计算DFT存在快速算法,即快速傅立叶变换(FFT),因而计算比较方便。
空间域是由f(x,y)所组成的坐标系,其中x和y用作(空间)变量。频率系统是由F(u,v)所组成的坐标系,其中u和v用作(频率)变量。由u=0,1,2,…M-1和v=0,1,2,…N-1定义的M×N矩形区域常称为频率矩形。显然,频率矩形的大小与输入图像的大小相同。为了与MATLAB的实现形式相一致,将1/MN项放置于逆变换公式的前面。由于MATLAB中的数组索引是以1而不是以0开头的,所以MATLAB中的F(1,1)和f(1,1)相应于正变换和逆变换中的数字量F(0,0)和f(0,0)。在频域原点处变换值[如F(0,0)]称为傅立叶变换的直流(dc)分量,F(0,0)等于f(x,y)的平均值的MN倍。
MATLAB图像处理工具箱提供了一些函数来进行傅立叶变换:
① 函数:fft2——用于计算二维快速傅立叶变换。调用格式为:
Y = fft2(X);
Y = fft2(X,M,N);
其中X是输入图像矩阵,Y是X进行二维傅立叶变换后的图像矩阵;X和Y大小相同。在Y=fft2(X,M,N)中,按照M、N指定的值对图像进行剪切或补0后进行傅立叶变换,返回变换矩阵的大小为M×N。变换结果的左上、右上、左下、右下四个角的周围对应于低频成分,中央部位对应于高频成分。
② 函数:fftn——用于计算n维傅立叶变换。调用格式:
Y = fftn(X);
Y = fftn(X,SIZE);
其中Y=fftn(X)计算图像的n维傅立叶变换,输出图像Y与X大小相同。在Y=fftn(X,SIZE)函数中,按照SIZE指定的值对图像X进行剪切或补0后进行傅立叶变换,返回变换矩阵的大小为SIZE。
③ 函数:fftshift——将变换后的图像频谱中心从矩阵的原点移到矩阵的中心。其调用格式为:
Y = fftshift(X);
Y = fftshift(X,DIM);
其中fftshift用于调整 fft、fft2和fftn的输出结果。对于向量X,将其左右两半交换位置,对于矩阵X,将其一、三象限和二、四象限进行互换,对于高维向量X,将矩阵各维的两半进行互换。利用这个函数可使变换结果的零频率分量位于中心。但应注意,在进行反变换时,必须使用四角代表低频成分,中央对应高频部分的变换结果。
④ 函数:ifft2——用于计算图像的二维傅立叶反变换。其调用格式为:
Y = ifft2(X);
Y = ifft2(X,M,N);
其中ifft2用于返回图像的二维傅立叶反变换矩阵,其参数定义同fft2。
⑤ 函数:ifftn——用于计算图像的n维傅立叶反变换。调用格式为:
Y = ifftn(X);
Y = ifftn(X,SIZE);
其参数定义同fftn。
实例:对某矩阵进行零填充后,进行快速傅立叶变换并显示其频谱。如图1.4.1所示。
f=zeros(30,30);
f(5:24,13:17)=1;
subplot(1,2,1),imshow(f);
F=fft2(f,256,256);
F2=fftshift(log(abs(F))); % 计算对数幅值并使零频率系数位于图形的中心
subplot(1,2,2),imshow(F2,[-1 5]);
colorbar;
(2)离散余弦变换(DCT)
离散余弦变换(DCT,Discrete Cosine Transform)的变换核为实数的余弦函数,因而DCT的计算速度要比变换核为复指数的DFT要快得多。离散余弦变换是仅次于K-L变换的次最佳正交变换,且有这样的性质:许多有关图像的重要可视信息都集中在DCT变换的一小部分系数中,因此已被广泛应用到图像压缩编码、语音信号处理等众多领域,并成为许多图像编码国际标准的核心。
MATLAB图像处理工具箱实现离散余弦变换有两种方法:其一是使用函数dct2,该函数用一个基于FFT的算法来提高当输入较大的输入方阵时的计算速度。其二是使用由dctmtx函数返回的DCT变换矩阵,这种方法较适合于较小的输入方阵(例如8×8或16×16)
提供DCT函数分别为:
① 函数:dct2——实现图像的二维离散余弦变换。调用格式为:
B = dct2(A);
B = dct2(A,[M N]);
B = dct2(A,M,N);
其中A表示要变换的图像,M和N是可选参数,表示填充后的图像矩阵大小,如果m和n比图像A小,则进行变换之前,将图像A进行剪切,B表示变换后得到的图像矩阵,各元素为离散余弦变换的系数B(k1,k2)。
② 函数:dctmtx——主要用于实现较小输入矩阵的离散余弦变换,调用格式为:D = dctmtx(N),其中D是返回N×N的DCT变换矩阵,如果矩阵A是N×N方阵,则A的DCT变换可用D×A×D’来计算。这在有时比dct2计算快,特别是计算大量小的相同尺寸DCT时,矩阵D只需计算一次,因而速度快。
例如,在实现JPEG压缩时,要多次实现大小为8×8的图像块的DCT,为了实现这种变换,首先利用语句D=dctmtx(8),然后,对每一个图像块执行运算B=D×A×D’。这种实现方法比调用函数dct2要快。
③ 函数:idct2——实现图像的二维离散余弦反变换。调用格式为:
B = idct2(A);
B = idct2(A,[M N]);
B = idct2(A,M,N);
其中参数同dct2。



灰度直方图
在数字图像处理中,灰度直方图是最简单且最有用的工具,可以说,对图像的分析与观察直到形成一个有效的处理方法,都离不开直方图。直方图表达的信息是每种亮度的像素点的个数。直方图是图像的一个重要特征,因为直方图用少量的数据表达图像的灰度统计特征。
根据图像直方图的定义编写的求灰度图像Matlab源程序。
*********************************************************************
%读入图像;
I=imread('taishan.jpg');
%将RGB图像转换为灰度图像;
B0=rgb2gray(I);
%将图像矩阵的类型转换成双精度型,便于后续的运算;
B=double(B0);
%求图像的行数与列数;
s=size(B);
%建立一个数组,用于存储1~256灰度级出现的个数;
h=zeros(1,256);
%根据定义,计算各像素灰度值出现的个数;
for i=1:s(1)
for j=1:s(2)
k=B(i,j);
k=floor(k);
h(k+1)=h(k+1)+1;
end
end
% 显示图像;
subplot(121),imshow(B0);
subplot(122),plot(h)
*********************************************************************


非线性灰度值变换
这种方法的目标与增强对比度相反。当原图的动态范围太大,超出了某些显示设备所允许的动态范围时,可采用对数形式的变换函数进行动态范围压缩:I=imread('yellowriver.jpg');
X1=rgb2gray(I);
>> figure,imshow(X1);
c=255/log(256);
x=0:1:255;
y=c*log(1+x);
figure,plot(x,y)
xlabel('f'),ylabel('g')
title('intensitytransformation')
%绘制变换曲线
[m,n]=size(X1);
X2=double(X1);
for i=1:m
for j=1:n
g(i,j)=0;
g(i,j)=c*log(X2(i,j)+1);
end
end
figure,imshow(mat2gray(g))




链码(又称为freeman码)是用曲线起始点的坐标和边界点方向代码来描述曲线或边界的方法,常被用来在图像处理、计算机图形学、模式识别等领域中表示曲线和区域边界。常用的链码按照中心像素点邻接方向个数的不同,分为4连通链码和8连通链码。4连通链码的邻接点有4个,分别在中心点的上、下、左和右。8连通链码比4连通链码增加了4个斜方向,因为任意一个像素周围均有8个邻接点,而8连通链码正好与像素点的实际情况相符,能够准确地描述中心像素点与其邻接点的信息。因此,8连通链码的使用相对较多。

8连通边界的链码生成程序:

function out=chaincode8(image)

%功能:实现8连通链码

%输入: 二值图像

%输出:链码的结果



n=[0 1;-1 1;-1 0;-1 -1;0 -1;1 -1;1 0;1 1];

%设置标志

flag=1;

%初始输出的链码串为空

cc=[];

%找到起始点

[x y]=find(image==1);

x=min(x);

imx=image(x,:);

y=min(find(imx==1));

first=[x y];



dir=7;

while flag==1

          tt=zeros(1,8);

          newdir=mod(dir+7-mod(dir,2),8);

          for i=0:7

              j=mod(newdir+i,8)+1;

              tt(i+1)=image(x+n(j,1),y+n(j,2));

          end

    d=min(find(tt==1));

          dir=mod(newdir+d-1,8);

          %找到下一个像素点的方向码后补充在链码的后面

    cc=[cc,dir];

    x=x+n(dir+1,1);y=y+n(dir+1,2);

    %判别链码的结束标志

    if x==first(1)&&y==first(2)

        flag=0;

    end

end

out=cc;



在Matlab图像处理工具箱中,提供了专门的bwlabel( )函数,对二值图像的连接部分进行标记。 其调用格式如下:
L = bwlabel(BW,n)

该函数返回一个和输入的二值图像BW大小相同的L矩阵,包含了标记了BW中每个连通区域的类别标签,这些标签的值为1、2、num(连通区域的个数)。n的值为4或8,表示是按4连通寻找区域还是8连通寻找,如果参数省略,则默认为8。

0 0
原创粉丝点击