咱们都知道梯度很好求,只须要将[-1,1] 与图像分别在x 方向和y方向卷积,便可求得两个方向上的梯度。不过在求梯度方向时,仍是有些麻烦,由于梯度方向会指向360°的任何一个方向,因此直接用atan(dy/dx)函数,一般会获得正负PI/2范围内的值,所以,在本文中将根据dy、dx的正负,求取任一象限内的梯度方向。x、y以及四个象限以下图所示:函数
在本文中编制了两个函数一个是获取梯度方向函数code
Mat getGradientDirect(Mat&img_dy,Mat&img_dx)blog
一个是将梯度方向等分为8个方向:0、PI/四、PI/二、PI、5PI/四、3PI/二、7PI/4.。函数名为:
void octantDirect(Mat&theta)
下面是两个函数的代码:get
Mat getGradientDirect(Mat&img_dy,Mat&img_dx) { int rows=img_dx.rows,cols=img_dy.cols; Mat theta(rows,cols,img_dx.type(),Scalar::all(0)); for(int i=0;i<rows;i++) { for(int j=0;j<cols;j++) { Vec3f dx=img_dx.at<Vec3f>(i,j); Vec3f dy=img_dy.at<Vec3f>(i,j); for(int k=0;k<theta.channels();k++) { if(dx[k]>0&&dy[k]==0)//X正向 theta.at<Vec3f>(i,j)[k]=0; if(dx[k]>0&&dy[k]>0)//第1象限 theta.at<Vec3f>(i,j)[k]=atan(dy[k]/dx[k]); if(dx[k]==0&&dy[k]>0)//Y正向 theta.at<Vec3f>(i,j)[k]=PI/2; if(dx[k]<0&&dy[k]>0)//第2象限 theta.at<Vec3f>(i,j)[k]=atan(dy[k]/dx[k])+PI; if(dx[k]<0&&dy[k]==0)//X负向 theta.at<Vec3f>(i,j)[k]=PI; if(dx[k]<0&&dy[k]<0)//第3象限 theta.at<Vec3f>(i,j)[k]=atan(dy[k]/dx[k])+PI; if(dx[k]==0&&dy[k]<0)//Y负向 theta.at<Vec3f>(i,j)[k]=PI*1.5; if(dx[k]>0&&dy[k]<0)//第4象限 theta.at<Vec3f>(i,j)[k]=atan(dy[k]/dx[k])+2*PI; if(dx[k]==0&&dy[k]==0)// dy/dx=0/0 theta.at<Vec3f>(i,j)[k]=0; } } } return theta; }
八分仪代码:class
void octantDirect(Mat&theta) { int rows=theta.rows,cols=theta.cols; for(int i=0;i<rows;i++) { for(int j=0;j<cols;j++) { auto p=theta.at<Vec3f>(i,j); // auto pr=theta.data+i*theta.step[0]+j*theta.step[1]; for(int k=0;k<theta.channels();k++) { if((0.125*PI>p[k]&&p[k]>=0) || ( PI*2>p[k]&&p[k]>=PI*1.875)) theta.at<Vec3f>(i,j)[k]=0; if(0.375*PI>p[k]&&p[k]>=0.125*PI) theta.at<Vec3f>(i,j)[k]=1; if(0.625*PI>p[k]&&p[k]>=0.375*PI) theta.at<Vec3f>(i,j)[k]=2; if(0.875*PI>p[k]&&p[k]>=0.625*PI) theta.at<Vec3f>(i,j)[k]=3; if(1.125*PI>p[k]&&p[k]>=0.875*PI) theta.at<Vec3f>(i,j)[k]=4; if(1.375*PI>p[k]&&p[k]>=1.125*PI) theta.at<Vec3f>(i,j)[k]=5; if(1.625*PI>p[k]&&p[k]>=1.375*PI) theta.at<Vec3f>(i,j)[k]=6; if(1.875*PI>p[k]&&p[k]>=1.625*PI) theta.at<Vec3f>(i,j)[k]=7; } } } }