《數字影象處理》--岡薩雷斯(第十章)
影象分割
點、線和邊緣檢測
點檢測
點檢測在MATLAB中可以用函式imfilter來實現
點檢測方法
>> g = abs(imfilter(double(f), w)) >= T
其中f 是輸入影象,w是一個合適的點檢測掩模, g是結果影象
計算已濾波的影象,即abs(imfilter(double(f),w));
使用來自己濾波的影象的資料找到T的值
將已濾波的影象與T做比較
點檢測舉例
>> w = [-1 -1 -1;-1 8 -1; -1 -1 -1]; >> g = abs(imfilter(double(f), w)); >> T = max
方法二
>>g = imsubstract(ordfilt2(f, m*n, ones(m, n)),ordfilt2(f, 1, ones(m, n))); >> g = g >= T;
線檢測
線檢測中對指定方向的線更感興趣,這種情況下可以與該方向相關的掩模並對其輸出做出閾值處理。
檢測指定方向的線
>> w = [2 -1 -1 ; -1 2 -1; -1 -1 2]; >> g = imfilter(double(f), w); >> gtop = g(1
b 圖是對a 進行
−45. 檢測器處理後的節剛過,下面兩幅分別是它的左上角和右下角的放大圖,e 是b 的絕對值 f 是滿足條件 g>= T的所有點函式pixeldup
pixeldup(m,n)————%pixeldup函式是將影象擴大m*n倍,通過複製每個畫素點m*n次。
函式edge
邊緣檢測的基本意圖是使用如下兩個基本準則之一在影象中找到亮度快速變化的地方:
- 找到亮度的一階導數在幅度上比指定的閾值大的地方
- 找到亮度的二階導數有零交叉的地方
[g, t] = edge(f, 'method', parameters)
其中f 是輸入影象 , method 是下表中的方法
輸出中 g是一個邏輯陣列 ,其值如下決定:
在f 中檢測到邊緣的位置為1, 在其他位置為 0
t 引數是可選的,它給出edge使用的閾值,以確定那個梯度值足夠大到可以稱為邊緣點。
Sobel邊緣檢測器
[g, t] = edge(f, 'soble', T, dir)
- 其中f 是輸入影象,T 是一個指定的閾值 ,dir指定檢測邊緣的首選方向:‘horizontal’、’vertical’、 或’both’
- g 是在被檢測到邊緣的位置處為 1而在其他位置為0 的邏輯類影象
- 輸出引數t 是可選的,它是函式edge所用的閾值
- 若指定了T的值,則t = T ; 否則,若T 未被賦值 ,則函式edge會令t 等於它自動確定的一個閾值,然後用於邊緣檢測。
- 在輸出參量中要包括t的主要原因之一是為了得到一個閾值的初始值
- 若使用語法 g = edge(f) 或 [g, t] = edge(f) ,則函式edge會預設使用Sobel 檢測器
Prewitt邊緣檢測器
[g, t] = edge(f, 'prewitt',T, dir)
Prewitt 檢測器比Sobel 檢測器在計算上簡單一點,但是比較容易產生一些噪聲
Roberts邊緣檢測器
該檢測器是最古老的邊緣檢測器之一,它也是最簡單的一種邊緣檢測器;經常用於硬體的實現,因為既簡單又快速。
Laplacian of a Gaussian 檢測器
[g, t] = edge(f, 'log', T, sigma)
其中sigma是標準偏差,預設值為2
零交叉檢測器
該檢測器基於與LOG方法相同的概念,但卷積是使用指定的濾波函式H執行的
[g, t] = edge(f, 'zerocross',T, H)
Canny邊緣檢測器
該檢測器是使用函式edge的最有效邊緣檢測器
[g, t] = edge(f, 'canny', T, sigma)
- 其中T 是一個向量, T= [T1,T2]
- sigma 是平滑濾波器的標準偏差
- t 是一個二元向量,該向量包含該演算法用到的兩個閾值
>> [gv, t] = edge(f,'sobel','vertical'); >> gv = edge(f, 'sobel', 0.15, 'vertical'); >> gboth = edge(f, 'sobel', 0.15); >> w45 = [-2 -1 0;-1 0 1; 0 1 2] >> g45 = imfilter(double(f), w45, 'replicate'); >> T = 0.3 * max(abs(g45(:))); >> g45 = g45 >= T; >> f45= [0 1 2;-1 0 1;-2 -1 0] >> h45= imfilter(double(f), f45,'replicate'); >> T = 0.3 * max(abs(h45(:))); >> h45 = h45 >= T;
a . 原影象
b .使用帶有自動確定的閾值的一個垂直Sobel 掩模後, 函式edge導致的結果
c .使用指定閾值後的結果
d .使用指定閾值來決定垂直邊緣和水平邊緣的結果
e .使用函式imfilter 計算 45° 邊緣的結果
f . 使用函式imfilter 計算 -45° 邊緣的結果
Sobel、LOG和Canny 邊緣檢測器的比較
>> [g_sobel_default, ts] = edge(f, 'sobel'); >> [g_log_default, tlog] = edge(f, 'log'); >> [g_canny_default, tc] = edge(f, 'canny'); >> g_sobel_best = edge(f, 'sobel', 0.05); >> g_log_best = edge(f, 'log', 0.003, 2.25); >> g_canny_best = edge(f, 'canny', [0.04 0.10], 1.5);
左列: Sobel、LOG 和 Canny 邊緣檢測器使用預設選項產生的結果
右列:互動地顯示原影象的主要特徵,減少了無關的細節
綜合所有,Canny 邊緣檢測器產生的最好結果
使用Hough變換的線檢測
尋找並連結影象中線段的處理方式
函式sparse
給是一個矩陣,用函式sparse把他轉換成稀疏矩陣
S = sparse(A)
更常用的方法:
S = sparse(r, c, s, m, n)
r 和 c 分別是我們希望轉換為稀疏矩陣的矩陣中非零元素的行和列索引向量
S 是一個向量,它包含有相應於索引對(r, c) 的值
m n 是結果矩陣的行維數和列維數
- 函式full
給出任意一個稀疏矩陣,用full 函式來獲得完整的矩陣
A = full(S)
使用hough變換做峰值檢測
- 找到包含有最大值的hough變換單元並記下它的位置
- 把第一步中找到的最大值點的鄰域中的hough變換單元設為零
- 重複該步驟,直到找到需要的峰值數時為止,或者達到一個指定的閾值時為止
函式houghpeaks
解決上述所講的問題
使用hough變換做先檢測和連結
一旦hough變換中識別出了一組候選的峰被,則他們還要留待確定是否存在與這些峰值相關的線段以及它們的起始和結束為止。對每一個峰值來說,第一步是找到影象中影響到峰值的每一個非零值點的位置。因此,編寫了函式houghpixels
這裡使用該函式來找到的位置相關的畫素必須結合成線段,
函式houghlines採用下面的策略
使用hough變換做先檢測和連結
[H, theta, rho] = hough(f, 0.5); imshow(imadjust(mat2gray(H)),'XData',theta,'YData',rho,'InitialMagnification','fit'),axis on, axis normal xlabel('\theta'),ylabel('\rho') [r, c] = houghpeaks(H, 5); hold on plot(theta(c), rho(r), 'linestyle', 'none', 'marker', 's', 'color', 'w') lines = houghlines(f, theta,rho,r,c) figure, imshow(f),hold on In images.internal.initSize (line 71) In imshow (line 309) for k = 1:length(lines) xy = [lines(k).point1 ; lines(k).point2]; plot(xy(:, 2),xy(:,1),'LineWidth', 4, 'Color', [.6 .6 .6]); end
閾值處理
- 全域性閾值處理
T = 0.5*(double(min(f(:))) + double(max(f(:))));
done = false;
while~done
g = f >= T;
Tnext = 0.5*(mean(f(g))+mean(f(~g)));
done = abs(T - Tnext) < 0.5;
T = Tnext;
end
T2 = graythresh(f);
T2 * 255
bw = im2bw(f, T2);
區域性閾值處理
全域性閾值處理方法在背景照明不均勻時有可能失效,在這種情況下
- 針對照明問題做預處理以補償影象,然後再對預處理後的影象採用全域性閾值處理