目录
一、内联函数与匿名函数
(一)内联函数
1. 特点
在命令窗口、程序或函数中创建局部函数,使用inline function不需要将其存储为一个.m文件,同时又可以像一般函数一样去调用它。
2. 语法
fhandle=inline(expr,arg1,arg2...)
其中,fhandle:函数句柄;expr:函数表达式;argi:函数参数
3. 优势
由于内联函数存储在内存中而不是.m文件中,所以省去了文件访问的时间,加快了程序运行的效率。
(二)匿名函数
1. 特点
用户可以编写简单的函数而不需要创建.m文件。具有inline函数的所有优点,比inline函数的运算效率还要高。
2. 语法
fhandle=@(arglist)expression
fhandle:函数句柄;arglist:参数列表
3. 例子
e.g.使用内联函数和匿名函数定义
f1=inline('x^2+y^2','x','y')
f2=@(x,y)x^2+y^2
二、MATLAB GPU 编程基础
(一)GPU设备确认
1. gpuDeviceCount 用于获取当前设备上的GPU的数量,语法格式为:
m=gpuDeviceCount
2.gpuDevice 用于选择GPU设备,语法格式为:
d=gpuDevice
%or
d=gpuDevice()
如果当前还未设置选择的GPU,则选择默认的GPU,D是返回对象;如果已经设置好了GPU,则返回设置的GPU对象。
d=gpuDevice(IDX)
表示选择IDX对应的GPU设置,D为返回对象
3. reset用于清空GPU内存,语法格式为:
reset(gpudev)
与clear命令功能类似,gpudev是gouDevice返回的对象。
4.例子
e.g.获取当前计算机的GPU数目,指定GPU设备,并清空所指定的GPU的内存
n=gpuDeviceCount
D=gpuDevice
reset(D)
(二)CPU与GPU之间的数据交互
1. gpuArray 用于将CPU内存的数据传到GPU内存中,语法格式为:
GX=gpuArray(x)
x为CPU中的内存变量,GX为GPU中的内存变量
2. gather 用于将GPU内存数据传到CPU内存中,语法格式为:
X=gather(GX)
GX为GPU中的内存变量,X为得到的CPU中的内存变量。
3. 例子
e.g.编程实现CPU与GPU之间内存变量的交互
X=rand(10,'single'); %单精度10*10数组(单精度每个数占4个字节)
GX=gpuArray(X); %在GPU定义变量GX,并将X的值传给GX
GX2=GX.*GX; %在GPU执行数组对应位置的点乘
X2=gather(GX2); %将在GPU上的运算结果GX2返回到CPU
e.g.编程比较CPU与GPU对大规模计算的运算效率
%CPU
A1=rand(12000,400);
B1=rand(400,12000);
tic
f1=sum(A1.'.*B1,1); %A1.':转置,.*对应元素相乘,1:按列相加
tCPU=toc
%GPU
A2=rand(12000,400,'gpuArray');
B2=rand(400,12000,'gpuArray');
tic
f2=sum(A2.'.*B2,1);
tGPU=toc
三、图像的基本操作
(一)数字图像的离散化表示
1.灰度图像
在MATLAB中图像是以二维矩阵的形式来表示的,矩阵中每一个元素代表一个像素,因此该矩阵也称为像素矩阵。元素值越大,对应的像素越亮。
在MATLAB中,矩阵元素的下标约定从(1,1) 开始;
2.RGB 图像
一幅分辨率为M✖️N的灰度图像,对应的数值矩阵为M✖️N维的矩阵,各个元素值的范围为[0,255];
一幅分辨率为M✖️N的RGB图像,对应的数值矩阵为M✖️N✖️3,分别对应R、G、B分量。
如果一幅图像的红色分量图比较亮,说明该RGB图像主要呈现为红色。
3. 索引图像
索引图像有两个分量,即整数的数据矩阵X和彩色映射矩阵map;map为m✖️3的浮点类型,m为其所定义的颜色数目,每一行定义了颜色的红、绿、蓝三个分量。如下图,左边数据矩阵存储每个像素点的颜色索引,右边矩阵存储图像所包含的所有颜色的RGB分量值。
(二)图像的读、写与显示
%读取图像
[I,map]=imread('image0.jpg'); %I为所得图像矩阵;
%map为彩色映射矩阵(若读取非索引矩阵,此参数可省略)
%图像大小
[m n]=size(I)
%显示图像
imshow(I)
imshow(I,[low high]);%将<=low的灰度显示为黑色,将>=high的灰度显示为白色
imshow(I,[]) %自动将low设置为I中的最小值,将high设置为I中的最大值;
%当图像矩阵的动态范围较小或有负值出现时经常用到
%保存图像
imwrite(I,filename); %将图像以文件名filename保存在存储器中,
%filename应包含扩展名,指定文件类型
(三)图像的邻域操作
1. 定义
将每个像素值利用其相应邻域信息进行处理的过程,所选的像素邻域通常远小于原图像的大小,且形状规则。
2.类型
滑动邻域操作和分离邻域操作
3.滑动邻域操作
(1)特点
- 滑动邻域是一个像素集,所包含的像素由中心像素的位置决定,操作的结果也作为该中心像素新的灰度值;
- 滑动邻域操作一个邻域只处理一个像素,即中心像素;为方便确定中心像素,通常采用奇数行、奇数列的矩阵窗口。
(2)实现步骤
- 选择一个单独的像素作为中心像素;
- 确定该像素的滑动邻域;
- 对邻域中的像素值应用一个函数求值,该函数将返回标量计算结果;
- 将计算结果作为输出图像中对应的像素点的值;
- 对输入图像的每个像素都重复上面4个步骤。
(3)函数实现
J=nlfilter(I,[m n],fun)
J=nlfilter(I,'indexed',[m n],fun)
其中,I为原图像;[m n]为指定大小为m✖️n的滑动邻域;
fun是对滑动邻域矩阵进行操作的函数,fun可以为函数句柄,用户可以定义匿名函数,提高代码效率
indexed是可选参数,指定这个参数,则表示原图像为索引图像。
e.g.使用nlfilter实现将每个像素设置为5✖️5邻域的最大值。
I=imread('tire.tif');
%myf=@(I)max(I(:));
%y=nlfilter(I,[5,5],myf);
y=nlfilter(I,[5,5],@my_max);
subplot(121);imshow(I);title('原图')
subplot(122);imshow(y);title('邻域操作结果')
figure
y=nlfilter(I,[5,5],@my_median);
subplot(121);imshow(I);title('原图')
subplot(122);imshow(y);title('邻域操作结果')
function y=my_max(x)
y=max(x(:));
end
(4)快速邻域块操作
colfilt函数为每个像素建立一个列向量,向量各元素对应该像素的邻域元素,减少了图像操作过程中的邻域定义的耗时。
J=colfilt(I,[m n],block_type,fun)
J=colfilt(I,[m n],[mblock unblock],block_type,fun)
J=colfilt(I,'indexed',...)
其中,I表示原图像;[m n]为指定大小为m✖️n的邻域块;
[mblock nblock]表示一次将大小为mblock✖️nblock大小的图像读入内存;
fun为邻域矩阵操作函数;indexed用于指明索引图像的可选参数;
block_type用于定义块的移动方式,'distinct'表示分离块操作,'sliding'表示滑动块操作。
e.g.使用colfilt实现快速滑动邻域操作
I=imread('tire.tif');
myf=@(I)max(I);
y=colfilt(I,[5 5],'sliding',myf);
subplot(121);imshow(I);title('原图')
subplot(122);imshow(y);title('邻域操作结果')
由于colfilt函数操作中,每个像素的邻域已排成列向量,所以这里的匿名函数为max(I)不同于nlfilt的max(I(:))。
(即在colfilt中,[m n]大小的邻域矩阵已排成列向量,fun编写时输入为列向量;而nlfilt中[m n]仍未二维矩阵形式,fun编写时其输入为二维矩阵。)
4.图像的块操作
图像的分离块操作是将图像划分为大小相同的矩形区域,不同图像块在图像中无重叠排列。
J=blockproc(I,blockSize,fun)
其中,I为原图像;
blockSize用于指定图像块的大小,图像块的大小由块结构定义,相应的数据矩阵放在.data域中。
e.g.将32✖️32的图像块中所有像素的灰度值设为该图像块的标准方差。
I=imread('moon.tif');
%fun=@(X)std2(X.data)*ones(size(X.data));
I2=blockproc(I,[32 32],@std);
subplot(121);
imshow('moon.tif');title('原图');
subplot(122);
imshow(I2,[]);title('块操作后图像');
function y=std(x)
y=std2(x.data)*ones(size(x.data));
end
四、图像的基本运算
(一)代数运算
- 图像的代数运算又称图像的算术运算,指多幅图像或多个波段图像间做相应像素的逐点加、减、乘、除等运算。
- 可以直接使用MATLAB运算符对图像矩阵进行操作,但需先将图像矩阵转换为与数值矩阵运算相一致的double类型,运算结束后还应转换回图像原数据类型。
1. 图像的叠加运算
Z=imadd(X,Y)
其中,X、Y为两个大小相同的图像矩阵。
e.g. 1 对MATLAB工具箱中rice.png和cameraman.tif图像进行叠加操作
X=imread('rice.png');
Y=imread('cameraman.tif');
subplot(131);
imshow(X);xlabel('(a)');
subplot(132)
imshow(Y);xlabel('(b)');
subplot(133)
Z=imadd(X,Y);
imshow(Z);xlabel('(c)');
另,利用imadd函数可以通过指定参数调整图像亮度。
e.g. 2 使用imadd函数调整图像亮度
I=imread('rice.png');
J=imadd(I,100); %为每个像素点都增加一个常数
subplot(121);
imshow(I);title('原图')
subplot(122);
imshow(J);title('提亮后')
2. 绝对差函数
对图像进行绝对差处理可以显示一张经过邻域处理的图像与原图的差别。
Z=imabsdiff(X,Y)
其中,X、Y为大小相同的两个图像矩阵;
Z为X、Y两个矩阵分别做减法并对每一个元素分别取相应差的绝对值的结果矩阵。
e.g.显示经过邻域处理的图与原图的差别
x=imread('cameraman.tif');
myf=@(x)mean(x);
y=uint8(colfilt(x,[7,7],'sliding',myf));
z=imabsdiff(x,y);
subplot(131);imshow(x);title('原图')
subplot(132);imshow(y);title('邻域处理')
subplot(133);imshow(z);title('绝对差值图像')
3.图像减法运算
图像减法运算通常用于检测图像变化,例如视频中两相邻帧之间的变化。
Z=imsubtract(X,Y)
其中,X、Y为大小相同的两个图像矩阵;
Z为X、Y两个矩阵各个元素做减法,当差小于0时,直接将结果设为0。
4.图像乘法运算
immultiply函数可将两幅图像相乘或将一幅图像与一个常数相乘。常用于掩膜操作(去掉图像中某些部分)或图像灰度增强。
Z=immultiply(X,Y)
5.除法运算
Z=imdivide(X,Y)
- 操作对象可以是两幅图像,也可以是一幅图像与一个常数;
- 运算结果是像素值的相对变化比率,而非绝对差异。(这是与图像相减的不同。)
e.g. 应用实例
imshow(z,[]);%显示动态范围小的图片
x=imread('rice.png');
myf=@(x)(min(min(x.data)))*uint8(ones(size(x.data)));
y=blockproc(x,[15 15],myf);
z=imdivide(x,y);
s=imdivide(x,2);
subplot(221)
imshow(x);title('原图')
subplot(222)
imshow(y);title('邻域处理后')
subplot(223)
imshow(z,[]) %z矩阵动态范围小
title('相除')
subplot(224)
imshow(s);title('与常数相除')
6.图像的线性组合
Z=imlincomb(K1,A1,K2,A2,...,Kn,An)
Z=imlincomb(K1,A1,K2,A2,...,Kn,An,K)
Z=imlincomb(...,output_class)
其中,Ki为双精度浮点标量;Ai为图像矩阵;K为常数项;output_class用来指定输出变量的数据类型。
(将Ai读入GPU后,可在GPU上运行。)
e.g.使用imlincomb实现图像的线性组合。
I=imread('rice.png');
J=imread('cameraman.tif');
K=imlincomb(1,I,3,J,'uint16');
subplot(131)
imshow(I);xlabel('a');
subplot(132)
imshow(J);xlabel('b');
subplot(133)
imshow(K,[]);xlabel('c');
%GPU实现
g_I=gpuArray(imread('rice.png'));
g_J=gpuArray(imread('cameraman.tif'));
K=imlincomb(1,I,3,J,'uint16');
7.图像求补运算
IM2=imcomplement(IM)
其中,IM可以为二值图像、灰度图像或RGB图像;输出的补图IM2与IM具有相同的图像大小和图像类型。
若为灰度图像,IM2各个元素的值为(255-IM各个元素的值)。
(二)几何变换
- 对图像进行几何变换时,像素坐标将发生改变,需进行插值操作,即利用已知位置的像素值生成未知位置的像素点的像素值。
- 常见的插值方法有:最近邻插值('nearest'),线性插值('linear'),三次插值('cublic'),双线性插值('bilinear'),双三次插值('bicubic')。
1.改变图像大小
保持图像形状的基础上对图像的大小进行改变。
B=imresize(A,scale,method)
B=imresize(A,outputSize,method)
[Y,newmap]=imresize(X,map,...)
其中,A为原图;scale是进行大小改变的倍数;method为可选项,指定插值方法,可选'nearest','bilinear','bicubic',默认为‘bicubic'
outputSize为输出图像的行和列的维数,通常以[numrows numcols]的方式给出;
X为索引图像,map为对应的映射表;Y为输出索引图像,newmap为Y的映射表。
2.图像剪切
I2=imcrop %未指定原图像,把当前图形窗口中的图像作为待剪切的图像
I2=imcrop(I)
X2=imcrop(X,map) %处理索引图像
I3=imcrop(h) %h为图像句柄
I2=imcrop(I,rect) %rect指定剪切区域的坐标及大小,分别为X,Y方向的最小值及矩形区域的宽与高
X2=imcrop(X,map,rect)
[I2,rect2]=imcrop(I,...) %输出剪切结果的同时还输出此剪切图像在原图中的位置
3.图像旋转
I2=imrotate(I,angle,method,bbox)
其中,angle为旋转角度;method为插值方法,可选'nearest','bilinear','bicubic',默认为'nearest';
bbox为旋转后图像边界选项,有'crop'和‘loose’(默认)两个选项,前者通过剪切图像,使旋转先后图像大小一致;后者允许I2包含I的全部信息。
e.g.两种图像边界对比。
4.图像的几何形变
I2=imwarp(I,tform,Interp)
其中,tform为变换矩阵;Interp为插值方式(默认为线性插值)。
e.g.利用坐标系的几何变换实现图像旋转
I=imread('google.png');
subplot(121)
imshow(I);title('原图')
tform=affine2d([cosd(30) sind(30) 0;-sind(30) cosd(30) 0;0 0 1]);
J=imwarp(I,tform);
%效果等价于
%J=imrotate(I,-30);
subplot(122)
imshow(J);title('顺时针旋转30度');