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);
}