邊緣檢測(cè)的理解可以結(jié)合前面的內(nèi)核,說(shuō)到內(nèi)核在圖像中的應(yīng)用還真是多,到現(xiàn)在為止學(xué)的對(duì)圖像的操作都是核的操作,下面還有更神奇的!
想把邊緣檢測(cè)出來(lái),從圖像像素的角度去想,那就是像素值差別很大,比如X1=20和X2=200,這兩個(gè)像素差值180,在圖像的顯示就非常明顯,這樣圖像的邊緣不就體現(xiàn)出來(lái)了?但是問(wèn)題來(lái)了,一幅圖像給你,如果一個(gè)像素一個(gè)像素對(duì)比,
邊緣檢測(cè)原理及步驟
在之前的博文中,作者從一維函數(shù)的躍變檢測(cè)開(kāi)始,循序漸進(jìn)的對(duì)二維圖像邊緣檢測(cè)的基本原理進(jìn)行了通俗化的描述。結(jié)論是:實(shí)現(xiàn)圖像的邊緣檢測(cè),就是要用離散化梯度逼近函數(shù)根據(jù)二維灰度矩陣梯度向量來(lái)尋找圖像灰度矩陣的灰度躍變位置,然后在圖像中將這些位置的點(diǎn)連起來(lái)就構(gòu)成了所謂的圖像邊緣(圖像邊緣在這里是一個(gè)統(tǒng)稱(chēng),包括了二維圖像上的邊緣、角點(diǎn)、紋理等基元圖)。
在實(shí)際情況中理想的灰度階躍及其線(xiàn)條邊緣圖像是很少見(jiàn)到的,同時(shí)大多數(shù)的傳感器件具有低頻濾波特性,這樣會(huì)使得階躍邊緣變?yōu)樾逼滦赃吘?,看起?lái)其中的強(qiáng)度變化不是瞬間的,而是跨越了一定的距離。這就使得在邊緣檢測(cè)中首先要進(jìn)行的工作是濾波。
1)濾波:邊緣檢測(cè)的算法主要是基于圖像強(qiáng)度的一階和二階導(dǎo)數(shù),但導(dǎo)數(shù)通常對(duì)噪聲很敏感,因此必須采用濾波器來(lái)改善與噪聲有關(guān)的邊緣檢測(cè)器的性能。常見(jiàn)的濾波方法主要有高斯濾波,即采用離散化的高斯函數(shù)產(chǎn)生一組歸一化的高斯核(具體見(jiàn)“高斯濾波原理及其編程離散化實(shí)現(xiàn)方法”一文),然后基于高斯核函數(shù)對(duì)圖像灰度矩陣的每一點(diǎn)進(jìn)行加權(quán)求和(具體程序?qū)崿F(xiàn)見(jiàn)下文)。
2)增強(qiáng):增強(qiáng)邊緣的基礎(chǔ)是確定圖像各點(diǎn)鄰域強(qiáng)度的變化值。增強(qiáng)算法可以將圖像灰度點(diǎn)鄰域強(qiáng)度值有顯著變化的點(diǎn)凸顯出來(lái)。在具體編程實(shí)現(xiàn)時(shí),可通過(guò)計(jì)算梯度幅值來(lái)確定。
3)檢測(cè):經(jīng)過(guò)增強(qiáng)的圖像,往往鄰域中有很多點(diǎn)的梯度值比較大,而在特定的應(yīng)用中,這些點(diǎn)并不是我們要找的邊緣點(diǎn),所以應(yīng)該采用某種方法來(lái)對(duì)這些點(diǎn)進(jìn)行取舍。實(shí)際工程中,常用的方法是通過(guò)閾值化方法來(lái)檢測(cè)。
邊緣檢測(cè)算法
1、Sobel邊緣檢測(cè)算法為例。
Sobel卷積核模板為:
偏導(dǎo)公式為:
2、Robert算子檢測(cè)邊緣:
x和y方向的算子
觀察上訴的算子,可以發(fā)現(xiàn)和我們剛開(kāi)始設(shè)想的一個(gè)一個(gè)比較差不多,比如本來(lái)比如X1=20和X2=40,這兩個(gè)像素差值20,但是20體現(xiàn)不出來(lái),所以用1,-1來(lái)增大這種差值,這其實(shí)解決了我們上訴遇到的第一點(diǎn)問(wèn)題了,但是后面的兩點(diǎn)依然沒(méi)有解決。
具體的例子我們可以用opencv自帶的API,addwight進(jìn)行試驗(yàn),把核改一下就行了。。。
Roberts算子檢測(cè)方法對(duì)具有陡峭的低噪聲的圖像處理效果較好,但是利用roberts算子提取邊緣的結(jié)果是邊緣比較粗,因此邊緣的定位不是很準(zhǔn)確。
X和Y方向
對(duì)X\Y兩個(gè)方向的梯度進(jìn)行合并
3、 Laplacian算子檢測(cè)邊緣:
拉普拉斯算子
拉普拉斯邊緣檢測(cè)是通過(guò)二階倒數(shù),從上面的一階倒數(shù)的理解就不難發(fā)現(xiàn)二階倒數(shù)是怎么進(jìn)行的了。
二階倒數(shù)比一階倒數(shù)的好處是在與受到周?chē)母蓴_小,其不具有方向性,操作容易,且對(duì)于很多方向的圖像處理好。
Laplacian算子法對(duì)噪聲比較敏感,所以很少用該算子檢測(cè)邊緣,而是用來(lái)判斷邊緣像素視為與圖像的明區(qū)還是暗區(qū)。
4、Scharr算子檢測(cè)邊緣:
這個(gè)濾波是Sobel的升級(jí)版,原理是一樣的,就是實(shí)現(xiàn)的近似代替不一樣,說(shuō)白了就事核改進(jìn)了。。。
5、.Canny算子檢測(cè)邊緣:
這是比較新的算法,運(yùn)用的也是最廣泛的。這個(gè)算法是在Sobel算法的基礎(chǔ)上改進(jìn)的,和Scharr不一樣!
Canny的步驟是:1.給一張圖片,先進(jìn)行濾波消除干擾,濾波前面博客已經(jīng)說(shuō)明。
2.計(jì)算梯度(進(jìn)行Sobel算子計(jì)算)。
3.非極大值抑制。
4.滯后閾值。
下面一屆具體介紹-》》》》
在opencv2.0的時(shí)候,直接調(diào)用API就幫你完成全部的工作,包含上面的四部。
現(xiàn)在opencv3.0濾波得自己操作,API完成了后三步操作。
這里在Sobel運(yùn)行之后的基礎(chǔ)上對(duì)圖像的邊緣進(jìn)行了優(yōu)化,哪些是優(yōu)秀的,哪些是差的,在這里會(huì)處理。
---細(xì)談邊緣檢測(cè)---
上面講到Canny的非極大值抑制和滯后閾值,其中這兩點(diǎn)是這個(gè)算法的核心!
非極大值抑制:
從字面上的理解就是從一群數(shù)據(jù)中找到真正的極大值,對(duì)于不是極大值的省略或者抑制顯示。
我們來(lái)想一下,Sobel算子計(jì)算的值就是邊緣的值嗎?1.算子是固定的,那就有很大的幾率會(huì)計(jì)算到不是邊緣的數(shù)據(jù)。
2.計(jì)算的結(jié)果不會(huì)省略不好的點(diǎn),也不會(huì)去加強(qiáng)好的點(diǎn),所以顯示就不明顯。
我們的目的就是改進(jìn)上面兩個(gè)點(diǎn),對(duì)于第一個(gè)點(diǎn),我們得比較那些計(jì)算的點(diǎn)進(jìn)行比較,把不好點(diǎn)舍去---》》》
以前在神經(jīng)網(wǎng)絡(luò)那篇博文里提到過(guò)“梯度”的概念,就是數(shù)據(jù)下降或者上升最快的方向,簡(jiǎn)單的說(shuō)就是求導(dǎo)切線(xiàn)的方向!
試想一下我們?cè)谶@個(gè)方向上找最大和最小值是最快最準(zhǔn)確的,這個(gè)具體原因神經(jīng)網(wǎng)絡(luò)那篇博文說(shuō)過(guò)了,可以去看看。
通過(guò)計(jì)算我們得到了θ的值在[-π/2,+π/2]區(qū)間,然后我們就可以比較在這個(gè)方向上的G和左右G1、G2的大小,當(dāng)G》G1、G2的時(shí)候,那就說(shuō)明這個(gè)G就是局部極大值,從而保留下來(lái):
例如:G0的θ是45度,那么在它的梯度方向來(lái)對(duì)比它是不是最大值,如果是的話(huà)那就說(shuō)明它是局部極大值-》判斷G0和(G3、G6)的大小關(guān)系!G0 = G0》G3&&G0》G6? G0:0;
上面的方法是第一代非極大值抑制算法,缺點(diǎn)是當(dāng) θ!=0、45、90、180 時(shí),那么旁邊的八個(gè)值就不在θ的梯度上,就沒(méi)辦法去做比較了,這時(shí)候出現(xiàn)第二代算法---》》》
插值法運(yùn)用在非最大值抑制算法中:
插值法:就是y=kx+b的插值公式,比如:X1和X2中間想插一點(diǎn)X,X = X1 + k(X2-X1)或者X= k*X1 +(1-k)X2 當(dāng)然插值法還有其它形式,不過(guò)兩點(diǎn)的線(xiàn)性插值比較簡(jiǎn)單的。這里使用第二者!
上面的圖形是當(dāng) |Gy|》|Gx| && Gx*Gy》0 的情況。前者保障靠近y軸,后者保證θ》0.
注釋?zhuān)涸谟械奈恼律峡吹暮臀艺f(shuō)的相反,按照數(shù)學(xué)知識(shí)應(yīng)該是這樣的啊,具體原因我也不知道了。
令 k = |Gy/Gx|
G23 = k*G2 + (1-k)*G3;
G67 = k*G6 + (1-k)*G7;
G0 = G0》G23 && G0》G67 ? G0:0;或者這里可以突出重點(diǎn)給定G0的值G0 = G0》G23 && G0》G67 ? 200:0;
opencv的源碼就是使用這種方法的,大家可以參考源碼:
1 void NonMaxSuppress(int*pMag,int* pGradX,int*pGradY,SIZE sz,LPBYTE pNSRst)
2 {
3 LONG x,y;
4 int nPos;
5 // the component of the gradient
6 int gx,gy;
7 // the temp varialbe
8 int g1,g2,g3,g4;
9 double weight;
10 double dTemp,dTemp1,dTemp2;
11 //設(shè)置圖像邊緣為不可能的分界點(diǎn)
12 for(x=0;x《sz.cx;x++)
13 {
14 pNSRst[x] = 0;
15 pNSRst[(sz.cy-1)*sz.cx+x] = 0;
16
17 }
18 for(y=0;y《sz.cy;y++)
19 {
20 pNSRst[y*sz.cx] = 0;
21 pNSRst[y*sz.cx + sz.cx-1] = 0;
22 }
23
24 for (y=1;y《sz.cy-1;y++)
25 {
26 for (x=1;x《sz.cx-1;x++)
27 {
28 nPos=y*sz.cx+x;
29 // if pMag[nPos]==0, then nPos is not the edge point
30 if (pMag[nPos]==0)
31 {
32 pNSRst[nPos]=0;
33 }
34 else
35 {
36 // the gradient of current point
37 dTemp=pMag[nPos];
38 // x,y 方向?qū)?shù)
39 gx=pGradX[nPos];
40 gy=pGradY[nPos];
41 //如果方向?qū)?shù)y分量比x分量大,說(shuō)明導(dǎo)數(shù)方向趨向于y分量
42 if (abs(gy)》abs(gx))
43 {
44 // calculate the factor of interplation
45 weight=fabs(gx)/fabs(gy);
46 g2 = pMag[nPos-sz.cx]; // 上一行
47 g4 = pMag[nPos+sz.cx]; // 下一行
48 //如果x,y兩個(gè)方向?qū)?shù)的符號(hào)相同
49 //C 為當(dāng)前像素,與g1-g3 的位置關(guān)系為:
50 //g1 g2
51 // C
52 // g4 g3
53 if(gx*gy》0)
54 {
55 g1 = pMag[nPos-sz.cx-1];
56 g3 = pMag[nPos+sz.cx+1];
57 }
58 //如果x,y兩個(gè)方向的方向?qū)?shù)方向相反
59 //C是當(dāng)前像素,與g1-g3的關(guān)系為:
60 // g2 g1
61 // C
62 // g3 g4
63 else
64 {
65 g1 = pMag[nPos-sz.cx+1];
66 g3 = pMag[nPos+sz.cx-1];
67 }
68 }
69 else
70 {
71 //插值比例
72 weight = fabs(gy)/fabs(gx);
73 g2 = pMag[nPos+1]; //后一列
74 g4 = pMag[nPos-1]; // 前一列
75 //如果x,y兩個(gè)方向的方向?qū)?shù)符號(hào)相同
76 //當(dāng)前像素C與 g1-g4的關(guān)系為
77 // g3
78 // g4 C g2
79 // g1
80 if(gx * gy 》 0)
81 {
82 g1 = pMag[nPos+sz.cx+1];
83 g3 = pMag[nPos-sz.cx-1];
84 }
85
86 //如果x,y兩個(gè)方向?qū)?shù)的方向相反
87 // C與g1-g4的關(guān)系為
88 // g1
89 // g4 C g2
90 // g3
91 else
92 {
93 g1 = pMag[nPos-sz.cx+1];
94 g3 = pMag[nPos+sz.cx-1];
95 }
96 }
97 //--線(xiàn)性插值等價(jià)于dTemp1 = g1 + weight*(g2-g1)--//
98 dTemp1 = weight*g1 + (1-weight)*g2;
99 dTemp2 = weight*g3 + (1-weight)*g4;
100 //當(dāng)前像素的梯度是局部的最大值
101 //該點(diǎn)可能是邊界點(diǎn)
102 if(dTemp》=dTemp1 && dTemp》=dTemp2)
103 {
104 pNSRst[nPos] = 128;
105 }
106 else
107 {
108 //不可能是邊界點(diǎn)
109 pNSRst[nPos] = 0;
110 }
111 }
112 }
113 }
114 }
在論文中海油一個(gè)改進(jìn)的插值,用二次插值代替一次插值,學(xué)過(guò)數(shù)值分析的都知道,一次插值在直線(xiàn)很好,但是在曲線(xiàn)不好,當(dāng)然二次插值也不能消除很多誤差,當(dāng)然海油牛頓插值等等。
這是當(dāng)Gx和Gy同號(hào)的情況,另一種情況自己想一下就行了。
二次插值相比較一次插值的優(yōu)點(diǎn)是:不用考慮哪個(gè)哪個(gè)具體的角度。其實(shí)很多人都提到了0、45、90、180的角度劃分,我這里沒(méi)有提到,原理是一樣的,我感覺(jué)直接做就好了,沒(méi)必要再去弄個(gè)中間變量過(guò)度一下,可能為了理解吧。
滯后閾值:
1. T1, T2為閾值,凡是高于T2的都保留,凡是小于T1都丟棄。
2.如果介于T1和T2之間的話(huà),判斷是否連接T2,如果沒(méi)連接T2那就刪除。
3.T1和T2比例最好1:2/1:3
這里說(shuō)明一下第二點(diǎn):
A.我們的目的是找到最大邊緣變化。
B.并且保證邊緣顯示效果很好。
對(duì)于A來(lái)說(shuō),我們非最大值抑制已經(jīng)找到部分最大值,現(xiàn)在用T2再進(jìn)行一遍,已經(jīng)很好的達(dá)到我們A目的了。
對(duì)于B來(lái)說(shuō),用T1去濾去可能不是最大值的點(diǎn),現(xiàn)在用第二點(diǎn)來(lái)加強(qiáng)顯示,在T2附近的保留,不在的都刪除(意思就是在最小值附近)。
看下面這個(gè)例子,T1=2,T2=9 用核3X3去找T2附近的值,那就表示只有6個(gè)值可以保留,其他值都將被刪除。
第一步:整個(gè)圖像去找T》T2和T《T1的值,刪除或者保留,并且標(biāo)記記錄。
第二步:在上一步記錄的最大值附近尋找存在的值,直接刪除或者保留。
評(píng)論
查看更多