MATLAB GUI设计入门与实战
上QQ阅读APP看书,第一时间看更新

1.3 函数及其调用

函数的使用在Matlab程序设计中是非常重要的。用户通过调用函数程序,可以大大地简化程序语句,减少程序冗余,并且用户可以很方便定位和查看模块化程序。特别是在程序调试过程中,函数化的程序将方便第三方查看和学习。

1.3.1 函数类型

MATLAB提供了友好的编程环境,用户可以采用MATLAB脚本文件(.m文件)进行函数书写,并且能够很简单地实现函数的嵌套调用,具体的MATLAB脚本文件如图1-20所示。

图1-20 MATLAB脚本函数文件

如图1-20所示为一函数脚本文件,函数脚本文件的书写和直接代码文件书写相同,只不过是将变化参量置留出来,供用户进行调用。

(1)函数常用的句柄是直接写一个函数,保存为一个函数文件,供用户调用。如一个加法运算函数的使用,具体如下:

    function y = add(s,w)
    % s:为一个数
    % w:为一个数
    % y:为s+w的和
    y = s + w;   % 加法运算
    end

保存即可得到一个函数文件,具体如图1-21所示。

图1-21 函数文件的生成

如图1-21所示,得到一个加法器的函数文件。采用函数文件的方式供用户使用,在GUI设计中,也常常应用。

用户可以在命令窗口调用该函数,具体如下:

    >> add(1,1)
    ans =
         2
    >> add(1,3)
    ans =
         4
    
    >> add(182,80378241)
    ans =
        80378423
    >> add(11740630,87)
    ans =
        11740717
    >>

(2)采用@function来创建,这种运算方式,我们在实际工程中,应用较少,但是对于简单的高等数学问题,则可以直接采用@function来创建,具体如下:

    % Designed by Yu Shengwei From SWJTU University
    % 2014年12月29日
    clc,clear,close all      % 清理命令区、清理工作区、关闭显示图形
    warning off               % 消除警告
    feature jit off          % 加速代码运行 
    
    y = @(s,w)s+w ;          % 加法运算
    y1 = y(1,2)               % 赋值
    y2 = y(117,4063087)      % 计算加和
    y3 = y(182803,78241)     % 计算加和
    
    y1 =
         3
    y2 =
         4063204
    y3 =
          261044

同样的可以对其进行循环赋值运算,具体操作如下:

    for i =1:10
        ysw(i) = y(i^2,2*i+1);                          % 加法运算
    end
    plot(ysw,'linewidth',2)                           % 线宽为2
    grid on                                            % 网格化
    haxes2=axes('position',[0.3,0.5,0.3,0.3]);      % 坐标轴二位置设置
    axis(haxes2);                                      % 轴设置
    plot(ysw,'ro--');                                 % 画图

运行程序输出图形如图1-22所示。

图1-22 函数图形

1.3.2 函数参数传递

从1.3.1小节可知,函数加法运算就是一个参数传递过程,MATLAB编写函数,在函数文件头需要写明输入和输出变量,才能构成一个完整的可调用函数。在主函数中调用时,通过满足输入关系,选择输出的变量,也就是相应的函数参数传递,MATLAB将这些实际值传回给相应的形式参数变量,每一个函数调用时变量之间互不冲突,均有自己独立的函数空间。

1.函数的直接调用

对于求解一个图像滤波器的程序,编写函数如下:

    function im_e = Homom_filter(im,d,rL,rH)

在命令中,im为输入的二维图像矩阵,d为截止频率,rL为低频增益,rH为高频增益。直接调用该函数即可得到滤波后的图像。

图像滤波函数如下:

    function im_e = Homom_filter(im,d,rL,rH)
    % 同态滤波
    % 函数输入
    %         im:  输入的二维图像矩阵
    %         d:   截止频率
    %         rL:   低频增益
    %         rH:   高频增益
    % 函数输出: 
    %         im_e: 重构滤波图像
    
    if ~isa(im,'double')
        im = double(im);
    end
    
    [r c]=size(im); % 输入图像维数
    % 高斯高通滤波
    A=zeros(r,c);
    for i=1:r
        for j=1:c
            A(i,j)=(((i-r/2).^2+(j-c/2).^2)).^(.5);
            B(i,j)=A(i,j)*A(i,j);                       % 元素平方
            H(i,j)=(1-exp(-((B(i,j)).^2/d.^2)));      % 传递函数
        end
    end
    
    % 同态滤波器传递函数
    H=((rH-rL).*H)+rL;
    % 取对数
    im_l=log2(im + 1e-5);
    % 离散傅里叶变换
    im_f=fft2(im_l);
    % 滤波
    im_nf=H.*im_f;
    % DFT反变换
    im_n=abs(ifft2(im_nf));
    % 指数变换,消除取对数
    im_e = exp(im_n);  % 滤波矩阵
    im_e = uint8(im_e);

具体调用如下:

    % 同态滤波
    clc,clear,close all      % 清理命令区、清理工作区、关闭显示图形
    warning off              % 消除警告
    feature jit off          % 加速代码运行
    tic
    im = imread('me.jpg');    % 读图
    im = imnoise(rgb2gray(im),'gaussian',0,1e-5);     % 原图像 + 白噪声
    
    % 同态滤波参数设置
    rL = 0.3999;              % 低频增益
    rH = 0.71;               % 高频增益
    D0 = 1;                   % 截止频率
    figure,
    subplot(121),imshow(im);title('原始图像')
    colormap(jet)              % 颜色
    shading interp             % 消隐
    im_e = Homom_filter(im,D0,rL,rH);               % 同态滤波
    subplot(122),imshow(im_e,[]);title('同态滤波图像')
    colormap(jet)              % 颜色
    shading interp             % 消隐
    toc

运行程序输出结果如下:

    时间已过 0.415661 秒。

输出滤波图像如图1-23所示。

图1-23 同态滤波图像(1)

如图1-23所示,对于已经写好的函数程序,用户只需要调用即可,也可以满足大规模项目同步进行,同时主程序可以用很简单的几句代码实现用户功能,因此函数的书写与调用显得很重要。

2.全局变量的使用

全局变量在大型的编程中,经常用到,特别是在GUI设计中,在每个功能模块下运行相应的程序,需要调用前面对应的输出和输入的变量,这时需要对应的全局变量。全局变量在MATLAB中用global表示,指定全局变量后,该变量能够分别在子函数和主函数中使用,全局变量在整个程序设计阶段基本保持一致。

对于同态滤波函数,采用全局变量的用法如下所述。

滤波函数程序修改如下:

    function im_e = Homom_filter_2(im)
    % Designed by Yu Shengwei From SWJTU University
    % 2014年12月29日
    % 同态滤波
    % 函数输入
    %         im:  输入的二维图像矩阵
    %         d:   截止频率
    %         rL:  低频增益
    %         rH:  高频增益
    % 函数输出
    %         im_e: 重构滤波图像
    global rL rH D0
    d = D0;
    
    if ~isa(im,'double')
        im = double(im);
    end
    
    [r c]=size(im); % 输入图像维数
    % 高斯高通滤波
    A=zeros(r,c);
    for i=1:r
        for j=1:c
            A(i,j)=(((i-r/2).^2+(j-c/2).^2)).^(.5);
            B(i,j)=A(i,j)*A(i,j);
            H(i,j)=(1-exp(-((B(i,j)).^2/d.^2)));  % 传递函数
        end
    end
    
    % 同态滤波器传递函数
    H=((rH-rL).*H)+rL;
    % 取对数
    im_l=log2(im + 1e-5);
    % 离散傅里叶变换
    im_f=fft2(im_l);
    % 滤波
    im_nf=H.*im_f;
    % DFT反变换
    im_n=abs(ifft2(im_nf));
    % 指数变换,消除取对数
    im_e = exp(im_n);  % 滤波矩阵
    im_e = uint8(im_e);

同理主函数程序如下:

    im = imread('me.jpg');                           % 读图
    im = imnoise(rgb2gray(im),'gaussian',0,1e-5);    % 原图像 + 白噪声
    
    % 同态滤波参数设置
    rL = 0.3999;                                      % 低频增益
    rH = 0.71;                                       % 高频增益
    D0 = 1;                                           % 截止频率
    global rL rH D0
    figure,
    subplot(121),imshow(im);title('原始图像')
    colormap(jet)                                      % 颜色
    shading interp                                     % 消隐
    im_e = Homom_filter_2(im);                       % 同态滤波
    subplot(122),imshow(im_e,[]);title('同态滤波图像')
    colormap(jet)                                      % 颜色
    shading interp                                     % 消隐

运行程序输出结果如图1-24所示。

图1-24 同态滤波图像(2)

对比图1-23和图1-24可知,Homom_filter_2(im)函数与Homom_filter(im,d,rL,rH)函数实现的功能是一样的,只是Homom_filter_2(im)函数输入量为1个,而Homom_filter(im,d,rL,rH)输入量为4个,主要原因在于Homom_filter_2(im)函数中的d、rL、rH这3个量采用全局变量来控制,具体代码为:

    global rL rH D0

因此全局变量的使用,可以减少函数变量的输入,避免用户过多地去重新定义,因此在实际应用中,也较常使用。