天天看點

深入淺出各種邊緣檢測算子及其推導

作者丨Rustle@知乎

編輯丨極市平台

導    讀

本文系統的講解了邊緣檢測算法的相關概念,并輔以大量的圖與公式幫助大家深入了解各種邊緣檢測算子。 

寫在前面:

本文篇幅較長,用了大量圖與公式幫助大家深入了解各種邊緣檢測算子,希望大家能看完哈,測試編譯器為Matlab,作為入門計算機視覺(Computer vision)領域來說,Matlab是一款非常友好且簡單的工具,其中自帶各種先進的庫函數,實作起來非常快速,偏向于實驗性質的應用。好了話不多說,來和筆者一起看一下今天的主題-邊緣檢測。

一.前言

首先我們先來簡單了解一下什麼是數字圖像處理(Digital Image Processing),先看一下數字圖像主要的兩個應用領域:

1.改善圖示資訊以便人們解釋;

2.為存儲、傳輸和表示而對圖像資料進行處理,以便于機器自動了解

我們可以簡單了解為就将一幅原始圖像,使用計算機處理為更為我們所能了解或所需要的形式,如圖1-1所示,為基于邊緣檢測的免疫細胞圖像自動分割過程示意圖

深入淺出各種邊緣檢測算子及其推導

圖 1-1 克隆細胞圖像自動分割過程示意圖

讓我們再看一個例子,如圖1-2 ,為經典的車牌檢測算法,将原始圖像進行灰階圖轉換、邊緣檢測、形态學腐蝕膨脹等操作,得到車牌區域,随後将車牌區域進行切割(這個是筆者剛入門時做的小demo,還沒有用到深度學習模型,用的是knn,是以識别結果很差,各位看官會心一笑就好了哈)

深入淺出各種邊緣檢測算子及其推導

圖2 -2 車牌檢測

OK,在我們大緻了解了數字圖像處理之後,接下來介紹數字圖像處理一些基本的算法。

二.數字圖像處理基礎知識與算法

接下來先簡單介紹一下一些學習數字圖像處理的基礎知識與算法

1).數字圖像

數字圖像指的是現在的圖像都是以二維數字表示,每個像素的灰階值均由一個數字表示,範圍為0-255(2^8)

2).二值圖像、灰階圖像、彩色圖像

二值圖像(Binary Image): 圖像中每個像素的灰階值僅可取0或1,即不是取黑,就是取白,二值圖像可了解為黑白圖像

灰階圖像(Gray Scale Image): 圖像中每個像素可以由0-255的灰階值表示,具體表現為從全黑到全白中間有255個介于中間的灰色值可以取

彩色圖像(Color Image): 每幅圖像是由三幅灰階圖像組合而成,依次表示紅綠藍三通道的灰階值,即我們熟知的RGB,此時彩色圖像要視為三維的[height,width, 3]

下面用一張圖來感受一下灰階圖與彩色圖像之間的聯系與差别

深入淺出各種邊緣檢測算子及其推導

圖2 -1 RGB圖像的分解

其中還有一個很重要的公式,即彩色圖像轉為灰階圖的計算公式:

 G

Gray表示灰階圖像,RGB則表示彩色圖像的紅(red)、綠(green)、藍(blue)三通道灰階值

3).鄰接性、連通性

4鄰域: 假設有一點像素p坐标為(x, y),則它的4領域是(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)

D鄰域: 假設有一點像素p坐标為(x, y), 則它的D領域是(x + 1, y + 1), ( x + 1, y - 1), (x - 1, y + 1)

(x - 1, y - 1)

8鄰域: 将4領域與D領域的集合取并集,即表示為8鄰域

深入淺出各種邊緣檢測算子及其推導

圖2 - 2 4鄰域(左)、 D鄰域(中)、 8鄰域(右)

4連通: 對于在像素點p的4鄰域内的像素均與像素點p形成4連通

8連通: 對于在像素點p的8鄰域内的像素均與像素點p形成8連通

4).濾波

濾波的目的主要兩個:

1.通過濾波來提取圖像特征,簡化圖像所帶的資訊作為後續其它的圖像處理

2.為适應圖像處理的需求,通過濾波消除圖像數字化時所混入的噪聲

其中第一點就是邊緣檢測中所使用的基本思想,即簡化圖像資訊,使用邊緣線代表圖像所攜帶資訊

濾波可了解為濾波器(通常為3*3、5*5矩陣)在圖像上進行從上到下,從左到右的周遊,計算濾波器與對應像素的值并根據濾波目的進行數值計算傳回值到目前像素點,如圖 2-3所示,藍色塊表示濾波器,對圖像進行點積運算并指派到圖像

具體公式表示為:

(其中  表示目前像素點,  表示目前像素與濾波器對應值相乘的值,n為濾波器大小,舉例來說如若此濾波器值全為1,則此公式計算的是目前像素點的8連通像素點的平均值,是以濾波完後的圖像應表現為模糊的效果,模糊程度取決于濾波器的大小,濾波器大小(size)越大,模糊效果越明顯)

深入淺出各種邊緣檢測算子及其推導

三.邊緣檢測(Sobel、Prewitt、Roberts、Canny、Marr-Hildreth)

1.基本邊緣檢測算子

在介紹完濾波的知識後,學習基本邊緣檢測算法是一件很輕松的事情,因為邊緣檢測本質上就是一種濾波算法,差別在于濾波器的選擇,濾波的規則是完全一緻的

為了更好了解邊緣檢測算子,我們引入梯度(gradient) 這一概念,梯度是人工智能(artificial intelligence) 非常重要的一個概念,遍布機器學習、深度學習領域,學過微積分的同學應該知道一維函數的一階微分基本定義為:

深入淺出各種邊緣檢測算子及其推導

而我們剛才也提到了,圖像的濾波一般是基于灰階圖進行的,是以圖像此時是二維的,是以我們在看一下二維函數的微分,即偏微分方程:

深入淺出各種邊緣檢測算子及其推導

由上面的公式我們可以看到,圖像梯度即目前所在像素點對于X軸、Y軸的偏導數,是以梯度在圖像處理領域我們可以也了解為像素灰階值變化的速度,下面我們舉一個簡單的例子:

深入淺出各種邊緣檢測算子及其推導

圖 3-1

圖中我們可以看到,100與90之間相差的灰階值為10,即目前像素點在X軸方向上的梯度為10,而其它點均為90,則求導後發現梯度全為0,是以我們可以發現在數字圖像處理,因其像素性質的特殊性,微積分在圖像處理表現的形式為計算目前像素點沿偏微分方向的內插補點,是以實際的應用是不需要用到求導的,隻需進行簡單的加減運算

而另一個概念梯度的模則表示f(x, y),在其最大變化率方向上的機關距離所增加的量,即:

深入淺出各種邊緣檢測算子及其推導

在了解完梯度的概念之後呢,下面我們先介紹一下幾種基本邊緣檢測濾波器: Sobel、Prewitt、Roberts算子

深入淺出各種邊緣檢測算子及其推導

圖 3-2 Roberts算子

深入淺出各種邊緣檢測算子及其推導

圖 3-2 Prewitt算子

深入淺出各種邊緣檢測算子及其推導

圖 3-3 Sobel算子

我們以Sobel為例,其中  分别表示對于X軸、Y軸的邊緣檢測算子,從 

如現在有一個一維數組長度為10,值為:

[ 8, 6, 2, 4, 9, 1, 3, 5, 10, 6 ]

此時我們的一維邊緣檢測算子則表現為[ -1, 0, 1 ],現在我們把邊緣檢測算子放在數組上面進行點積(即對應點相乘之後的和),得到結果為:

[ 6, -6, -2, 7, -3, -6, 4, 7, 1, -10]

可以發現得到的值出現了負數,但我們之前的定義則聲明了像素灰階值定義域為0-255範圍内,是以這裡一般的操作為将負數截斷到0-255以内或者直接取絕對值,是以現在我們得到的是

[ 6, 6, 2, 7, 3, 6, 4, 7, 1, 10]

其中數字的大小則表示了目前像素點梯度的模大小,即灰階變化的速度有多大,值越大,我們一定程度上就可以确信目前點為我們所要找的邊緣點,通過一維的例子我們可以更好了解二維的邊緣檢測思想,即沿着X軸、Y軸進行兩次濾波操作,得到的結果進行平方求和加根号的操作得出目前像素點的圖像梯度,我們來通過一張圖了解一下這個過程:

深入淺出各種邊緣檢測算子及其推導

圖 3-4 原圖像、沿X軸梯度圖像、沿Y軸梯度圖像、梯度圖像的可視化

圖中(a)為原始的灰階圖像,(b)和(c)為使用圖3-3中Sobel算子的 、 兩種形式分别對原始圖像進行的濾波結果,即表示為分别沿X、Y軸的梯度圖,最後将兩個圖融合在一起則得到了我們所需的梯度圖像(d),在給大家一張圖來幫助了解Sobel算法

深入淺出各種邊緣檢測算子及其推導

現在我們已經大緻了解了邊緣檢測的基本思想了,看着圖 3-4(d)是不是覺得它挺好看的呢,但是好看不一定說明它就是我們所需要的邊緣圖,直接用基本的邊緣算子如Sobel求得的邊緣圖存在很多問題,如噪聲污染沒有被排除、邊緣線太過于粗寬等,是以我們接下來要介紹兩個先進的邊緣檢測算子:Canny算子和Marr-Hildreth算子

2.較為先進的邊緣檢測算子

1).Canny算子

Canny算子是澳洲計算機科學家約翰·坎尼(John F. Canny)于1986年開發出來的一個多級

邊緣檢測算法,其目标是找到一個最優的邊緣,其最優邊緣的定義是:

1.好的檢測 --算法能夠盡可能多地标示出圖像中的實際邊緣

2.好的定位 --辨別出的邊緣要與實際圖像中的實際邊緣盡可能接近

3.最小響應 --圖像中的邊緣隻能辨別一次,并且可能存在的圖像噪聲不應該辨別為邊緣

是以接下來我們來介紹一下目前流行的Canny算法的具體步驟

(1).高斯(Gaussian)濾波

高斯濾波目前是最為流行的去噪濾波算法,高斯與我們學的機率論中正态分布中正态一詞指的是同一個意思,其原理為根據待濾波的像素點及其鄰域點的灰階值按照高斯公式生成的參數規則進行權重平均,這樣可以有效濾去理想圖像中疊加的高頻噪聲(noise)

二維高斯公式為:

深入淺出各種邊緣檢測算子及其推導

常見的高斯濾波器有:

深入淺出各種邊緣檢測算子及其推導

圖 3-5 常見的高斯濾波器

其實高斯濾波器很像一個金字塔結構,其濾波器的值大小我們可以了解為權重(weight),值越大對應的像素點權重越大,分量也就越大,是以從高斯濾波器我們可以看出對應目前像素點,距離越遠權重越小,對灰階值的貢獻也就越小

讓我們舉個例子來了解一下高斯濾波,如圖3-5中左邊的高斯濾波器,其中心點4我們可以把它看成是'主人公',其周圍的點看成是'鄰居',噪聲我們把它看成是'壞人',現在我們假設這9個人裡面,有一個人是'壞人',我們也知道壞人是肯定會說自己是好人的,但要是我們有投票機制決定一個人是否為'壞人'呢,其中權重(weight)則對應每個人說話的分量,投票機制就為我們所說的權重平均政策,現在我們可以很直覺地發現,其實高斯濾波就是一個會考慮其周圍像素點的濾波器,即使目前點位為噪聲點,高斯濾波器也會通過周圍點的灰階值來制約噪聲的影響,生成高斯濾波器與濾波的代碼如下:

​​sigma=1; %高斯标準差

% 根據高斯标準差計算濾波器長度
filterExtent = ceil(4*sigma);
x = -filterExtent:filterExtent;

% 生成一維高斯核
c = 1/(sqrt(2*pi)*sigma);
gaussKernel = c * exp(-(x.^2)/(2*sigma^2));

% 标準化
gaussKernel = gaussKernel/sum(gaussKernel);

% 對圖像進行高斯濾波平滑
aSmooth=imfilter(a,gaussKernel,'conv','replicate'); % 沿着X軸卷積
aSmooth=imfilter(aSmooth,gaussKernel','conv','replicate'); % 沿着Y軸卷積      

(其中gaussKernel'表示對gaussKernel進行轉置)

(2).計算梯度圖像與角度圖像

計算梯度圖像我們剛才基本也有了解了一下,無非就是用各種邊緣檢測算子進行梯度的檢測,但Canny中使用的梯度檢測算子有點進階,是使用高斯濾波器進行梯度計算得到的濾波器,得到的結果也類似于Sobel算子,即距離中心點越近的像素點權重越大,代碼如下:

​​% 數值梯度函數(Gaussian核的生成1-D導數)
derivGaussKernel = gradient(gaussKernel);

% 标準化
negVals = derivGaussKernel < 0;
posVals = derivGaussKernel > 0;
derivGaussKernel(posVals) = derivGaussKernel(posVals)/sum(derivGaussKernel(posVals));
derivGaussKernel(negVals) = derivGaussKernel(negVals)/abs(sum(derivGaussKernel(negVals)));

% 計算梯度
dx = imfilter(aSmooth, derivGaussKernel, 'conv','replicate');
dy = imfilter(aSmooth, derivGaussKernel', 'conv','replicate');


mag = hypot(dx,dy); 
magmax = max(mag(:));
if magmax>0
magGrad = mag / magmax; % 梯度标準化
end
​      

角度圖像的計算則較為簡單,其作用為非極大值抑制的方向提供指導,公式如下:

深入淺出各種邊緣檢測算子及其推導

(3).對梯度圖像進行非極大值抑制

從上一步得到的梯度圖像存在邊緣粗寬、弱邊緣幹擾等衆多問題,現在我們可以使用非極大值抑制來尋找像素點局部最大值,将非極大值所對應的灰階值置0,這樣可以剔除一大部分非邊緣的像素點

如圖 3-6所示,C表示為目前非極大值抑制的點,g1-4為它的8連通鄰域點,圖中藍色線段表示上一步計算得到的角度圖像C點的值,即梯度方向,第一步先判斷C灰階值在8值鄰域内是否最大,如是則繼續檢查圖中梯度方向交點dTmp1,dTmp2值是否大于C,如C點大于dTmp1,dTmp2點的灰階值,則認定C點為極大值點,置為1,是以最後生成的圖像應為一副二值圖像,邊緣理想狀态下都為單像素邊緣

深入淺出各種邊緣檢測算子及其推導

圖 3-6 非極大值抑制

(其中需要注意的是梯度方向交點并不一定落在8領域所在8個點的位置,是以dTmp1和dTmp2實際應用中是使用相鄰兩個點的雙線性插值所形成的灰階值)

最後在上一張圖幫助大家了解,如圖3-7所示,其中梯度方向均為垂直向上,經過非極大值抑制後取梯度方向上最大值為邊緣點,形成細且準确的單像素邊緣

深入淺出各種邊緣檢測算子及其推導

圖 3-7

(4).使用雙門檻值進行邊緣連接配接

經過以上三步之後得到的邊緣品質已經很高了,但還是存在很多僞邊緣,是以Canny算法中所采用的算法為雙門檻值法,具體思路為選取兩個門檻值,将小于低門檻值的點認為是假邊緣置0,将大于高門檻值的點認為是強邊緣置1,介于中間的像素點需進行進一步的檢查

根據高門檻值圖像中把邊緣連結成輪廓,當到達輪廓的端點時,該算法會在斷點的8鄰域點中尋找滿足低門檻值的點,再根據此點收集新的邊緣,直到整個圖像閉合,具體代碼為:

​​function nedge=connect1(nedge,y,x,low,high,magGrad) %種子定位後的連通分析
neighbour=[-1 -1;-1 0;-1 1;0 -1;0 1;1 -1;1 0;1 1]; %八連通搜尋
[m n]=size(nedge);

for k=1:8
yy=fix(y+neighbour(k,1));
xx=fix(x+neighbour(k,2));


if yy>=1 &&yy<=m xx="">=1 && xx<=n 
if magGrad(yy,xx)>=low & nedge(yy,xx)~=255 & magGrad(yy,xx)<high 
nedge(yy,xx)=255;
%disp('check check');
%nedge=connect1(nedge,yy,xx,low,high,magGrad);
end
end
end
end      

但由于尋找弱邊緣點的計算代價過大,因為使用的是遞歸思維,且所找尋到的弱邊緣點為數不多,是以實際應用中常常舍去這一步驟,取而代之的是基于形态學的邊緣細化操作,具體思想我們以後還會提到,具體代碼為:

​​H = bwmorph(H, 'thin', 1);      

至此,我們已經深度了解了Canny算法的思想與實作手段,實際應用中Canny一般是邊緣檢測的首選項,其算法思想也非常值得我們學習,接下來我們在簡單介紹基于二階導數法的Marr-Hildreth邊緣檢測算子

1).Marr-Hildreth算子

在學習Marr-Hildreth算子之前我們先來了解一下為什麼要用二階導數法

如圖 3-8所示,左邊表示的是一副灰階圖像,從左到右從黑色(0)慢慢變為白色(255),現在我們來看它的水準灰階剖面,灰階值從小到大平穩上升,其一階導數表示為在上升區域為不變的值,其中得到的資訊是圖像灰階值是平穩過渡的,即梯度值相等,接下來在将其求二次導數,得到的圖像為在開始過渡的起點為正數,其值為一階導數在此點的梯度值,結束點也和起點一樣,現在重點來了,我們将這兩點連起來得到一個與X軸的交叉點,這一點就是我們所認為的邊緣點,這就是二階導數應用在邊緣檢測領域的奇妙之處(第一次接觸的時候覺得巨神奇)

在看一下marr和hildreth的證明結論:

1.灰階變化與圖像尺寸無關,是以他們的檢測要求使用不同尺寸的算子

2.灰階的突然變換會在一階導數中引起波峰或波谷,在二階導數中等效引起零交叉

深入淺出各種邊緣檢測算子及其推導

圖 3-8 零交叉原理

學習了基于二階導數的馬爾雜湊演算法原理之後,我們來看一下它的思路:

(1).高斯濾波

對你沒看錯,還是高斯濾波,基本所有邊緣檢測算法前面都會加一個高斯濾波來去除高頻噪聲,是以這裡不在多說了,大家往前回顧一下就好了

(2).計算拉普拉斯(Laplacian)二階導

Marr-Hildreth證明,最滿足圖像處理需求的算子是濾波器拉普拉斯高斯(Log)算子,具體原理我們不在多做闡述,這裡我們來看一下它的公式:

深入淺出各種邊緣檢測算子及其推導

由其生成的拉普拉斯濾波器也被稱為墨西哥草帽算子,因為其中間一般為較大的正數,8鄰域連通點為較小的負數值,常用的濾波器如圖 3-9所示:

深入淺出各種邊緣檢測算子及其推導

圖 3-9 拉普拉斯濾波器

之後就是使用拉普拉斯濾波器進行圖像的濾波操作,得到待計算圖像

(3).計算零交叉(Zero crossing)

零交叉的實作較為簡單,由于零交叉點意味着至少兩個相鄰的像素點的像素值異号,一共有四種需要檢測的情況:左右,上下,兩個對角,其中如果濾波後的圖像g(x, y)的任意像素p處的四種情況其中一組的內插補點的絕對值超過了設定的門檻值,則我們可以稱p為一個零交叉像素,示例如下:

深入淺出各種邊緣檢測算子及其推導

圖 3-10

此為Marr-Hildreth其中一小部分,檢測[ - +]這一情況是否滿足,其中thresh為提到的門檻值

到這裡我們就學習了兩種最為流行且經典的先進邊緣檢測算法與思想,接下來說的是一些經驗與算法的選擇參考

四.補充

1.濾波器的大小應該是奇數,這樣才有一個中心點可進行指派操作,常見的濾波器或卷積核(Conv kernel)有3*3、5*5等,是以也有了半徑的概念,例如5*5的卷積核的半徑為2

2.濾波器中所有元素之和應為0,這一限制條件是保證濾波前後圖像總體灰階值不變

3.Roberts算子、Sobel算子、Prewitt算子運算速率高,對噪聲也有一定抑制作用,但檢測出的邊緣品質不高,如邊緣較粗、定位不準、間斷點多

4.Canny算子不容易受噪聲幹擾,得到的邊緣精細且準确,缺點就是運算代價較高,運作于實時圖像處理較困難,适用于高精度要求的應用

5.Marr-Hildreth算子邊緣檢測效果相對較優,但對于噪聲比較敏感(因其二階運算的性質)

五.總結

總體來說,邊緣檢測算法應用面非常廣,遍及很多領域,是入門計算機視覺(Computer vision) 學習一個非常好的途徑,其中很多思想和原理的東西至今對筆者也有印象,是以筆者第一篇文章就想着從這個開始寫,還有就是文章有些地方是筆者自己的一些了解和見解,如有錯誤的地方希望大家幫忙指出來哈,以後還會繼續寫一些關于機器學習(Machine learning)、深度學習(Deep learning)、人臉識别(Face recognition) 的文章,最後附上Canny邊緣檢測算法完整的Matlab代碼實作(當然也可以調用edge函數,但是學習的話最好自己從底層實作一遍嘛是吧)

​​I=imread('cameraman.tif');
%I=rgb2gray(I);
figure(1);subplot(121);imshow(I);xlabel('原圖像');
[m n]=size(I);
a=double(I);
sigma=1; %高斯标準差
%highThresh=0.0625; %上門檻值
%lowThresh=0.0250 ; %下門檻值


%=======================高斯濾波&梯度計算=======================

%%%%%%%%%%%%%%%%%%%%%%%%%Old%%%%%%%%%%%%%%%%%%%%%%%%%%%
%pw = 1:30; 
%ssq = sigma^2;
%width = find(exp(-(pw.*pw)/(2*ssq))>0.0001,1,'last');
%if isempty(width)
% width = 1; 
%end

%t = (-width:width);
%gauss = exp(-(t.*t)/(2*ssq))/(2*pi*ssq); % 一維高斯濾波器


%[x,y]=meshgrid(-width:width,-width:width);
%gauss2=-x.*exp(-(x.*x+y.*y)/(2*ssq))/(pi*ssq); %二維高斯濾波器

%對圖像進行高斯濾波平滑
%aSmooth=imfilter(a,gauss,'conv','replicate'); % 沿着X軸卷積
%aSmooth=imfilter(aSmooth,gauss','conv','replicate'); % 沿着Y軸卷積

%使用二維高斯對圖像進行卷積
%dx = imfilter(aSmooth, gauss2, 'conv','replicate');
%dy = imfilter(aSmooth, gauss2', 'conv','replicate');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


% 根據高斯标準差計算濾波器長度
filterExtent = ceil(4*sigma);
x = -filterExtent:filterExtent;

% 生成一維高斯核
c = 1/(sqrt(2*pi)*sigma);
gaussKernel = c * exp(-(x.^2)/(2*sigma^2));

% 标準化
gaussKernel = gaussKernel/sum(gaussKernel);

% 數值梯度函數(Gaussian核的生成1-D導數)
derivGaussKernel = gradient(gaussKernel);

% 标準化
negVals = derivGaussKernel < 0;
posVals = derivGaussKernel > 0;
derivGaussKernel(posVals) = derivGaussKernel(posVals)/sum(derivGaussKernel(posVals));
derivGaussKernel(negVals) = derivGaussKernel(negVals)/abs(sum(derivGaussKernel(negVals)));


% 對圖像進行高斯濾波平滑
aSmooth=imfilter(a,gaussKernel,'conv','replicate'); % 沿着X軸卷積
aSmooth=imfilter(aSmooth,gaussKernel','conv','replicate'); % 沿着Y軸卷積
%hv=fspecial('sobel');

% 計算梯度
dx = imfilter(aSmooth, derivGaussKernel, 'conv','replicate');
dy = imfilter(aSmooth, derivGaussKernel', 'conv','replicate');


mag = hypot(dx,dy); 
magmax = max(mag(:));
if magmax>0
magGrad = mag / magmax; % 梯度标準化
end

% 門檻值選擇
%PercentOfPixelsNotEdges = 0.7; 
counts=imhist(magGrad, 64);
highThresh = find(cumsum(counts) > 0.7*m*n, 1 ,'first' ) / 64;
lowThresh = 0.4*highThresh;

%figure(8);imshow(magGrad);
%%========================高斯濾波========================================
%w=fspecial('gaussian',[5 5]);
%img=imfilter(img,w,'replicate');
%figure;
%imshow(uint8(img))

%%===================sobel邊緣檢測=======================================
%hv=fspecial('sobel');
%dx=imfilter(img,hv,'replicate'); %求橫邊緣
%hh=hv';
%dy=imfilter(img,hh,'replicate'); %求豎邊緣
%img=sqrt(dx.^2+dy.^2); 


% magmax = max(img(:));% (門檻值選擇歸一化)
% if magmax > 0
% magGrad = img / magmax;
% end
%figure;
%imshow(uint8(img));

I = thinAndThreshold(dx, dy, magGrad, lowThresh, highThresh);


%disp(lowThresh);
subplot(122);imshow(I);xlabel('canny邊緣檢測');
disp("高門檻值TL: "+highThresh);
disp("低門檻值TH: "+lowThresh);


%========================非極大值抑制和邊緣連接配接=======================================
function H = thinAndThreshold(dx, dy, magGrad, lowThresh, highThresh)

E = cannyFindLocalMaxima(dx,dy,magGrad,lowThresh); %非極大值抑制

if ~isempty(E)
[rstrong,cstrong] = find(magGrad>highThresh & E);

if ~isempty(rstrong) 
H = bwselect(E, cstrong, rstrong, 8); % 標明強邊緣8連通目标
% figure(2);imshow(H);

% set(0,'RecursionLimit',1000); %弱邊緣連通(無太大作用,且運算時間過長)
% [xstrong ystrong]=find(magGrad>highThresh & E);
% for i=1:numel(xstrong);
% H = connect1(H,xstrong(i),ystrong(i),lowThresh,highThresh,magGrad);
% end
% figure(3);imshow(H);

H = bwmorph(H, 'thin', 1); % 邊緣細化
else
H = false(size(E));
end
else
H = false(size(E));
end
end

%========================弱邊緣連接配接=======================================

function nedge=connect1(nedge,y,x,low,high,magGrad) %種子定位後的連通分析
neighbour=[-1 -1;-1 0;-1 1;0 -1;0 1;1 -1;1 0;1 1]; %八連通搜尋
[m n]=size(nedge);

for k=1:8
yy=fix(y+neighbour(k,1));
xx=fix(x+neighbour(k,2));


if yy>=1 &&yy<=m xx="">=1 && xx<=n 
if magGrad(yy,xx)>=low & nedge(yy,xx)~=255 & magGrad(yy,xx)<high 
nedge(yy,xx)=255;
%disp('check check');
%nedge=connect1(nedge,yy,xx,low,high,magGrad);
end
end
end
end      

效果如圖所示:

深入淺出各種邊緣檢測算子及其推導

本文亮點總結

1.邊緣檢測算法,其目标是找到一個最優的邊緣,其最優邊緣的定義是:

1.好的檢測 --算法能夠盡可能多地标示出圖像中的實際邊緣

2.好的定位 --辨別出的邊緣要與實際圖像中的實際邊緣盡可能接近

3.最小響應 --圖像中的邊緣隻能辨別一次,并且可能存在的圖像噪聲不應該辨別為邊緣

2.高斯濾波目前是最為流行的去噪濾波算法,高斯與我們學的機率論中正态分布中正态一詞指的是同一個意思,其原理為根據待濾波的像素點及其鄰域點的灰階值按照高斯公式生成的參數規則進行權重平均,這樣可以有效濾去理想圖像中疊加的高頻噪聲(noise)

—THE END—

繼續閱讀