SUSAN ( Small univalue segment assimilating nucleus) 算子是一种基于灰度的特征点获取方法, 适用于图
像中边缘和角点的检测, 可以去除图像中的噪声, 它具有简单、有效、抗噪声能力强、计算速度快的特点。
SUSAN 算子的模板与常规卷积算法的正方形模板不同, 它采用一种近似圆形的模板, 用圆形模板在图像上移动, 模板内部每个图像像素点的灰度值都和模板中心像素的灰度值作比较, 若模板内某个像素的灰度与模板中心像素(核)灰度的差值小于一定值, 则认为该点与核具有相同(或相近)的灰度, 如下图所示。由满足这一条件的像素组成的区域称为吸收核同值区(Univalue Segment Assimilating Nucleus, USAN)。
当圆形模板完全处在背景或目标中时,USAN 区域面积最大;当模板移向目标边缘时,USAN 区域逐渐变小;当模板中心处于边缘时,USAN 区域很小;当模板中心处于角点时,USAN 区域最小。
因此,可以通过计算每 1 个像素的 USAN 值,并与设定的门限值进行比较, 如果该像素的 USAN 值小于门限
值,则该点可以认为是 1 个边缘点。这就是 SUSAN 算法思xia
与其他边缘和角点检测算子相比,SUSAN 算子有一些独特的地方。
(1)在用SUSAN算子对边缘和角点进行检测时不需要计算微分,这使得SUSAN算子对噪声更加鲁棒。
(2)SUSAN检测算子能提供不依赖于模板尺寸的边缘精度。换句话说,最小USAN区域面积的计算是个相对的概念,与模版尺寸无关,所以SUSAN边缘算子的性能不受模版尺寸影响。
(3)控制参数的选择很简单,且任意性小,容易实现自动化选取
下面贴出详细的实现代码
#include
#include
#include
#include "cv.h"
#include "highgui.h"
int main( int argc, char** argv )
{
int height ,width ,step ,channels ;
int i,j,k,same ,max,min,sum;
float thresh;
uchar *data0,*data1 ;
//char *filename="result.bmp";
IplImage* Img, *nimg; //声明IplImage指针
//载入图像
Img = cvLoadImage( "D:\\lena.jpg",0);
cvNamedWindow( "Image0", 2); //创建窗口
cvShowImage( "Image0", Img ); //显示图像
nimg = cvCreateImage(cvGetSize(Img),8,1);
height = Img->height;
width = Img->width;
step = Img->widthStep/sizeof(uchar);
channels = Img->nChannels;
data0 = (uchar*)Img->imageData;
data1 = (uchar*)nimg->imageData;
printf("Processing a %d X %d image with %d channels\n",width,height,channels);
int OffSetX[37] =
{ -1, 0, 1,
-2,-1, 0, 1, 2,
-3,-2,-1, 0, 1, 2, 3,
-3,-2,-1, 0, 1, 2, 3,
-3,-2,-1, 0, 1, 2, 3,
-2,-1, 0, 1, 2,
-1, 0, 1 };
int OffSetY[37] =
{
-3,-3,-3,
-2,-2,-2,-2,-2,
-1,-1,-1,-1,-1,-1,-1,
0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2,
3, 3, 3
};
max = min = data0[0];
for(i=3;i
same =0;
sum = 0;
for(k=0;k<37;k++)
{
sum+=data0[(i+OffSetY[k])*step+(j+OffSetX[k])];
thresh = (float)sum/37;
float data_fabs;
data_fabs= (float)(data0[(i+OffSetY[k])*step+(j+OffSetX[k])]-data0[i*step+j]);
if(fabs( data_fabs)<=thresh)
same++;
}
if(same<18)
nimg->imageData[i*step+j] = 255;
else
nimg->imageData[i*step+j] = 0;
printf("same = %d\n", same);
}
cvNamedWindow( "Image", 2); //创建窗口
cvShowImage( "Image", nimg ); //显示图像
cvWaitKey(0); //等待按键
cvDestroyWindow( "Image" );//销毁窗口
cvReleaseImage( &Img ); //释放图像
cvReleaseImage( &nimg );
return 0;
}