HARRIS 定义的角点位于图像二阶导数的自相关矩阵有两个最大特征值的地方,所以采用二阶导数。
算法流程:
1. 对每个像素点计算图像在X方向Y方向的二阶偏导数,计算图像的XY方向的导数
首先计算Ix,Iy采用Sobel 算子计算近似一阶导数,在边缘检测中,常用的一种模板是Sobel 算子。Sobel 算子有两个,一个是检测水平边缘的 ;另一个是检测垂直边缘的 。公式如下:
求出Ix,Iy
部分代码如下:
//
定义水平方向差分算子并求
Ix
double dx[9]={-1,0,1,-1,0,1,-1,0,1};
mat_Ix=mbys(mat_I,cxDIB,cyDIB,dx,3,3); //
求
Ix
矩阵
//
定义水平方向差分算子并求
Ix
double dx[9]={-1,0,1,-1,0,1,-1,0,1};
mat_Ix=mbys(mat_I,cxDIB,cyDIB,dx,3,3); //
求
Ix
矩阵
</pre><div><pre name="code" class="html" style="color: rgb(51, 51, 51); font-size: 24px; line-height: 24px; text-indent: 28px;"> //定义水平方向差分算子并求Ix double dx[9]={-1,0,1,-2,0,2,-1,0,1}; mat_Ix=mbys(mat_I,cxDIB,cyDIB,dx,3,3); //求Ix矩阵
</pre><br style="color: rgb(51, 51, 51); font-family: arial, 宋体, sans-serif; font-size: 24px; line-height: 24px; text-indent: 28px;" /><div style="color: rgb(51, 51, 51); font-family: arial, 宋体, sans-serif; font-size: 24px; line-height: 24px; text-indent: 28px;"></div><div style="color: rgb(51, 51, 51); font-family: arial, 宋体, sans-serif; font-size: 24px; line-height: 24px; text-indent: 28px;"><pre name="code" class="html">CvMat *mbys(CvMat *mat,intxwidth,intywidth,double *a,int size1,int size2)//size { inti,j; int i1,j1; intpx,py; int m; CvMat *mat1; mat1=cvCloneMat(mat); for(i=size1/2;i<ywidth-size1/2;i++) for(j=size2/2;j<xwidth-size2/2;j++) { m=0; for(i1=0;i1<size1;i1++) for(j1=0;j1<size2;j1++) { px=i-size1/2+i1; py=j-size2/2+j1; //CV_MAT_ELEM访问矩阵元素 m+=CV_MAT_ELEM(*mat,double,px,py)*a[i1*size1+j1]; } CV_MAT_ELEM(*mat1,double,i,j)=m; } return mat1; }
其中同理得出IY
Ixx=IX*Ix;
Iyy=Iy*Iy;
Ixy=Ix*IY;
Ix表示x方向的一阶导数
其中Iy表示y方向的一阶导数
其中Ixx表示X方向的二阶偏导数
Iyy表示Y方向的二阶偏导数
Ixy表XY方向的二阶导数
2.对Ix2/Iy2/Ixy进行高斯平滑,以去除噪声
3.根据下列公式计算角点量(个人理解就是计算每个点的自相关矩阵的特征值)
下为自相关矩阵
计算角点量
计算角点量
角点量公式为
Ix2*Iy2-Ixy*IXY/IX+Iy;
4计算出角点量之后进行局部非极大值抑制
//用来求得局部极大值 CvMat *mblocmax(CvMat *mat1,int xwidth,intywidth,int size) { inti,j; double max=-1000; int i1,j1; intpx,py; CvMat *mat; mat=cvCloneMat(mat1); for(i=size/2;i<ywidth-size/2;i++) for(j=size/2;j<xwidth-size/2;j++) { max=-10000; for(i1=0;i1<size;i1++) var cpro_psid ="u2572954"; var cpro_pswidth =966; var cpro_psheight =120; for(j1=0;j1<size;j1++) { px=i-size/2+i1; py=j-size/2+j1; if(CV_MAT_ELEM(*mat1,double,px,py)>max) max=CV_MAT_ELEM(*mat1,double,px,py); } if(max>0) CV_MAT_ELEM(*mat,double,i,j)=max; else CV_MAT_ELEM(*mat,double,i,j)=0; } return mat; } //用来确认角点 CvMat *mbcorner(CvMat *mat1,CvMat *mat2,int xwidth,intywidth,intsize,double thresh) { CvMat *mat; inti,j; mat=cvCreateMat(ywidth,xwidth,CV_32FC1); for(i=size/2;i<ywidth-size/2;i++) for(j=size/2;j<xwidth-size/2;j++) { if(CV_MAT_ELEM(*mat1,double,i,j)==CV_MAT_ELEM(*mat2,double,i,j))//首先取得局部极大值 //mat1是CRF相应的所有。Mat2是CRF局部极大值点. if(CV_MAT_ELEM(*mat1,double,i,j)>thresh)//然后大于这个阈值 CV_MAT_ELEM(*mat,int,i,j)=255;//满足上两个条件,才是角点! else CV_MAT_ELEM(*mat,int,i,j)=0; } return mat; }最终获得角点