《数字图像处理与机器视觉——Visual C++与Matlab实现(第2版)》——第 1 章 MATLAB数字图像处理编程基础2.1 MATLAB R2011a简介...

本节书摘来自异步社区出版社《Visual C++ 2012 开发权威指南》一书中的第1章,第1.1节,作者: 张铮 , 徐超 , 任淑霞 , 韩海玲,更多章节内容可以访问云栖社区“异步社区”公众号查看。

第 1 章 MATLAB数字图像处理编程基础

数字图像处理与机器视觉——Visual C++与Matlab实现(第2版)
MATLAB是Mathworks公司开发的一款工程数学计算软件。不同于C++、Java、FORTRAN等高级编程语言,它们是对机器行为进行描述,而MATLAB是对数学操作进行更直接的描述。MATLAB图像处理工具箱(Image Processing Toolbox,IPT)封装了一系列针对不同图像处理需求的标准算法,它们都是通过直接或间接地调用MATLAB中的矩阵运算和数值运算函数来完成图像处理任务的。

2.1 MATLAB R2011a简介

数字图像处理与机器视觉——Visual C++与Matlab实现(第2版)
本节将介绍一些MATLAB R中与图像处理密切相关的数据结构及基本操作,如基本文件操作、变量使用、程序流程控制、打开和关闭图像以及图像格式转换和存储方式等。这些都是后续将要学习的图像处理算法的基础。

2.1.1 MATLAB软件环境

1.软件界面
图1.1所示是运行于32-bit Windows操作系统上的MATLAB R截图。软件主界面由3个子窗口组成,左上为当前工作目录的文件列表,右上方为当前工作区的变量,右下为当前和最近会话的命令历史记录,而中间的主窗口则是命令输入和结果输出区,>>为提示符。

image

图1.1 MATLAB界面

2.MATLAB命令与程序
可以在>>提示符后面输入简单的算式(例如53-2)或带有函数的算式(例如sin(pi/2)sqrt(3)/2)并回车,会提示ans=0.8660,这就是MATLAB最基本的计算功能。

这样的输入形式实际上是MATLAB命令,而如果在每行命令的结尾输入半角分号,命令窗口不会立即显示命令执行的结果,而会将结果保存在工作区中。例如下面的命令。

res = sin(pi/2)*sqrt(3)/2; % 将计算结果保存至变量res当中
此时,变量res已经存在于工作区中,但是命令窗口不会回显它的值。

另外,也可以在文件菜单下执行“New”→“M-Files”命令来创建一个新的MATLAB文件,在里面输入命令(以半角分号结尾),从而得到一个MATLAB程序。在MATLAB程序中,使用“%”表示注释,其用法和C/C++中的“//”注释符类似。

3.跨行语句
MATLAB允许在同一行中输入多条语句,之间用分号隔开。同时,MATLAB还允许将同一条语句分割在多行中书写以方便较长语句的阅读,方法是在行末使用3个半角圆点。例如下面的语句。

>> z = 2 .* x +exp( x .^ 2 + y .^ 2 - sqrt(1 - log(x) - log (y) ) )...
       - y .* sqrt(t)  - x .* sqrt(t);```
###2.1.2 文件操作
默认情况下,MATLAB可以自动搜索到当前目录(Current Directory)和MATLAB的路径变量path中所含有目录下面的文件。对处在这些位置可由MATLAB执行的文件,直接在命令窗口中输入文件名即可运行。如果需要直接运行其他目录下的文件,就要使用addpath和genpath等命令向路径列表中添加路径。

1.addpath函数
向path变量中加入指定的目录路径,其原型如下。

`addpath('dir','dir2','dir3' ...'-flag')`
该函数可以接受任意数目的参数。

参数说明:

dir、dir2、dir3等为要加入的目录路径,这些变量必须是绝对路径;
flag参数可以用来指定函数的行为,它是可选参数,其取值的含义如表1.1所示。
表1.1 addpath函数中flag参数的取值

![image](https://yqfile.alicdn.com/5e356b22b686210f099bfb07b71b93bf9faf42a6.png)

可以在使用addpath函数前后查看path变量的内容,以确定添加成功。

2.genpath函数
生成包含指定目录下所有子目录的路径变量,其原型如下。

`p = genpath('directory');`
参数说明:

参数directory为指定的目录。
返回值:

函数返回包含指定目录本身和其全部子目录的数据。返回值也可以直接提供给addpath,从而直接添加一个目录及其全部子目录到当前路径列表中。通过这样的方式可以方便地调用自己的程序工具箱,例如使用下面的命令将目录“F:\doctor research\Matlab Work\FaceRec”添加到系统当前路径列表后,就可以直接调用人脸识别工具箱FaceRec中的任何函数了。
`>> addpath(genpath('F:\doctor research\Matlab Work\FaceRec'))  %`注意这里要使用绝对路径
也可以在运行M文件时使用完整的文件路径,从而避免同名文件的冲突问题,或是从资源管理器中将M文件拖动到MATLAB的命令窗口中直接运行。

3.打开与编辑M文件
如果需要编辑某个M文件,可以使用open命令和edit命令,它们的调用形式如下。

open filename
edit filename`
参数filename为需要打开的文件名。edit命令只能编辑M文件,而open命令可以使用Windows默认操作打开一系列其他类型的文件。

2.1.3 在线帮助的使用

在MATLAB中,有以下4种方法获取软件的在线帮助。

1.help命令
help命令可以用于查看MATLAB系统或M文件中内置的在线帮助信息。命令格式如下。

help command-name
command-name为需要查看在线帮助的命令或函数的名称。例如,想要查看doc命令的使用方法,可在命令提示符下直接输入“help doc”,如图1.2所示。

image

图1.2 help命令界面

2.doc命令
doc命令可以用于查看命令或函数的HTML帮助,这种帮助信息可以在帮助浏览器窗口中打开。其调用格式如下。

doc function-name
doc命令可提供比help命令更多的信息,还可能包含图片或视频等的多媒体例子,对图像处理工具箱中的函数更是如此。

图1.3所示为在命令行中输入doc imhist命令后出现的帮助示例界面。

3.lookfor命令
当忘记命令或函数的完整拼写时,可以使用lookfor命令查找当前目录和自动搜索列表下所有名字中含有所查内容的函数或命令。其调用格式如下。

image

图1.3 doc命令结果

lookfor keyword
keyword为指定要查找的关键字。此命令可以给出一个包含指定字符串的函数列表,其中的函数名称为超链接,点击即可查看该函数的在线帮助,如图1.4所示。
image

图1.4 lookfor命令界面

4.F1命令打开帮助浏览器
在MATLAB R的主界面中按键盘的“F键,弹出如图1.5所示的对话框。

单击左下角的“Open Help Browser”链接打开如图1.6所示的帮助浏览器窗口。在左上角的编辑框中输入感兴趣的关键字,单击回车进行查询,右侧会出现相应的帮助信息。
image

图1.5 F1命令界面

在后面的章节中,如果忘记了曾经提到的命令的含义,建议首先通过在线帮助寻求相关信息,以此增强自学能力。

image

图1.6 Help浏览器界面

2.1.4 变量的使用

变量可以保存中间结果和输出数值等信息,MATLAB中变量的命名规则和C/C++等常见的编程语言很类似,同时也对大小写是敏感的。另外,MATLAB中的变量不需要先行定义,但在使用前一定要赋值。

1.变量的赋值
可以通过赋值语句来给变量赋值。赋值操作使用等号“=”,例如a=5是给a(注意不是A)这个变量赋值5,如果未定义变量a,会自动定义。在MATLAB中,变量定义时不需要显式地指明类型,Matlab会根据等号右边的值自动确定变量的类型。默认的对数字的存储类型为double型或double型数组,而字符的存储类型为char型,字符串的存储类型为char型数组。

对字符串赋值时,需要用半角单引号“'”括起来(注意不是双引号,也不是任何的全角字符),例如msg='Hello world'。

2.内部变量
MATLAB有某些内部变量名和保留字,如表1.2所示。变量命名时不要与它们重名。

表1.2 MATLAB内部变量列表
image

image

3.查看工作区中的变量
使用who和whos命令可以查看所有当前工作区中变量的情况。使用clear或clear all命令可以清除工作区中所有的变量定义,也可以在clear后面加上变量名,清除特定的变量定义。另外,clc命令可以用来清屏,所以这两个命令常常用在M文件的开头用来构造一个干净的工作区。

>> a = 1; %定义一个数值型变量a
>> str = 'hello'; %定义一个字符串变量(字符数组)
>> v = [3 2 1] %定义一个数值型向量
v =
     3     2     1
>> whos
  Name      Size            Bytes  Class     Attributes
  a         1x1                 8  double              
  str       1x5                10  char                
  v         1x3                24  double              
>> clear all
>> whos
>>```
4.数据类型及其转换
MATLAB中的数据类型列表如表1.3所示。

表1.3 MATLAB数据类型
![image](https://yqfile.alicdn.com/0b14bb9680ef806c5558e38181821c722c922fff.png)
![image](https://yqfile.alicdn.com/3eac2ca6ff8bcc3ce28d215df922c1a00ed422cf.png)


默认情况下,MATLAB将变量存储为双精度浮点数(double),而MATLAB中的很多函数也只接受这种类型的数据。然而,图像处理操作中经常使用到uint8等类型的数据,这就需要执行数据类型的强制转换操作。这种操作很简单,调用格式统一如下。

Destination_Var = type_name(Source_Var)`
其中,type_name即数据的存储类型,Destination_Var和Source_Var分别为目标变量和原始变量。例如下面的命令将double原始变量a 转换为uint8变量b。

>> a = 1;
>> b = uint8(a);```
5.读取与保存工作区中的变量
save命令可以将当前工作区的变量以二进制的方式保存到扩展名为MAT的文件中;load命令可以读出这样的文件。它们的调用格式如下。

save filename arg1 arg2 arg3, …
load filename arg1 arg2 arg3, …`
filename参数指定保存或读取变量所使用的文件名。如果不指定文件名,默认使用的文件是matlab.mat。
arg1、arg2、arg3等参数是需要从文件中存储或读出的变量名。这两个命令分别可以存储或读取一个或一组变量。
下面的命令将price、age和number三个变量保存到文件MyData.mat中。
>> save('MyData.mat', 'price', 'age', 'number')
提示 也可以不指定变量名,从而将当前工作区中所有的变量一起储存到mat文件或将文件中保存的所有变量一起读入工作区,这个批量保存和读取功能在运行非常耗时的程序时显得十分有用——由于MATLAB执行效率并不高(和Visual C++相比),所以对于一个计算量很大的程序而言,运行几个小时并不稀奇。这时,可以根据需要在希望中断程序时保存程序的所有上下文变量,以备之后随时从中断点开始执行。
2.1.5 矩阵的使用
1.矩阵的定义
在MATLAB中定义矩阵很简单。可以使用半角分号分隔行与行,使用半角逗号(或者空格)分隔列与列来直接定义矩阵,比如下面的命令就定义了一个3行3列的二维矩阵A。

A=[1, 2, 3; 4, 5, 6; 7, 8, 9]
A =
     1     2     3
     4     5     6
     7     8     9```
还有另一种方式可以生成行向量,[begin:inc:end]会生成从begin开始到end结束,增量为incre的一系列数字组成的向量。如v=[2:1:10]表示生成从2到10的间隔为1的向量(一维矩阵),即:

v= [2:1:10]
v=

 2     3     4     5     6     7     8     9    10```

如果间隔为1,也可以忽略中间的参数,直接输入I=[2:10]即可。

2.生成特殊矩阵
除直接定义外,可以通过函数生成特定的矩阵,比如eye(n)生成N阶单位阵,zeros(n)生成N阶每个元素均为0的方阵,magic(n)生成N阶幻方阵等。常见的用于生成矩阵的函数列表如表1.4所示。

表1.4 生成矩阵的函数
image
image

3.获得矩阵大小和维度
size函数可以获得指定数组某一维的大小,可以用来查看图像的高度和宽度以及动态图像的帧数等。其调用方法如下。

size(A,dim)
A为需要查看大小的数组;
dim为指定的要查看的维数,这是一个可选参数,若不指定此参数,返回值为一个包含数组从第一维到最后一维大小的数组。
例如,对于一个3行5列的矩阵B,有size(B, 1)=3,size(B, 2) = 5,size(B) = [3 5]。

函数ndims可以查看数组的维数。调用方式如下。

ndims(A)
其中A为需要查看维数的数组。

4.访问矩阵元素
访问矩阵的一个元素的方式是在矩阵名字的后面注明行列序号,例如访问A的第3行第2列元素就是A(3,2)。提取矩阵的一整行元素,如要提出A的第2行使用A(2,:),如果是第2列则是A(:,2);而A(:)表示将矩阵按列存储得到一个长列向量。示例如下。

>> A=[1, 2, 3; 4, 5, 6; 7, 8, 9] ; %定义矩阵A
>> A(1, :) %提取第1行
ans =
     1     2     3
>> A(:, 3) %提取第3列
ans =
     3
     6
     9
>> A(:)'
ans =
     1     4     7     2     5     8     3     6     9```
注意  MATLAB中的矩阵下标是从1开始的。对图像矩阵也是一样,所以一个m×n的矩阵实际的下标范围为[1:m]和[1:n]。
对于矩阵A,提取矩阵元素或子块的方法如表1.5所示。

表1.5 提取矩阵元素或子块的方法

![image](https://yqfile.alicdn.com/c43b67b3d06cccd6fab8ba4a6f9d2f85ac9ed6f1.png)

5.进行矩阵运算
可以像对数字操作一样对矩阵进行操作,常见算术运算符的使用方法如表1.6所示。

表1.6 常见的算术运算符
![image](https://yqfile.alicdn.com/756f74442e83705253bdcfe28e9df0e00ea5021b.png)

![image](https://yqfile.alicdn.com/4cd896a59ac2156ccd62830c4e1d8b7ed6fcdb18.png)

应用于复数数值时的含义是取共轭,应用于实数矩阵时的含义与普通转置相同,应用于复数矩阵时首先对所有元素取共轭再求矩阵转置

矩阵运算的求值顺序和一般的数学求值顺序相同:表达式是从左向右执行的,幂运算的优先级最高,乘除次之,最后是加减。如果有括号,那么括号的优先级最高。

对于图像矩阵,还有一系列MATLAB函数可以进行专门针对图像的像素级操作。如图像叠 加——imadd,图像相减——imsubtract等。

###2.1.6 细胞数组(Cell Array)和结构体(Structure)
1.细胞数组
在处理函数返回值和示波器部件输出时,常常会遇到不同维度的返回值同时被一个函数返回的情况。同时,通常也希望能使函数的输入参数尽可能少。MATLAB提供了允许这样做的方式。

细胞数组是MATLAB特有的一种数据结构,它的各个元素可以是不同的数据类型。细胞数组可采用下标访问。

例如,一个细胞数组可以采用如下方式定义。

Cell = {'Harry', 15, [1 0; 15 2]};
也可以通过{}加上索引来直接定义细胞数组的某个元素,如下所示。

%定义细胞数组的另一种方式

Cell {1}= 'Harry';
Cell{2}= 15;
Cell{3}= [1 0; 15 2];`
注意使用花括号{}而不是方括号[]来定义细胞数组。对细胞数组的访问方式也很简单,同样使用花括号{}来给定索引值。

%访问细胞数组
>> Cell{1}
ans =
Harry
>> Cell{2}
ans =
    15
>> Cell{3}
ans =
     1     0
    15     2```
而使用圆括号形式的索引可以得到变量的描述,如下所示。

`>> Cell(3)
ans = 
[2x2 double]`
注意 细胞数组中存储的是建立该对象时所使用的其他对象(矩阵或字符串、数字等)的复制而不是引用或指针,即使其他对象的值被改变,细胞数组中的值也不变。
2.结构体
结构体是另一种形式的聚合类型,它与C/C++中的结构体或类很相似,拥有多个不同类型的字段,通过圆点运算符“.”引用内部字段,字段必须具有独特的名字以便区分。访问结构体的方式与定义的方式相同。上面的例子如果用结构体表示,则如下所示。

% 定义结构体
Struct.Name = 'Harry';
Struct.Age = 15;
Struct.SalaryMatrix = [1 0; 15 2];

Struct %显示结构体的内容

Struct =

        Name: 'Harry'
         Age: 15
SalaryMatrix: [2x2 double]

% 访问结构体的内部字段
name = Struct.Name;`

而访问结构体内容时,使用相同的语法即可,例如Struct.Name的值仍然是“Harry”。

这两种复合类型在保存用户输入和使用Simulink仿真输出时尤为常用。

2.1.7 关系运算与逻辑运算

关系运算符的运算结果是布尔量(0或1),具体说明如表1.7所示。

表1.7 关系运算符的使用

image

MATLAB同样支持逻辑运算,常见的逻辑运算符如表1.8所示。

表1.8 逻辑运算符的使用
image

1.1.8 常用图像处理数学函数

MATLAB最为强大的功能是依靠函数实现的,这些函数可能是MATLAB内置的,也可能是由M文件提供的。常见的有sin、cos、tan、log、log2这样的数值函数和trace这样的矩阵函数,还有逻辑函数等。逻辑函数和矩阵函数在图像处理中应用较多,表1.9所示为其中较常用的一部分函数。关于这些函数更详细的用法描述,可以通过help或open命令获得。

表1.9 常用的逻辑函数和矩阵函数
image
image

调用MATLAB函数的方法为:函数名后使用一对圆括号括住提供给函数的参数,如sin(t)。如果函数有返回值,但调用者没有指定接收返回值的变量,系统会使用默认的ans变量存储返回值。如果函数返回多个值,则ans中只保留第一个返回值,因此对于这种情况应显式地使用向量来接收返回值,如下所示。

[V D] = eigs(A) ; %计算矩阵A的特征值和特征向量,返回值中V为特征向量,D为特征值
使用函数还应当注意以下几点。

(1)函数只能出现在等式的右边。

(2)每个函数依原型不同,对自变量的个数和类型有一定的要求,如sin和sind函数。

(3)函数允许按照规则嵌套,比如sin(acos(0.5))。

2.1.9 MATLAB程序流程控制

MATLAB提供了程序流程分支控制的语句,它们的用法和C/C++中几乎完全一致,如表1.10所示。

表1.10 程序流程控制方法
image
image

1.简要示例
在后面,将多次使用这些语句,因而,在此给出几个简单的例子。读者可以在金羽图书论坛(http://bbs.book95.com) 的“金羽图书与答疑”板块与本书同名的主题帖子附件中的chapter1/code目录下找到示例1.1~示例1.3所对应的M文件,也可以通过菜单“File”→“New”→“M-Files”新建一个M文件,在出现的窗口中粘贴这些代码,然后运行。在非注释行处按下F12可以设置断点,按下F5键可以运行程序。

【例1.1】if语句和for循环及其嵌套。

%ex1_1.m
arg=input('Input argument:');  % 提示输入arg变量
total = 0; detail = 0;
% if语句开始
if(arg==1)
    % 外层for语句开始
    for i=1:1:5
        total = total + 1;
        % 内层for语句开始
        for j=1:0.1:2
            detail = detail + total;
        % 内层for语句结束
        end
    % 外层for语句结束
    end
 % if语句的另一分支
elseif (arg==2)
    total = 0;
    detail = total;
% if语句的其他所有分支
else
    error('Invalid arguments!');
%if语句结束
end
detail  % 显示detail变量```
请注意本例中分号的使用。

【例1.2】与例1.1类似的功能,使用switch分支和while循环。

%ex1_2.m
arg=input('Input argument:');
total = 0; detail = 0;
% switch语句开始
switch arg

% 分支1
case 1
    i=1;
    % 外层while语句开始
    while (i<=5)
        total = total + 1;
        i = i + 1;
        j = 1;
        % 内层while语句开始
        while (j<=2);
            detail = detail + total;
            j = j + 0.1;
        % 内层while语句结束
        end
    % 外层while语句结束
end
% 分支2
case 2
    total = 0;
    detail = total;
% 分支其他
case others
    error('Invalid arguments');

% switch语句结束
end
detail`
总结这两个例子,可以发现,在分支较多时使用switch是合算的,而for和while用于循环控制,这一点与C/C++是完全相同的。但是,相对于C/C++,MATLAB有一个突出的优点,就是可以自动生成元素之间具有特定间隔的矩阵,从而避免使用某些循环,这里仅仅使用二维的情况举例。

【例1.3】产生一幅亮度按对角线方向的余弦规律变化的灰度图,比较一维方法和二维方法所需的时间。

A = rand(3000, 3000);
f = zeros(3000, 3000);
u0 = 100; v0 = 100;

tic; % 开始计时
% 一维方法
% 外层for循环开始
for r=1:3000
        u0x=u0*(r-1);
        % 内层for循环开始
        for c=1:3000
            v0y=v0*(c-1);
            f(r,c) = A(r,c) * cos(u0x+v0y);
        % 内层for循环结束
        end
% 外层for循环结束
end
t1=toc     % 停止计时并记录时间到t1

tic; % 重新开始计时
% 二维方法
r = 0:3000-1;
c = 0:3000-1;
[C, R] = meshgrid(c, r);
% meshgrid是生成网格坐标的函数,实际就是生成需要的二维像素点的坐标拟合表示
% 建议读者在这里中断,观察一下C和R矩阵的内容。

g = A .* cos(u0 .* R + v0 .* C);
%系统将自动执行“循环”操作,实质是对R和C中每个数据按照指定公式操作

t2 = toc % 停止计时并将计时值保存到t2```
在运行之后,结果发现,t2远小于t1。因此,在用MATLAB对数字图像按像素进行操作时,需要尽可能地避免使用笨拙的多层嵌套循环。

2.meshgrid()函数
例1.3中用到的meshgrid()函数用于根据给定的横纵坐标点生成坐标网格,以便计算二元函数的取值,在绘制三维曲面时常常会用到它。其调用方式如下。

`[X,Y] = meshgrid(x, y)`
参数说明:

x为输入的横坐标;
y为输入的纵坐标。
返回值:

X和Y为输出采样点的横坐标矩阵和纵坐标矩阵,X阵和Y阵的元素分别为对应位置点的横坐标和纵坐标。
下面以绘制二维高斯函数曲面为例说明meshgrid的用法。

中心在原点的二维高斯函数表达式为:

下面的程序分别为u和v赋值[-10:0.1:10],令σ=3,使用meshgrid函数生成网格,并计算函数值,(注意这里使用的是.^和./,而不是^和/,因为计算的对象是矩阵中的元素),然后再使用mesh函数将其显示到绘图窗口中。

u = [-10:0.1:10];
v = [-10:0.1:10];
[U,V] = meshgrid(u,v);
H = exp(-(U.^2 + V.^2)./2/3^2);
mesh(u, v, H);`
% mesh函数是绘制三维曲面的函数,第一个和第二个参数分别为_x_轴和_y_轴的坐标点序列,第三个参数为在由坐标点序列确定的每一个方格点上的函数值
生成的图像如图1.7所示。

image

优化小技巧:提前分配矩阵内存
这个技巧与动态内存的使用有关。在C/C++里,使用大块动态内存往往意味着堆操作,而当分配的动态内存零散无序时,会产生大量内存碎片,进而导致内存分配和回收效率降低。所以,可以事先分配一块足够大的空间(当然,不是过大)以尽量减少内存碎片的产生。事实上,MATLAB中分配动态内存远没有C/C++那样麻烦,只需要类似如下一条语句即可。
memo = zeros(1024, 128);
这条语句本来是用于构造一个元素全部为零的矩阵,但同时很自然地也就分配了一块足够大的空间。

2.1.10 M文件编写

M文件和C/C++中c/cpp文件类似,就是存储MATLAB代码并可以执行的文件。MATLAB的源代码文件可以直接执行而不需编译(也可以通过编译来使代码运行得更快)。很多情况下,M文件用于封装一个功能函数从而提供某些特定功能。一般来说,M文件以文本格式存储,执行顺序从第1行开始向下遇到终止语句结束,用户可以在M文件中定义函数和过程。

M文件可以使用任何文本编辑器编写,但最常使用的还是MATLAB自带的M文件编辑器。如果是编写函数,最好将它放在MATLAB的搜索路径列表中的某个目录下,并与系统自带的M文件分开,以便管理。

对于位于当前工作目录中的M文件,可以直接在命令行输入其文件名来运行它。作为函数时,M文件也可以接受参数。

稍后将提供一个MATLAB自带M文件的例子,并给予简单分析。

2.1.11 MATLAB函数编写

1.函数语法
MATLAB函数通常在M文件中定义,一个文件可以定义多个函数。一个MATLAB函数通常包含以下组成部分。

◆ 函数定义行

function [outputs] = name(inputs)
MATLAB允许返回多个参数(outputs),如果只返回一个参数,可以省略方括号。需要注意的是,输入参数是使用圆括号括起来的。例如,如果要定义一个用于平滑图像的函数imsmooth,可以将定义行书写如下。

function [imgOut, retCode] = imsmooth(imgIn, args)
某些函数可能没有输出参数,那么就需要在省略方括号及其中内容的同时,省略等号。于是无返回值的函数就需要定义如下。

function imsmooth(imgIn, args)
MATLAB允许区分函数名的前63个字母,多出的字母将被忽略。函数的命名规则与C/C++类似,必须以字母开头,可以包含字母、数字和下划线,但不能包含空格。

函数可以在其他的M函数中被调用,也可以在命令行直接调用。调用函数的方法很简单,只需要写出函数定义中除了function之外的部分即可。例如:

`[a,b] = imsmooth(I,arg);
◆“H1”行`

“H1”行是M文件中的第一个注释行(即以百分号开始的行),它必须紧跟着函数定义行,中间不能有空行,这一行的百分号前也不能有空白字符或缩进。这一行的内容将在使用help命令时显示在第一行,而lookfor命令查找H1行中的指定关键词,并在结果的右侧列显示H1行。一个典型的H1行的例子如下。

% IMSMOOTH Perform smooth operation on specified image with certain arguments.
这样,smooth函数在lookfor命令查找的时候就会显示如下。

IMSMOOTH SMOOTH Perform smooth operation on specified image with certain arguments.
◆ 帮助文本

帮助文本的位置和约定同H1行类似,只能紧跟H1行,中间不能有任何空行或者缩进。同样,帮助文本的本质就是注释行,因而需要以%开头。

MATLAB通过判断是否紧跟函数定义来判断一个注释行究竟是H1行、帮助文本,还是普通注释。因此可以在加入一个或多个空行后加入普通注释,使用Help命令将不会显示普通注释的内容。

◆ 函数体和备注

这些部分的编写方式和普通的MATLAB程序类似,如果有返回值,应在函数体中为输出变量赋值。

2.一个M文件的例子片断
可以在命令行输入edit imfinfo查看完整源文件。

function info = imfinfo(filename, format)                     %函数定义
%IMFINFO Information about graphics file.                     %H1行
%   INFO = IMFINFO(FILENAME,FMT) returns a structure whose    %帮助文本
%   fields contain information about an image in a graphics
%   file.  FILENAME is a string that specifies the name of the
%   graphics file, and FMT is a string that specifies the format
%   of the file.  The file must be in the current directory or in
%   a directory on the MATLAB path.  If IMFINFO cannot find a
%   file named FILENAME, it looks for a file named FILENAME.FMT.
%   
%   The possible values for FMT are contained in the file format
%   registry, which is accessed via the IMFORMATS command.
%
%   If FILENAME is a TIFF, HDF, ICO, GIF, or CUR file containing more
%   than one image, INFO is a structure array with one element for
%   each image in the file.  For example, INFO(3) would contain
%   information about the third image in the file.  
%
%   INFO = IMFINFO(FILENAME) attempts to infer the format of the
%   file from its content.
%
%   INFO = IMFINFO(URL,...) reads the image from an Internet URL.
%   The URL must include the protocol type (e.g., "http://").
%
%   The set of fields in INFO depends on the individual file and
%   its format.  However, the first nine fields are always the
%   same.  These common fields are:
%
%   Filename       A string containing the name of the file
%
%   FileModDate    A string containing the modification date of
%                    the file
%
%   FileSize       An integer indicating the size of the file in
%                   bytes
%
%   Format         A string containing the file format, as
%                  specified by FMT; for formats with more than one
%                  possible extension (e.g., JPEG and TIFF files),
%                  the first variant in the registry is returned
%
%   FormatVersion  A string or number specifying the file format
%                  version 
%
%   Width          An integer indicating the width of the image
%                   in pixels
%
%   Height         An integer indicating the height of the image
%                   in pixels
%
%   BitDepth       An integer indicating the number of bits per
%                   pixel 
%
%   ColorType      A string indicating the type of image; this could
%                   include, but is not limited to, 'truecolor' for a 
%                  truecolor (RGB) image, 'grayscale', for a grayscale 
%                  intensity image, or 'indexed' for an indexed image.
%
%   If FILENAME contains Exif tags (JPEG and TIFF only), then the INFO 
%   struct may also contain 'DigitalCamera' or 'GPSInfo' (global 
%   positioning system information) fields.
%
%   The value of the GIF format's 'DelayTime' field is given in hundredths
%   of seconds.
%
%   Example:
%     
%      info = imfinfo('ngc.jpg');
%
%   See also IMREAD, IMWRITE, IMFORMATS.

%   Copyright 1984-2008 The MathWorks, Inc.
%   $Revision: .14 $  $Date: 2009/11/09 16:27:13 $

error(nargchk(1, 2, nargin, 'struct'));        %函数体和注释
…(函数体)
% Delete temporary file from Internet download.
if (isUrl)
    deleteDownload(filename);
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值