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è)置圖像邊緣為不可能的分界點
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分量大,說明導(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兩個方向?qū)?shù)的符號相同
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兩個方向的方向?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兩個方向的方向?qū)?shù)符號相同
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兩個方向?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 //--線性插值等價于dTemp1 = g1 + weight*(g2-g1)--//
98 dTemp1 = weight*g1 + (1-weight)*g2;
99 dTemp2 = weight*g3 + (1-weight)*g4;
100 //當(dāng)前像素的梯度是局部的最大值
101 //該點可能是邊界點
102 if(dTemp》=dTemp1 && dTemp》=dTemp2)
103 {
104 pNSRst[nPos] = 128;
105 }
106 else
107 {
108 //不可能是邊界點
109 pNSRst[nPos] = 0;
110 }
111 }
112 }
113 }
114 }
在論文中海油一個改進的插值,用二次插值代替一次插值,學(xué)過數(shù)值分析的都知道,一次插值在直線很好,但是在曲線不好,當(dāng)然二次插值也不能消除很多誤差,當(dāng)然海油牛頓插值等等。
這是當(dāng)Gx和Gy同號的情況,另一種情況自己想一下就行了。
二次插值相比較一次插值的優(yōu)點是:不用考慮哪個哪個具體的角度。其實很多人都提到了0、45、90、180的角度劃分,我這里沒有提到,原理是一樣的,我感覺直接做就好了,沒必要再去弄個中間變量過度一下,可能為了理解吧。
滯后閾值:
1. T1, T2為閾值,凡是高于T2的都保留,凡是小于T1都丟棄。
2.如果介于T1和T2之間的話,判斷是否連接T2,如果沒連接T2那就刪除。
3.T1和T2比例最好1:2/1:3
這里說明一下第二點:
A.我們的目的是找到最大邊緣變化。
B.并且保證邊緣顯示效果很好。
對于A來說,我們非最大值抑制已經(jīng)找到部分最大值,現(xiàn)在用T2再進行一遍,已經(jīng)很好的達到我們A目的了。
對于B來說,用T1去濾去可能不是最大值的點,現(xiàn)在用第二點來加強顯示,在T2附近的保留,不在的都刪除(意思就是在最小值附近)。
看下面這個例子,T1=2,T2=9 用核3X3去找T2附近的值,那就表示只有6個值可以保留,其他值都將被刪除。
第一步:整個圖像去找T》T2和T《T1的值,刪除或者保留,并且標(biāo)記記錄。
第二步:在上一步記錄的最大值附近尋找存在的值,直接刪除或者保留。
評論
查看更多