转载自:http://blog.youkuaiyun.com/likezhaobin/article/details/6892629
3.3 图像增强——计算图像梯度及其方向
- //////////////////同样可以用不同的检测器/////////////////////////
- /////
P[i,j]=(S[i,j+1]-S[i,j]+S[i+1,j+1]-S[i+1,j])/2 ///// - /////
Q[i,j]=(S[i,j]-S[i+1,j]+S[i,j+1]-S[i+1,j+1])/2 ///// - /////////////////////////////////////////////////////////////////
- double*
P = new double[nWidth*nHeight]; //x向偏导数 - double*
Q = new double[nWidth*nHeight]; //y向偏导数 - int*
M = new int[nWidth*nHeight]; //梯度幅值 - double*
Theta = new double[nWidth*nHeight]; //梯度方向 - //计算x,y方向的偏导数
- for(i=0;
i<(nHeight-1); i++) - {
-
for(j=0; j<(nWidth-1); j++) -
{ -
P[i*nWidth+j] = (double)(pCanny[i*nWidth + min(j+1, nWidth-1)] - pCanny[i*nWidth+j] + pCanny[min(i+1, nHeight-1)*nWidth+min(j+1, nWidth-1)] - pCanny[min(i+1, nHeight-1)*nWidth+j])/2; -
Q[i*nWidth+j] = (double)(pCanny[i*nWidth+j] - pCanny[min(i+1, nHeight-1)*nWidth+j] + pCanny[i*nWidth+min(j+1, nWidth-1)] - pCanny[min(i+1, nHeight-1)*nWidth+min(j+1, nWidth-1)])/2; -
} - }
- //计算梯度幅值和梯度的方向
- for(i=0;
i<nHeight; i++) - {
-
for(j=0; j<nWidth; j++) -
{ -
M[i*nWidth+j] = (int)(sqrt(P[i*nWidth+j]*P[i*nWidth+j] + Q[i*nWidth+j]*Q[i*nWidth+j])+0.5); -
Theta[i*nWidth+j] = atan2(Q[i*nWidth+j], P[i*nWidth+j]) * 57.3; -
if(Theta[i*nWidth+j] < 0) -
Theta[i*nWidth+j] += 360; //将这个角度转换到0~360范围 -
} - }
3.4 非极大值抑制
- unsigned
char* N = new unsigned char[nWidth*nHeight]; //非极大值抑制结果 - int
g1=0, g2=0, g3=0, g4=0; //用于进行插值,得到亚像素点坐标值 - double
dTmp1=0.0, dTmp2=0.0; //保存两个亚像素点插值得到的灰度数据 - double
dWeight=0.0; //插值的权重
- for(i=0;
i<nWidth; i++) - {
-
N[i] = 0; -
N[(nHeight-1)*nWidth+i] = 0; - }
- for(j=0;
j<nHeight; j++) - {
-
N[j*nWidth] = 0; -
N[j*nWidth+(nWidth-1)] = 0; - }
- for(i=1;
i<(nWidth-1); i++) - {
-
for(j=1; j<(nHeight-1); j++) -
{ -
int nPointIdx = i+j*nWidth; //当前点在图像数组中的索引值 -
if(M[nPointIdx] == 0) -
N[nPointIdx] = 0; //如果当前梯度幅值为0,则不是局部最大对该点赋为0 -
else -
{ -
////////首先判断属于那种情况,然后根据情况插值/////// -
////////////////////第一种情况/////////////////////// -
///////// g1 g2 ///////////// -
///////// C ///////////// -
///////// g3 g4 ///////////// -
///////////////////////////////////////////////////// -
if( ((Theta[nPointIdx]>=90)&&(Theta[nPointIdx]<135)) || -
((Theta[nPointIdx]>=270)&&(Theta[nPointIdx]<315))) -
{ -
//////根据斜率和四个中间值进行插值求解 -
g1 = M[nPointIdx-nWidth-1]; -
g2 = M[nPointIdx-nWidth]; -
g3 = M[nPointIdx+nWidth]; -
g4 = M[nPointIdx+nWidth+1]; -
dWeight = fabs(P[nPointIdx])/fabs(Q[nPointIdx]); //反正切 -
dTmp1 = g1*dWeight+g2*(1-dWeight); -
dTmp2 = g4*dWeight+g3*(1-dWeight); -
} -
////////////////////第二种情况/////////////////////// -
///////// g1 ///////////// -
///////// g2 C g3 ///////////// -
///////// g4 ///////////// -
///////////////////////////////////////////////////// -
else if( ((Theta[nPointIdx]>=135)&&(Theta[nPointIdx]<180)) || -
((Theta[nPointIdx]>=315)&&(Theta[nPointIdx]<360))) -
{ -
g1 = M[nPointIdx-nWidth-1]; -
g2 = M[nPointIdx-1]; -
g3 = M[nPointIdx+1]; -
g4 = M[nPointIdx+nWidth+1]; -
dWeight = fabs(Q[nPointIdx])/fabs(P[nPointIdx]); //正切 -
dTmp1 = g2*dWeight+g1*(1-dWeight); -
dTmp2 = g4*dWeight+g3*(1-dWeight); -
} -
////////////////////第三种情况/////////////////////// -
///////// g1 g2 ///////////// -
///////// C ///////////// -
///////// g4 g3 ///////////// -
///////////////////////////////////////////////////// -
else if( ((Theta[nPointIdx]>=45)&&(Theta[nPointIdx]<90)) || -
((Theta[nPointIdx]>=225)&&(Theta[nPointIdx]<270))) -
{ -
g1 = M[nPointIdx-nWidth]; -
g2 = M[nPointIdx-nWidth+1]; -
g3 = M[nPointIdx+nWidth]; -
g4 = M[nPointIdx+nWidth-1]; -
dWeight = fabs(P[nPointIdx])/fabs(Q[nPointIdx]); //反正切 -
dTmp1 = g2*dWeight+g1*(1-dWeight); -
dTmp2 = g3*dWeight+g4*(1-dWeight); -
} -
////////////////////第四种情况/////////////////////// -
///////// g1 ///////////// -
///////// g4 C g2 ///////////// -
///////// g3 ///////////// -
///////////////////////////////////////////////////// -
else if( ((Theta[nPointIdx]>=0)&&(Theta[nPointIdx]<45)) || -
((Theta[nPointIdx]>=180)&&(Theta[nPointIdx]<225))) -
{ -
g1 = M[nPointIdx-nWidth+1]; -
g2 = M[nPointIdx+1]; -
g3 = M[nPointIdx+nWidth-1]; -
g4 = M[nPointIdx-1]; -
dWeight = fabs(Q[nPointIdx])/fabs(P[nPointIdx]); //正切 -
dTmp1 = g1*dWeight+g2*(1-dWeight); -
dTmp2 = g3*dWeight+g4*(1-dWeight); -
} -
} -
//////////进行局部最大值判断,并写入检测结果//////////////// -
if((M[nPointIdx]>=dTmp1) && (M[nPointIdx]>=dTmp2)) -
N[nPointIdx] = 128; -
else -
N[nPointIdx] = 0; -
} - }