SUSAN算子的实现一、实验内容特征点即图像的极值点、线段的端点、曲线曲率最大点,它保留了图像的重要特征,可以代替图像的处理,有效减少数据量,提高处理速度。本实验要求通过课堂讲授知识,利用SUSAN算子实现特征点的提取。二、实验原理1.SUSAN算子SUSAN算子是牛津大学的Smith教授提出的,只使用一个圆形模板来计算各向同性的响应,既可检测目标边缘点,又能检测图像中的角点,且具有较强的鲁棒性。2.基本思想SUSAN算子使用圆形模板,通过检测模板范围内的核同值区域(USAN)的面积大小,判断该像素(核)是否为角点。有如下结论:(1)USAN面积大于一半,核位于灰度一致区;(2)USAN面积小,核接近边缘;(3)USAN面积最小,核位于角点。三、基本原理与步骤(1)选择圆形模板,共37个像素,按照从左至右从上至下的顺序存入数组,中心像素(核)为第十九个像素;(2)找出核同值像素,并计算核同值区域的面积:C(𝑥0,𝑦0;𝑥,𝑦)={1|𝑓(𝑥0,𝑦0)−𝑓(𝑥,𝑦)|≤𝑇0|𝑓(𝑥0,𝑦0)−𝑓(𝑥,𝑦)|𝑇S(𝑥0,𝑦0)=∑𝐶(𝑥0,𝑦0;𝑥,𝑦)(𝑥,𝑦)∈𝑀(𝑥,𝑦)S(𝑥0,𝑦0)即为核同值区域面积。(3)阈值化得到初步的边缘响应R(𝑥0,𝑦0)={𝐺−S(𝑥0,𝑦0)S(𝑥0,𝑦0)𝐺0𝑒𝑙𝑠𝑒G取USAN最大值的1/2.USAN值越小,角点的响应就越强。四、实验代码BOOLCBmpProcessView::SUSAN(LPSTRlpDIBBits,LONGlWidth,LONGlHeight){//指向源图像的指针LPSTRlpSrc;//指向缓存图像的指针LPSTRlpDst;//指向缓存DIB图像的指针LPSTRlpNewDIBBits;HLOCALhNewDIBBits;//循环变量longi;longj;unsignedcharpixel[37];//暂时分配内存,以保存新图像hNewDIBBits=LocalAlloc(LHND,lWidth*lHeight);if(hNewDIBBits==NULL){//分配内存失败returnFALSE;}//锁定内存lpNewDIBBits=(char*)LocalLock(hNewDIBBits);//初始化新分配的内存,设定初始值为255lpDst=(char*)lpNewDIBBits;memset(lpDst,(BYTE)255,lWidth*lHeight);PPointm_point;g_point.clear();//使用水平方向的结构元素进行腐蚀for(j=lHeight-4;j2;j--){for(i=3;ilWidth-3;i++){//由于使用7×7的模板,为防止越界,所以不处理最下边和最右边的两列像素//指向源图像第j行,第i个象素的指针lpSrc=(char*)lpDIBBits+lWidth*j+i;//指向目标图像第j行,第i个象素的指针lpDst=(char*)lpNewDIBBits+lWidth*j+i;pixel[0]=(unsignedchar)*(lpSrc-3*lWidth-1);pixel[1]=(unsignedchar)*(lpSrc-3*lWidth);pixel[2]=(unsignedchar)*(lpSrc-3*lWidth+1);pixel[3]=(unsignedchar)*(lpSrc-2*lWidth-2);pixel[4]=(unsignedchar)*(lpSrc-2*lWidth-1);pixel[5]=(unsignedchar)*(lpSrc-2*lWidth);pixel[6]=(unsignedchar)*(lpSrc-2*lWidth+1);pixel[7]=(unsignedchar)*(lpSrc-2*lWidth+2);pixel[8]=(unsignedchar)*(lpSrc-lWidth-3);pixel[9]=(unsignedchar)*(lpSrc-lWidth-2);pixel[10]=(unsignedchar)*(lpSrc-lWidth-1);pixel[11]=(unsignedchar)*(lpSrc-lWidth);pixel[12]=(unsignedchar)*(lpSrc-lWidth+1);pixel[13]=(unsignedchar)*(lpSrc-lWidth+2);pixel[14]=(unsignedchar)*(lpSrc-lWidth+3);pixel[15]=(unsignedchar)*(lpSrc-3);pixel[16]=(unsignedchar)*(lpSrc-2);pixel[17]=(unsignedchar)*(lpSrc-1);pixel[18]=(unsignedchar)*lpSrc;pixel[19]=(unsignedchar)*(lpSrc+1);pixel[20]=(unsignedchar)*(lpSrc+2);pixel[21]=(unsignedchar)*(lpSrc+3);pixel[22]=(unsignedchar)*(lpSrc+lWidth-3);pixel[23]=(unsignedchar)*(lpSrc+lWidth-2);pixel[24]=(unsignedchar)*(lpSrc+lWidth-1);pixel[25]=(unsignedchar)*(lpSrc+lWidth);pixel[26]=(unsignedchar)*(lpSrc+lWidth+1);pixel[27]=(unsignedchar)*(lpSrc+lWidth+2);pixel[28]=(unsignedchar)*(lpSrc+lWidth+3);pixel[29]=(unsignedchar)*(lpSrc+2*lWidth-2);pixel[30]=(unsignedchar)*(lpSrc+2*lWidth-1);pixel[31]=(unsignedchar)*(lpSrc+2*lWidth);pixel[32]=(unsignedchar)*(lpSrc+2*lWidth+1);pixel[33]=(unsignedchar)*(lpSrc+2*lWidth+2);pixel[34]=(unsignedchar)*(lpSrc+3*lWidth-1);pixel[35]=(unsignedchar)*(lpSrc+3*lWidth);pixel[36]=(unsignedchar)*(lpSrc+3*lWidth+1);ints=0;for(intk=0;k37;k++){if(abs(pixel[18]-pixel[k])27)s++;}intr=0;if(s18){r=18-s;m_point.x=i;m_point.y=lHeight-1-j;g_point.push_back(m_point);}elser=0;}}//返回returnTRUE;}五、实验结果原始图像SUSAN算子提取角点六、实验分析(1)SUSAN算法是比较容易实现的角点检测算法,按照课堂上讲述的内容,编译难度较小,让大家头痛的地方在于如何把搜寻到的角点用画笔描绘出来。开始我直接改变了像素的灰度值,把角点置为白色,效果还可以,但是有个最大的缺陷就是改变了原有图像。后来在李建胜教员的帮助下,我可以用画笔标出图像中的角点,并且并未改变原有图片。画笔的使用算是本次实验的额外收获。(2)在最初代码运行时,程序并未报错,但是图像中并没有检测出角点。在一步步检查下,我发现原因是我在定义变量时没有区分全局变量与局部变量,比如用s、r记录核同值区域面积和边缘响应值时,我在全局中定义声明并且进行初始化,导致循环结束后变量的值仍是赋给的初值,循环的结果没有保存在相应的变量中,所以变量值始终为初始值(0)。这是细节导致失误。