MATLAB中的函數句柄及其應用


1.函數句柄的創建

函數句柄(function handle)是MATLAB中的一類特殊的數據結構,它的地位類似於其它計算機語言里的函數對象(Javascript,Python),函數指針(C++),或者函數引用(Perl)。作用是將一個函數封裝成一個變量,使其能夠像其它變量一樣在程序的不同部分傳遞。

MATLAB中的函數句柄在調用時和普通函數沒有任何區別,下面展示幾種創建函數句柄的方式,最后通過函數句柄調用sin(pi)。

% 函數句柄的創建% 方式1 : 直接加@
% 語法:@函數名
fun1 = @sin;

% 方式2 : str2func函數
% 語法:str2fun('函數名')
fun2 = str2func('cos');

% 方式3 : 匿名函數
% 語法:@(參數列表)單行表達式
fun3 = @(x, y)x.^2 + y.^2

% 函數句柄的調用fun1(pi);

2.將函數句柄作為函數參數

函數對象的經典應用情境之一就是排序(Sorting),即為一列未知類型的數組提供自定義的排序規則。下面我將實現一個函數super_sort,接收兩個參數,第一個參數為待排序的數組,第二個參數是一個對原始數據的變換函數。super_sort能夠對原始數據按照變換后的結果進行排序,並返回排好序的原始數據。

%文件名:super_sort.m

function sorted = super_sort(arr, fh)
transformed = fh(arr);% 對原始數組進行變換
[~, index] = sort(transformed); % 獲得排序后的原數組位置索引
sorted = arr(index); % 返回排序后的原數組
end

測試腳本:

arr = round(randn(8, 1) * 10);
super_sort(arr, @abs) % 將arr按照其絕對值大小排序
super_sort(arr, @sin) % 將arr按照sin(x)的結果排序

注意,與Perl或Python不同,這里提供的函數句柄並不用於元素間的比較,而是用於將數組內各個元素進行映射成待比較的值。

3.利用函數句柄進行畫圖

借助函數句柄,可以方便地畫出各類函數的圖像,這類繪圖函數往往以ez開頭,下面我將演示ezplot, ezsurf兩個函數。

% ezplot畫sin函數在[0, 2 * pi]內的曲線

ezplot(@sin, [0, 2 * pi]);

% ezplot利用x和y上的參數方程畫心形線

xfun = @(t)3*(2*cos(t)-cos(2*t));
yfun = @(t)3*(2*sin(t)-sin(2*t));
ezplot(xfun, yfun);

% ezsurf畫二次曲面

fun3 = @(x,y)x.^2+y.^2;
ezsurf(fun3, [-2, 2, -2, 2]);

4.利用函數句柄進行圖像的濾波

MATLAB提供了colfilt這一函數,該函數能將圖像分成獨立的子塊(局部處理),或者相互交疊的窗口(可實現二維卷積及中值濾波),並利用傳入的函數句柄對各個子塊進行處理。

函數原型為B = colfilt(A,[M N],BLOCK_TYPE,FUN),其中B是輸出圖像,A是輸入圖像,[M N]是圖像塊或窗口的長寬,BLOCK_TYPE參數決定是進行塊處理還是窗口滑動處理,FUN就是處理用的函數句柄,它只接收一個矩陣參數,這個矩陣的每一列都是拉長為列向量的子圖像,FUN一次可能要處理多個子圖像。

下面將實現利用colfilt對圖像進行5*5中值濾波,以及局部閾值化。

% 在BLOCK_TYPE=sliding時進行滑動窗口處理
% f的返回值必須是一個元素個數與輸入矩陣的列數相等的行向量
% 行向量中每個元素都將作為對應窗口中心元素的輸出值

I = imread('tire.tif');
f = @(mat)median(im2double(mat));
I2 = colfilt(I, [5 5], 'sliding', f)

% 在BLOCK_TYPE=distinct時進行子圖像塊的處理% f的返回值必須是和輸入矩陣尺寸相同的矩陣
% 返回值中的每一列都將被復原成輸出圖像中的對應子塊% 這里偷了一個懶, 直接將MATLAB自動分配的多個連續子圖像
% 作為一個閾值化區域, 其實各個區域雖然連續,但大小是不相等的

thre = @(mat)im2bw(mat, graythresh(mat));

I3 = colfilt(I, [50 50], 'distinct', thre);
imshow([im2double(I) I2 I3]);

輸出圖像如下:

5.組合匿名函數實現更復雜的函數句柄

由於只能包含單行的表達式,匿名函數只能完成簡單的運算。但是如果把多個匿名函數結合,就能實現更強大的功能。

當函數sort作用於矩陣時,將各列分別排序,如果要實現提取排序后第K小的行,使用單個匿名函會遇到麻煩。因為

@(mat)sort(mat)(K, :)

這樣的語法在MATLAB中是錯誤的,通過組合匿名函數,我們就能解決這一問題。

extract_row = @(mat, k)mat(k, :);
order = @(mat, k)extract_row(sort(mat), k);

6.總結

函數句柄是函數的數據抽象,能夠作為其它函數的參數。善用它,將讓程序更加優雅並具有更強的靈活性。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM