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 //设置图像边缘为不可能的分界点
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 方向导数
39 gx=pGradX[nPos];
40 gy=pGradY[nPos];
41 //如果方向导数y分量比x分量大,说明导数方向趋向于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两个方向导数的符号相同
49 //C 为当前像素,与g1-g3 的位置关系为:
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两个方向的方向导数方向相反
59 //C是当前像素,与g1-g3的关系为:
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两个方向的方向导数符号相同
76 //当前像素C与 g1-g4的关系为
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两个方向导数的方向相反
87 // C与g1-g4的关系为
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 //当前像素的梯度是局部的最大值
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 }
在论文中海油一个改进的插值,用二次插值代替一次插值,学过数值分析的都知道,一次插值在直线很好,但是在曲线不好,当然二次插值也不能消除很多误差,当然海油牛顿插值等等。
这是当Gx和Gy同号的情况,另一种情况自己想一下就行了。
二次插值相比较一次插值的优点是:不用考虑哪个哪个具体的角度。其实很多人都提到了0、45、90、180的角度划分,我这里没有提到,原理是一样的,我感觉直接做就好了,没必要再去弄个中间变量过度一下,可能为了理解吧。
滞后阈值:
1. T1, T2为阈值,凡是高于T2的都保留,凡是小于T1都丢弃。
2.如果介于T1和T2之间的话,判断是否连接T2,如果没连接T2那就删除。
3.T1和T2比例最好1:2/1:3
这里说明一下第二点:
A.我们的目的是找到最大边缘变化。
B.并且保证边缘显示效果很好。
对于A来说,我们非最大值抑制已经找到部分最大值,现在用T2再进行一遍,已经很好的达到我们A目的了。
对于B来说,用T1去滤去可能不是最大值的点,现在用第二点来加强显示,在T2附近的保留,不在的都删除(意思就是在最小值附近)。
看下面这个例子,T1=2,T2=9 用核3X3去找T2附近的值,那就表示只有6个值可以保留,其他值都将被删除。
第一步:整个图像去找T》T2和T《T1的值,删除或者保留,并且标记记录。
第二步:在上一步记录的最大值附近寻找存在的值,直接删除或者保留。
评论
查看更多