太原科技大学
课 程 设 计(论 文)
设计(论文)题目:基于MATLAB图像处理
目录
摘要 II
第1章 绪论 1
第2章 图像处理 2
2.1文件 2
2.1.1、打开 2
2.1.2、保存 2
2.1.3、退出 2
2.2编辑 2
2.2.1、灰度 2
2.2.2、亮度 4
2.2.3、截图 5
2.2.4、缩放 5
2.3旋转 6
2.3.1、上下翻转 6
2.3.2、左右翻转 7
2.3.3任意角度翻转 7
2.4噪声 8
2.5直方图统计 8
第3章程序调试及结果分析 10
参考文献 11
附 录 12
基于MATLAB的图像处理
摘要
学习MATLAB GUI程序设计,利用MATLAB图像处理工具箱,设计和实现自己的Photoshop 。要求:按照软件工程方法,根据需求进行程序的功能分析和界面设计,给出设计详细说明。然后按照自己拟定的功能要求进行程序设计和调试。 1)图像的读取和保存。2)设计图形用户界面,让用户能够对图像进行任意的亮度和对比度变化调整,显示和对比变换前后的图像。3)设计图形用户界面,让用户能够用鼠标选取图像感兴趣区域,显示和保存该选择区域。4)编写程序通过最近邻插值和双线性插值等算法将用户所选取的图像区域进行放大和缩小整数倍的操作,并保存,比较几种插值的效果。对数字图像进行处理,以达到不同的效果。根据题目的要求,除了实现要求的功能外,还有很多的功能需要用到。关键词:MATLAB 数字图像处理
第1章 绪论
数字图像处理技术是20世纪60年代发展起来的一门新兴学科,随着图像处理理论和方法的进一步完善,使得数字图像处理技术在各个领域得到了广泛应用,并显示出广阔的应用前景。MATLAB既是一种直观、高效的计算机语言,同时又是一个科学计算平台。它为数据分析和数据可视化、算法和应用程序开发提供了最核心的数学和高级图形工具。根据它提供的500多个数学和工程函数,工程技术人员和科学工作者可以在它的集成环境中交互或编程以完成各自的计算。
MATLAB中集成了功能强大的图像处理工具箱。由于MATLAB语言的语法特征与C语言极为相似,而且更加简单,更加符合科技人员对数学表达式的书写格式,而且这种语言可移植性好、可扩展性强,再加上其中有丰富的图像处理函数,所以MATLAB在图像处理的应用中具有很大的优势
学习MATLAB GUI程序设计,利用MATLAB图像处理工具箱,设计和实现自己的Photoshop 。要求:按照软件工程方法,根据需求进行程序的功能分析和界面设计,给出设计详细说明。然后按照自己拟定的功能要求进行程序设计和调试。
以下几点是程序必须实现的功能。
1)图像的读取和保存。
2)设计图形用户界面,让用户能够对图像进行任意的亮度和对比度变化调整,显示和对比变换前后的图像。
3)设计图形用户界面,让用户能够用鼠标选取图像感兴趣区域,显示和保存该选择区域。
4)编写程序通过最近邻插值和双线性插值等算法将用户所选取的图像区域进行放大和缩小整数倍的操作,并保存,比较几种插值的效果。
5)图像直方图统计和直方图均衡,要求显示直方图统计,比较直方图均衡后的效果。
第2章 图像处理
2.1文件
2.1.1、打开
为了让使用者更方便的使用,所以在设计的时候,通过对话框的形式来选择文件,选择uigetfile函数来实现,uigetfile函数显示一个打开文件对话框,该对话框自动列出当前路径下的目录和文件,由于这个GUI程序的操作对象是图像文件,所以设置这里的缺省后缀名为“”。
Uigetfile函数的调用格式为[name,path]=yigetfile(…), 在按下对话框中的执行按钮“打开”后,返回选择的文件名和路径,分别保存到“name”和“path”中。如果按下取消按钮或是发生错误,则返回值是0。 根据返回值的情况,如果是0,则弹出提示错误的对话框,否则,通过imread函数读出图像数据,把图像数据赋值给全局变量handles.img。
2.1.2、保存
同样也通过对话框的形式来保存图像数据,通过uigetfile函数选择文件名和路径,用getimage(gca)取出坐标2变换后的图像数据保存到变量i,最后用imwrite函数,把数据i存到指定的文件。
2.1.3、退出
退出比较简单,程序如下所示:
clc;
close all;
close(gcf);
2.2编辑
2.2.1、灰度
由于RGB图像是三维图像,所以图像数据是一个三维数组,为了显示灰度图像,把三维图像降为二维,可以只取其中的二维数据,实现方法程序为:
y=(handles.img(:,:,1)); %当然也可以选择(:,:,2) 或(:,:,3)
imshow(y);
但是这样的话,根据程序所选的不同,图像数据也不同,显示也就不一样。
另一种方法就是,运用rgb2gray函数实现彩色图像到灰度图像的转换。程序为:
y=rgb2gray(handles.img);
imshow(y);
这个程序只能用于RGB图像转换灰度图像,当原始图像本来就是灰度图像时,运行该程序时就会出错,但是使用者在使用时有时并不知道这些,为了使该程序更加完善,应该在使用者原先图像时灰度图像时使用该功能时,应该要显示提示类信息。所以在开始时应该要有一个RGB图像或是灰度图像的判断过程。完整的程序如下:
if isrgb(handles.img)
y=rgb2gray(handles.img);
imshow(y);
else
msgbox('这已经是灰度图像','转换失败');
end
如果原图是RGB,执行该操作的结果如下图:
图2.1 图2.2
如果原图本身已经是灰度图像了,执行该操作弹出如 右图所示的提示对话框
2.2.2、亮度 图5.3
用imadjust函数,其调用格式如下:
g=imadust(f,[low_in high_in],[low_out high_out]),gamma)
gamma 表示映射性质,默认值是1 表示线性映射。
由于该函数有五个参数需要输入,为了方便用户改变,所以这里设计一个输入对话框,用户通过对话框把五个参数赋值给[low_in high_in],[low_out high_out],gamma这五个参数,如下一组命令建立了如图所示的输入对话框:
prompt={'输入参数1','输入参数2','输入gamma'};
defans={'[0 0.7]','[0 1]','1'}; 图2.4
p=inputdlg(prompt,'输入参数',1,defans);
但是,这种方法并不能很好的让用户能够对图像进行任意的亮度和对比度变化调整,有时并不事先知道参数的值要多少,也不关心,而是任意调节的,直到满意为止。所以应该用滑动条来调节图像的亮度和对比度,这样更适合用户的使用习惯。
由于imadjust函数有五个参数,所以原则上需要设计五个滑动条来调节对比
度,这对用户来说显然比较麻烦,因此在设计的时候固定其中的三个参数,通过调节两个参数的值来改变亮度和对比度。
[0 handles.beta],[0 1],handles.gm,这里的变量handles.beta和handles.gm就通过滑动条得到,滑动条设计如下图:
图2.5
亮度调整的tag名为ld,取值范围0~1,gamma值的tag名为gamma,取值范围为0~5。获取滑动条参数的程序如下:
handles.beta=get(handles.ld,'value');
handles.gm=get(handles.gamma,'value');
2.2.3、截图
在MATLAB中,用函数imcrop实现对图像的剪切操作。该操作剪切的是图像中的一个矩形子图,用户可以通过参数指定这个矩形四个顶点的坐标,也可以交互地用鼠标选取这个矩形。
Imcrop函数的调用格式如下:
y=imcrop(handles.img);
不管handles.img是三维的还是二维数据,该函数都能进行操作。
图2.6 图2.7
2.2.4、缩放
在MATLAB中,用函数imresize来实现对图像的放大或缩小。插值方法可选用三种方法,最近邻插值,双线性插值,双三次插值。
该函数的调用格式如下:
B=imresize(A,m,method)
其中:
参数method用于指定插值的方法,可选的值为“nearest”(最近邻法),“bilinear”(双线性插值)、“bicubic”(双三次插值),缺省值为“nearest”。
B=imresizee(A.m,method)表示返回原图A的m倍放大图像(m小于1时实际上是缩小);
下图就是采用邻近插值法的放大和缩小图像,参数值保持默认设置:
图2.8 图2.9
虽然处理后看不出放大的效果,这是由于坐标轴的原因,如果把处理后的图片保存起来,再把处理后的文件打开,就可以看到比较明显的放大效果。
图2.10
2.3旋转
2.3.1、上下翻转
函数flipud是实现一个二维矩阵的上下翻转,如
a=[1 2;3 4],经过该函数处理后,原矩阵变为[3 4;1 2];所以利用该函数也可以对图像进行上下翻转处理,但由于该函数针对二维数据的处理,所以在写程序时,要对RGB图像和灰度图像分开处理,这就要用到isrgb函数来判断,如果是灰度图像,则可以直接用这个函数进行处理,否则就要对RGB图像进行降维处理, for k=1:3
y(:,:,k)=flipud(x(:,:,k));
end
处理结果如图:
图2.11 图2.12
2.3.2、左右翻转
对图像的左右翻转也可以用fliplr函数来处理,同样的,也要对灰度和彩色图像分开处理,处理结果如图:
图2.13 图2.14
2.3.3任意角度翻转
用函数imrotate来实现对图像的插值旋转。
该函数的调用格式如下:
B=imrotate(A,angle,method,’crop’)
其中,参数method用于指定插值的方法,可选的值可以有三种,分别为邻近插值,双线性插值,双三次插值,缺省时为邻近插值,参数angle代表旋转的角度。
一般来说,旋转后的图像会比原图大,用户可以指定“crop”参数对旋转后的图像进行剪切(取图像的中间部分),使返回的图像与原图大小相同。执行结果为:
图2.15 图2.16
2.4噪声
经常用到的噪声有三种,高斯噪声,椒盐噪声,乘性噪声,可以通过以下三个函数来实现:
y=imnoise(handles.img,'gaussian',p1,p2);%高斯噪声
y=imnoise(x,'salt & pepper',p1); %椒盐噪声
y=imnoise(handles.img,'speckle',p1); %乘性噪声
p1,p2的参数也通过输入对话框的形式得到,原图加入高斯噪声后结果如下所示:
图2.17
2.5直方图统计
用imhist函数对图像数据进行直方图统计,
x=imhist(handles.img(:,:,1));
bar(horz,x);
其中,x矩阵的数据是0~255灰度值的统计个数,如果直接对x矩阵数据进行图形图显示,由于有256个数据,在坐标系中就会很密集,为了更清楚的显示条形图,所以在程序设计时,把x数据进行部分提取,
x1=x(1:10:256);
horz=1:10:256;
bar(horz,x1);
除了显示数据的直方图统计外,还可以对图像进行均衡处理,所用到的函数是histeq,这两个函数同样只使用于二维数据,所以也要对二维和三维数据分开处理。
直方图显示和均衡后的图像分别如下图所示
图2.18
第3章程序调试及结果分析
1、一个函数只能对灰度图像处理,不能对RGB图像处理,那么如何才能对RGB图像处理呢?
这主要是对MATLAB函数的不够清楚,用到的很多函数是针对二维数据的,而RGB图像的数据是一个三维矩阵,所以处理要与灰度图像不同,在开始的时候,我认为应该找一个能够应用于三维矩阵的函数,结果却没找到,后来想到可以把三维数据进行降维处理,同样使用二维的函数,只要是同样处理三次。比如,彩色图像的滤波处理,直方图均衡等。
2、同一个操作对灰度图像可以使用,当用户选择的是彩色图像时,该操作就会出错?
这是由于设计程序时,本身程序是有针对性的,有些程序只能对灰度图像有效,有些对彩色图像有效,但是用户并不清楚这些,所以在设计的过程中就要考虑全面,要分开设计。在本次课程设计中,我均对每个程序的开始时,用if isrgb(x)进行判断。
3、在没有加入噪声的情况下,点击“中值滤波”或是其它滤波,会提示错误?
这是由于在滤波程序设计的过程中,开始用到的变量是handles.noise_img,而这个变量是在加入噪声时候才定义的,所以在没有加入噪声的情况下,点击各个滤波就会弹出变量没有定义的错误,解决方法就是在文件打开的时候就给定义handles.noise_img=x。
4、本次设计存在一个比较大的问题,就是每次操作都是的,比如要对图像加入噪声,然后在此基础上进行亮度调整,截图,频谱分析等等就不行。
我认为应该是整个程序设计过程中对变量的设置没有做好,应该每次操作后,把处理后的数据保存在一个全局变量,这样还要对处理后的数据进行在处理时,只要把这个全局变量作为原始数据带入就可。
参考文献
[1]LIBERTI J,RAPPAPORT T S.Smart antennas for wireless communicaitions IS-95 and third generation CDMA applicaitions[M].Upper Saddle River NJ,USA:Prentice Hall,1999.
[2]LU M,LO T, L J.A decision-directed beamforming algorithm for CDMA systems with noncohereht m-ary orthogonal Modulation[J].Submitted to IEEE Trans.on commm,1995,43(12):2920-2924.
[3]刘敏. MATLAB通信仿真与应用[M].北京:国防工业出版社,2001.
[4]桑怀胜,李峥嵘. 智能天线的原理、自适应波束形成算法的研究进展与应用[J]. 国防科技大学学报,2001,23(6):83-.
附 录
function varargout = two(varargin)
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @two_OpeningFcn, ...
'gui_OutputFcn', @two_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT
% --- Executes just before erzhi is made visible.
function two_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
--------------------
%接下来是菜单的程序
---------------------
function file_Callback(hObject, eventdata, handles)
---------------------
%文件打开程序
function open_Callback(hObject, eventdata, handles)
载入图像');
if isequal(name,0)|isequal(path,0)
errordlg('没有选中文件','出错');
return;
else
x=imread([path,name]);
axes(handles.axes1);
imshow(x);
handles.img=x;
handles.noise_img=x;
guidata(hObject,handles)
end
----------------
function save_Callback(hObject, eventdata, handles)
%文件保存
图片保存为');
if isequal([filename,pathname],[0,0])
errordlg('没有保存','出错');
return;
else
file=strcat(pathname,filename);
(handles.axes2);
i=getimage(gca);
imwrite(i,file);
end
-----------------
function exit_Callback(hObject, eventdata, handles)
clc;
close all;
close(gcf);
----------------
%编辑菜单的程序
----------------
function edit_Callback(hObject, eventdata, handles)
------------
function huidu_Callback(hObject, eventdata, handles)
%灰度处理
axes(handles.axes2);
if isrgb(handles.img)
y=rgb2gray(handles.img); %RGB
imshow(y);
else
msgbox('这已经是灰度图像','转换失败');
end
-----------------
function liangdu_Callback(hObject, eventdata, handles)
%亮度处理
prompt={'输入参数1','输入参数2','输入gamma'};
defans={'[0 0.7]','[0 1]','1'};
p=inputdlg(prompt,'输入参数',1,defans);
p1=str2num(p{1});
p2=str2num(p{2});
p3=str2num(p{3});
gamma=p3;
x=(handles.img);
y=imadjust(x,p1,p2,gamma);
axes(handles.axes2);
imshow(y);
---------
function jietu_Callback(hObject, eventdata, handles)
%截图
set(handles.axes2,'HandleVisibility','ON');
axes(handles.axes2);
y=imcrop(handles.img);
imshow(y);
handles.Timage=y;
----------
function fangda_Callback(hObject, eventdata, handles)
-----------
function lingjz_Callback(hObject, eventdata, handles)
%邻近插值放大
axes(handles.axes2);
prompt={'输入放大倍数:'};
defans={'2'};
p=inputdlg(prompt,'输入放大倍数',1,defans);
p1=str2num(p{1});
y=imresize(handles.img,p1,'nearest'); %最近邻插值法放大
imshow(y);
--------------
function shuangxianfa_Callback(hObject, eventdata, handles)
%双线放大
axes(handles.axes2);
prompt={'输入放大倍数:'};
defans={'2'};
p=inputdlg(prompt,'输入放大倍数',1,defans);
p1=str2num(p{1});
y=imresize(handles.img,p1,'bilinear'); %最近邻插值法放大
imshow(y);
----------
function shuangsanci_Callback(hObject, eventdata, handles)
%双三次放大
axes(handles.axes2);
prompt={'输入放大倍数:'};
defans={'2'};
p=inputdlg(prompt,'输入放大倍数',1,defans);
p1=str2num(p{1});
y=imresize(handles.img,p1,'bicubic');
imshow(y);
-------------------------------------------------------
function suoxiao_Callback(hObject, eventdata, handles)
%邻近插值缩小
axes(handles.axes2);
prompt={'输入放大倍数:'};
defans={'0.2'};
p=inputdlg(prompt,'输入放大倍数',1,defans);
p1=str2num(p{1});
y=imresize(handles.img,p1,'nearest'); %最近邻插值法缩小
imshow(y);
-------------
function shuangxian_Callback(hObject, eventdata, handles)
%双线性缩小
axes(handles.axes2);
prompt={'输入放大倍数:'};
defans={'0.2'};
p=inputdlg(prompt,'输入放大倍数',1,defans);
p1=str2num(p{1});
y=imresize(handles.img,p1,'bilinear'); %最近邻插值法缩小
imshow(y);
---------------
function shuangsancisuox_Callback(hObject, eventdata, handles)
%双三次缩小
axes(handles.axes2);
prompt={'输入放大倍数:'};
defans={'0.2'};
p=inputdlg(prompt,'输入放大倍数',1,defans);
p1=str2num(p{1});
y=imresize(handles.img,p1,'bicubic');
imshow(y);
-------------
function xuanzhuan_Callback(hObject, eventdata, handles)
-----------
function updown_Callback(hObject, eventdata, handles)
%上下翻转
axes(handles.axes2);
x=(handles.img);
if isrgb(handles.img)
for k=1:3
y(:,:,k)=flipud(x(:,:,k));%上下翻转函数
end
imshow(y);
else
x=(handles.img);
y=flipud(x);
imshow(y);
end
-------------
function leftright_Callback(hObject, eventdata, handles)
%左右翻转
axes(handles.axes2);
if isrgb(handles.img)
x=(handles.img);
for k=1:3
y(:,:,k)=fliplr(x(:,:,k));%左右翻转函数
end
imshow(y);
else
x=(handles.img);
y=fliplr(x);
imshow(y);
end
---------------
function zeft90_Callback(hObject, eventdata, handles)
%左转90度
axes(handles.axes2);
x=(handles.img);
y=imrotate(x,90);
imshow(y);
------------
function right90_Callback(hObject, eventdata, handles)
%右转90度
axes(handles.axes2);
x=(handles.img);
y=imrotate(x,-90);
imshow(y);
------------
function other_Callback(hObject, eventdata, handles)
%任意角度旋转
axes(handles.axes2);
prompt={'输入参数1:'};
defans={'30'};
p=inputdlg(prompt,'输入参数',1,defans);
p1=str2num(p{1});
y=imrotate(handles.img,p1);
imshow(y);
-------------
function gs_Callback(hObject, eventdata, handles)
%加入高斯噪声
axes(handles.axes2);
prompt={'输入参数1:','输入参数2'};
defans={'0','0.02'};
p=inputdlg(prompt,'输入参数',1,defans);
p1=str2num(p{1});
p2=str2num(p{2}); y=imnoise(handles.img,'gaussian',p1,p2);
imshow(y);
handles.noise_img=y;
guidata(hObject,handles);
------------
function jy_Callback(hObject, eventdata,
handles)
%加入椒盐噪声
prompt={'输入参数1:'}; %对话框的设置,用户输入的是字符串
defans={'0.02'}; %缺省值
p=inputdlg(prompt,'输入参数',1,defans);
p1=str2num(p{1}); %字符串转化为数值
axes(handles.axes2);
x=(handles.img);
y=imnoise(x,'salt & pepper',p1);
imshow(y);
handles.noise_img=y;
guidata(hObject,handles);
------------
function cx_Callback(hObject, eventdata, handles)
%加入乘性噪声
axes(handles.axes2);
prompt={'输入参数1:'};
defans={'0.02'};
p=inputdlg(prompt,'输入参数',1,defans);
p1=str2num(p{1});
y=imnoise(handles.img,'speckle',p1);
imshow(y);
handles.noise_img=y;
guidata(hObject,handles);
------------
function zhifangtutongji_Callback(hObject, eventdata, handles)
-------------
function red_Callback(hObject, eventdata, handles)
%R直方图
set(handles.axes2,'HandleVisibility','ON');
axes(handles.axes2);
x=imhist(handles.img(:,:,1)); %直方图统计
x1=x(1:10:256);
horz=1:10:256;
bar(horz,x1);
set(handles.axes2,'xtick',0:50:255);
-----------
function gray_Callback(hObject, eventdata,
handles)
%G直方图
set(handles.axes2,'HandleVisibility','ON');
axes(handles.axes2);
if isrgb(handles.img)
x=imhist(handles.img(:,:,2)); %直方图统计
x1=x(1:10:256);
horz=1:10:256;
bar(horz,x1);
set(handles.axes2,'xtick',0:50:255);
else
msgbox('这是灰度图像','旋转失败');
end
----------
function blue_Callback(hObject, eventdata, handles)
%B直方图
set(handles.axes2,'HandleVisibility','ON');
axes(handles.axes2);
if isrgb(handles.img)
x=imhist(handles.img(:,:,3)); %直方图统计
x1=x(1:10:256);
horz=1:10:256;
bar(horz,x1);
%axis([0 255 0 150000]);
set(handles.axes2,'xtick',0:50:255);
%set(handles.axes2,'ytick',0:2000:15000);
else
msgbox('这是灰度图像','旋转失败');
end
----------
function junheng_Callback(hObject, eventdata, handles)
%直方图均衡
set(handles.axes2,'HandleVisibility','ON');
axes(handles.axes2);
if isrgb(handles.img)
a=histeq(handles.img(:,:,1));
b=histeq(handles.img(:,:,2));
c=histeq(handles.img(:,:,3));
k(:,:,1)=a;
k(:,:,2)=b;
k(:,:,3)=c;
imshow(k);
else
h=histeq(handles.img); %直方图均衡
imshow(h);
end
-------------