4 非极大值抑制是进行边缘检测的一个重要步骤, 通俗意义上是指寻找像素点局部最大值。 沿着梯度方向,比较它前面和后面的梯度值进行了 。见下图。

上图中左右图:g1、g2、g3、g4都代表像素点,很明显它们是c的八领域中的4个,左图中c点是我们需要判断的点,蓝色的直线是它的梯度方向,也就是说c要是局部极大值,它的梯度幅值M需要大于直线与g1g2和g2g3的交点,dtmp1和dtmp2处的梯度幅值。但是dtmp1和dtmp2不是整像素,而是亚像素,也就是坐标是浮点的,那怎么求它们的梯度幅值呢?线性插值,例如dtmp1在g1、g2之间,g1、g2的幅值都知道,我们只要知道dtmp1在g1、g2之间的比例,就能得到它的梯度幅值,而比例是可以靠夹角计算出来的,夹角又是梯度的方向。
写个线性插值的公式:设g1的幅值M(g1),g2的幅值M(g2),则dtmp1可以很得到:
M(dtmp1)=w*M(g2)+(1-w)*M(g1)
其中w=distance(dtmp1,g2)/distance(g1,g2)
distance(g1,g2) 表示两点之间的距离。实际上w是一个比例系数,这个比例系数可以通过梯度方向(幅角的正切和余切)得到。
右边图中的4个直线就是4个不同的情况,情况不同,g1、g2、g3、g4代表c的八领域中的4个坐标会有所差异,但是线性插值的原理都是一致的。
代码如下:
1 ////////第四步:非极大值抑制
2 //注意事项 权重的选取,也就是离得近权重大
3 /////////////////////////////////////////////////////////////////
4 IplImage * N;//非极大值抑制结果
5 N=cvCreateImage(cvGetSize(ColorImage),ColorImage->depth,1);
6 IplImage * OpencvCannyimg;//非极大值抑制结果
7 OpencvCannyimg=cvCreateImage(cvGetSize(ColorImage),ColorImage->depth,1);
8 int g1=0, g2=0, g3=0, g4=0; //用于进行插值,得到亚像素点坐标值
9 double dTmp1=0.0, dTmp2=0.0; //保存两个亚像素点插值得到的灰度数据
10 double dWeight=0.0; //插值的权重
11
12 for(int i=1;i<nWidth-1;i++)
13 {
14 for(int j=1;j<nHeight-1;j++)
15 {
16 //如果当前点梯度为0,该点就不是边缘点
17 if (M[i+j*nWidth]==0)
18 {
19 N->imageData[i+j*nwidthstep]=0;
20 }else
21 {
22 ////////首先判断属于那种情况,然后根据情况插值///////
23 ////////////////////第一种情况///////////////////////
24 ///////// g1 g2 /////////////
25 ///////// C /////////////
26 ///////// g3 g4 /////////////
27 /////////////////////////////////////////////////////
28 if((Theta[i+j*nWidth]>=90&Θ[i+j*nWidth]<135)||(Theta[i+j*nWidth]>=270&Θ[i+j*nWidth]<315))
29 {
30 g1=M[i-1+(j-1)*nWidth];
31 g2=M[i+(j-1)*nWidth];
32 g3=M[i+(j+1)*nWidth];
33 g4=M[i+1+(j+1)*nWidth];
34 dWeight=fabs(P[i+j*nWidth])/fabs(Q[i+j*nWidth]);
35 dTmp1=g1*dWeight+(1-dWeight)*g2;
36 dTmp2=g4*dWeight+(1-dWeight)*g3;
37 ////////////////////第二种情况///////////////////////
38 ///////// g1 /////////////
39 ///////// g2 C g3 /////////////
40 ///////// g4 /////////////
41 /////////////////////////////////////////////////////
42 }else if((Theta[i+j*nWidth]>=135&Θ[i+j*nWidth]<180)||(Theta[i+j*nWidth]>=315&Θ[i+j*nWidth]<360))
43 {
44 g1=M[i-1+(j-1)*nWidth];
45 g2=M[i-1+(j)*nWidth];
46 g3=M[i+1+(j)*nWidth];
47 g4=M[i+1+(j+1)*nWidth];
48 dWeight=fabs(Q[i+j*nWidth])/fabs(P[i+j*nWidth]);
49 dTmp1=g1*dWeight+(1-dWeight)*g2;
50 dTmp2=g4*dWeight+(1-dWeight)*g3;
51 ////////////////////第三种情况///////////////////////
52 ///////// g1 g2 /////////////
53 ///////// C /////////////
54 ///////// g4 g3 /////////////
55 /////////////////////////////////////////////////////
56 }else if((Theta[i+j*nWidth]>=45&Θ[i+j*nWidth]<90)||(Theta[i+j*nWidth]>=225&Θ[i+j*nWidth]<270))
57 {
58 g1=M[i+1+(j-1)*nWidth];
59 g2=M[i+(j-1)*nWidth];
60 g3=M[i+(j+1)*nWidth];
61 g4=M[i-1+(j+1)*nWidth];
62 dWeight=fabs(P[i+j*nWidth])/fabs(Q[i+j*nWidth]);
63 dTmp1=g1*dWeight+(1-dWeight)*g2;
64 dTmp2=g4*dWeight+(1-dWeight)*g3;
65 ////////////////////第四种情况///////////////////////
66 ///////// g1 /////////////
67 ///////// g4 C g2 /////////////
68 ///////// g3 /////////////
69 /////////////////////////////////////////////////////
70 }else if((Theta[i+j*nWidth]>=0&Θ[i+j*nWidth]<45)||(Theta[i+j*nWidth]>=180&Θ[i+j*nWidth]<225))
71 {
72 g1=M[i+1+(j-1)*nWidth];
73 g2=M[i+1+(j)*nWidth];
74 g3=M[i-1+(j)*nWidth];
75 g4=M[i-1+(j+1)*nWidth];
76 dWeight=fabs(Q[i+j*nWidth])/fabs(P[i+j*nWidth]);
77 dTmp1=g1*dWeight+(1-dWeight)*g2;
78 dTmp2=g4*dWeight+(1-dWeight)*g3;
79
80 }
81
82 }
83
84 if ((M[i+j*nWidth]>=dTmp1)&&(M[i+j*nWidth]>=dTmp2))
85 {
86 N->imageData[i+j*nwidthstep]=200;
87
88 }else N->imageData[i+j*nwidthstep]=0;
89
90 }
91 }
92
93
94 //cvNamedWindow("Limteimg",0);
95 //cvShowImage("Limteimg",N); //显示非抑制
96 //cvWaitKey(0);
97 //cvDestroyWindow("Limteimg");
View Code
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-37359-5.html
不然会很麻烦的