Harris角点检测


close all;
clear all;
clc;

img=imread('rice.png');
imshow(img);
[m n]=size(img);

tmp=zeros(m+2,n+2);
tmp(2:m+1,2:n+1)=img;
Ix=zeros(m+2,n+2);
Iy=zeros(m+2,n+2);

E=zeros(m+2,n+2);

Ix(:,2:n)=tmp(:,3:n+1)-tmp(:,1:n-1);
Iy(2:m,:)=tmp(3:m+1,:)-tmp(1:m-1,:);

Ix2=Ix(2:m+1,2:n+1).^2;
Iy2=Iy(2:m+1,2:n+1).^2;
Ixy=Ix(2:m+1,2:n+1).*Iy(2:m+1,2:n+1);

h=fspecial('gaussian',[7 7],2);
Ix2=filter2(h,Ix2);
Iy2=filter2(h,Iy2);
Ixy=filter2(h,Ixy);

Rmax=0;
R=zeros(m,n);
for i=1:m
    for j=1:n
        M=[Ix2(i,j) Ixy(i,j);Ixy(i,j) Iy2(i,j)];
        R(i,j)=det(M)-0.06*(trace(M))^2;
        
        if R(i,j)>Rmax
            Rmax=R(i,j);
        end
    end
end
re=zeros(m+2,n+2);

tmp(2:m+1,2:n+1)=R;
img_re=zeros(m+2,n+2);
img_re(2:m+1,2:n+1)=img;
for i=2:m+1
    for j=2:n+1
        
        if tmp(i,j)>0.01*Rmax &&...
           tmp(i,j)>tmp(i-1,j-1) && tmp(i,j)>tmp(i-1,j) && tmp(i,j)>tmp(i-1,j+1) &&...
           tmp(i,j)>tmp(i,j-1) && tmp(i,j)>tmp(i,j+1) &&...
           tmp(i,j)>tmp(i+1,j-1) && tmp(i,j)>tmp(i+1,j) && tmp(i,j)>tmp(i+1,j+1)
                img_re(i,j)=255; 
        end
          
    end
end

figure,imshow(mat2gray(img_re(2:m+1,2:n+1)));

 //定义模板运算函数

//im:输入图像  tp:模板参数

double * mbys(double * im,int imW,intimH,double *tp,int tpW,int tpH)

{

         double* out=new double[imW*imH];

         memset(out,0, imW*imH*sizeof(double));

         inti,j,m,n;

         #defineim(ROW,COL) im[imW*(ROW)+(COL)]

         #definetp(ROW,COL) tp[tpW*(ROW)+(COL)]

         #defineout(ROW,COL) out[imW*(ROW)+(COL)]

         doublea;

         for(i=0;i<imH;i++)

                   for(j=0;j<imW;j++)

                   {

                            a=0;

                            //去掉靠近边界的行

                            if(i>int(tpH/2)&& i<imH-int(tpH/2) && j>int(tpW/2) &&j<imW-int(tpW/2))

                                     for(m=0;m<tpH;m++)

                                               for(n=0;n<tpW;n++)

                                               {

                                                        a+=im(i+m-int(tpH/2),j+n-int(tpW/2))*tp(m,n);

                                               }

                            out(i,j)=a;

                   }

         returnout;

}

 

void CImagetestDoc::OnImgHarris()

{

         //gausswidth:二维高斯窗口宽度

         //sigma:高斯函数的方差

         //size:非极大值抑制的邻域宽度

         //thresh:最终确定角点所需的阈值

         inti,j,m,n,size,thresh,gausswidth;

         doublesigma;

 

         //输入四个参数

         CInput2input;

         input.m_gausswidth=5;

         input.m_sigma=0.8;

         input.m_size=5;

         input.m_thresh=5000;

         input.DoModal();

         gausswidth=input.m_gausswidth;

         sigma=input.m_sigma;

         size=input.m_size;

         thresh=input.m_thresh;

 

 

   unsigned char *lpSrc;//一个指向源、目的像素的移动指针

         LPSTRlpDIB = (LPSTR) ::GlobalLock((HGLOBAL)m_hDIB);

         intcxDIB = (int) ::DIBWidth(lpDIB);        // 图像宽度

         intcyDIB = (int) ::DIBHeight(lpDIB);       // 图像高度

         LPSTRlpDIBBits=::FindDIBBits (lpDIB);

         longlLineBytes = WIDTHBYTES(cxDIB * 8);    // 计算灰度图像每行的字节数

 

         //创建I、Ix、Ix2、Iy、Iy2、Ixy、cim、mx、corner数组

         double*I=new double[cxDIB*cyDIB];

         double*Ix=new double[cxDIB*cyDIB];

         double*Ix2=new double[cxDIB*cyDIB];

         double*Iy=new double[cxDIB*cyDIB];

         double*Iy2=new double[cxDIB*cyDIB];

         double*Ixy=new double[cxDIB*cyDIB];

         double*cim=new double[cxDIB*cyDIB];

         double*mx=new double[cxDIB*cyDIB];

 

         corner=newbool[cxDIB*cyDIB];

         memset(corner,0, cxDIB*cyDIB*sizeof(bool));

 

         //定义宏以方便访问元素

         #defineI(ROW,COL) I[cxDIB*(ROW)+(COL)]

         #defineIx(ROW,COL) Ix[cxDIB*(ROW)+(COL)]

         #defineIx2(ROW,COL) Ix2[cxDIB*(ROW)+(COL)]

         #defineIy(ROW,COL) Iy[cxDIB*(ROW)+(COL)]

         #defineIy2(ROW,COL) Iy2[cxDIB*(ROW)+(COL)]

         #defineIxy(ROW,COL) Ixy[cxDIB*(ROW)+(COL)]

         #definecim(ROW,COL) cim[cxDIB*(ROW)+(COL)]

         #definemx(ROW,COL) mx[cxDIB*(ROW)+(COL)]

         #definecorner(ROW,COL) corner[cxDIB*(ROW)+(COL)]

 

         //将图像灰度值复制到I中,这步很重要!想想为什么?

         for(i= 0; i < cyDIB; i++)

         {

                   for(j= 0; j < cxDIB; j++)

                   {                          

                            lpSrc= (unsigned char*)lpDIBBits + lLineBytes * (cyDIB - 1 - i) + j;

                            //将256级灰度图像转化为double型

                            I(i,j)=double(*lpSrc);

                   }

         }

 

 

         //--------------------------------------------------------------------------

         //                     第一步:利用差分算子对图像进行滤波

         //--------------------------------------------------------------------------

        

         //定义水平方向差分算子并求Ix

         doubledx[9]={-1,0,1,-1,0,1,-1,0,1};

         Ix=mbys(I,cxDIB,cyDIB,dx,3,3);

 

         //定义垂直方向差分算子并求Iy

         doubledy[9]={-1,-1,-1,0,0,0,1,1,1};

         Iy=mbys(I,cxDIB,cyDIB,dy,3,3);

 

        

         //计算Ix2、Iy2、Ixy

         for(i= 0; i < cyDIB; i++)

         {

                   for(j= 0; j < cxDIB; j++)

                   {        Ix2(i,j)=Ix(i,j)*Ix(i,j);

                            Iy2(i,j)=Iy(i,j)*Iy(i,j);

                            Ixy(i,j)=Ix(i,j)*Iy(i,j);

                   }

         }

 

 

         //--------------------------------------------------------------------------

         //                  第二步:对Ix2/Iy2/Ixy进行高斯平滑,以去除噪声

         //--------------------------------------------------------------------------

        

         //本例中使用5×5的高斯模板

         //计算模板参数

         double*g=new double[gausswidth*gausswidth];

         for(i=0;i<gausswidth;i++)

                   for(j=0;j<gausswidth;j++)

                            g[i*gausswidth+j]=exp(-((i-int(gausswidth/2))*(i-int(gausswidth/2))+(j-int(gausswidth/2))*(j-int(gausswidth/2)))/(2*sigma));

        

         //归一化:使模板参数之和为1(其实此步可以省略)

         doubletotal=0;

         for(i=0;i<gausswidth*gausswidth;i++)

                   total+=g[i];

         for(i=0;i<gausswidth;i++)

                   for(j=0;j<gausswidth;j++)

                            g[i*gausswidth+j]/=total;

 

         //进行高斯平滑

         Ix2=mbys(Ix2,cxDIB,cyDIB,g,gausswidth,gausswidth);

         Iy2=mbys(Iy2,cxDIB,cyDIB,g,gausswidth,gausswidth);

         Ixy=mbys(Ixy,cxDIB,cyDIB,g,gausswidth,gausswidth);

        

 

         //--------------------------------------------------------------------------

         //                        第三步:计算角点量

         //--------------------------------------------------------------------------

        

         //计算cim:即cornernessof image,我们把它称做‘角点量’

         for(i= 0; i < cyDIB; i++)

         {

                   for(j= 0; j < cxDIB; j++)

                   {

                            //注意:要在分母中加入一个极小量以防止除数为零溢出

                            cim(i,j)= (Ix2(i,j)*Iy2(i,j) - Ixy(i,j)*Ixy(i,j))/(Ix2(i,j) + Iy2(i,j) + 0.000001);

                   }

         }

 

 

         //--------------------------------------------------------------------------

         //                 第四步:进行局部非极大值抑制以获得最终角点

         //--------------------------------------------------------------------------

        

         //注意进行局部极大值抑制的思路

 

         //constdouble size=7;

         doublemax;

         //对每个点在邻域内做极大值滤波:即将该点的值设为邻域中最大的那个值(跟中值滤波有点类似)

         for(i= 0; i < cyDIB; i++)

         {

                   for(j= 0; j < cxDIB; j++)

                   {

                            max=-1000000;

                            if(i>int(size/2)&& i<cyDIB-int(size/2) && j>int(size/2) &&j<cxDIB-int(size/2))

                                     for(m=0;m<size;m++)

                                     {

                                               for(n=0;n<size;n++)

                                                        {                                                      

                                                                 if(cim(i+m-int(size/2),j+n-int(size/2))>max)

                                                                           max=cim(i+m-int(size/2),j+n-int(size/2));

                                                        }

                                     }

                            if(max>0)

                                     mx(i,j)=max;

                            else

                                     mx(i,j)=0;

                   }

         }

 

         //最终确定角点

         //constdouble thresh=4500;

         for(i= 0; i < cyDIB; i++)

         {

                   for(j= 0; j < cxDIB; j++)

                   {       

                            if(cim(i,j)==mx(i,j))  //首先取得局部极大值

                                               if(mx(i,j)>thresh)  //然后大于这个阈值

                                                        corner(i,j)=1;   //满足上两个条件,才是角点!

                   }

         }

        

         ::GlobalUnlock((HGLOBAL)m_hDIB);    

   UpdateAllViews(NULL, 0, NULL);   

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值