susan角点检测算法
SUSAN算法是1997年牛津大学的Smith等人提出的一种处理灰度图像的方法,它主要是用来计算图像中的角点特征。SUSAN算法选用圆形模板(如图1所示)。将位于圆形窗口模板中心等待检测的像素点称为核心点。核心点的邻域被划分为两个区域:亮度值相似于核心点亮度的区域即核值相似区(Univalue SegmentAs-similatingNueleus,USAN)和亮度值不相似于核心点亮度的区域。
图1 圆形模板
USAN的典型区域如图2所示。模板在图像上移动时,当圆形模板完全在背景或者目标区域时,其USAN区域最大,如图2(a);当核心在边缘时,USAN区域减少一半,如图2(c);当核心在角点时, USAN区域最小,如图2(d)。基于这一原理, Smith提出了最小核值相似区角点检测算法。
图2 典型区域
SUSAN角点检测算法的具体步骤如下:
(1)在图像上放置一个37个像素的圆形模板,模板在图像上滑动,依次比较模板内各个像素点的灰度与模板核的灰度,判断是否属于USAN区域。判别函数如下:
(2)统计圆形模板中和核心点有相似亮度值的像素个数n(r0)。
其中,D(r0)是以r0为中心的圆形模板区域
(3)使用如下角点响应函数。若某个像素点的USAN值小于某一特定阈值,则该点被认为是初始角点,其中,g可以设定为USAN的最大面积的一半。
(4)对初始角点进行非极值抑制来求得最后的角点。
算法实现如下:
IplImage* SUSAN(IplImage* src)
{
uchar *data0, *data1, *data2;
int same, max, min, thresh;
IplImage* img = cvCreateImage(cvGetSize(src), 8, 1); //中间图像
IplImage* dst = cvCreateImage(cvGetSize(src), 8, 1); //结果图像
int height = src->height;
int width = src->width;
int step = src->widthStep / sizeof(uchar);
int channels = src->nChannels;
data0 = (uchar*)src->imageData;
data1 = (uchar*)img->imageData;
data2 = (uchar*)dst->imageData;
int g = 18; //核值相似区域中点个数的阈值
//模版 x 和 y的坐标的偏移量
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 (int i = 0; i < height; i++)
{
for (int j = 0; j<width; j++)
{
if (data0[i*step + j]>max) max = data0[i*step + j];
if (data0[i*step + j]<min) min = data0[i*step + j];
}
}
thresh = (max - min) / 10;//可选取其他方法
for (int i = 3; i < height - 3; i++)
{
for (int j = 3; j < width - 3; j++)
{
same = 0;
for (int k = 0; k < 37; k++)
{
if (abs(data0[(i + OffSetY[k])*step + (j + OffSetX[k])] - data0[i*step + j]) < thresh)
same++;
}
if (same < g)//g值可改
data1[i*step + j] = g-same;
else
data1[i*step + j] = 0;
}
}
//非极大值抑制
int i_s[8] = { -1, -1, -1, 0, 0, 1, 1, 1 };
int j_s[8] = { -1, 0, 1, -1, 1, -1, 0, 1 };
int flag;
for (int i = 4; i < height - 4; i++)
{
for (int j = 4; j < width -4; j++)
{
flag = 0;
for (int k = 0; k < 8; k++)
{
if (data1[i*step + j] <= data1[ (i + i_s[k]) * step + (j + j_s[k]) ] )
{
flag = 1;
break;
}
}
if (flag == 0)
{
data2[i*step + j] = 255;
}
else
{
data2[i*step + j] = 0;
}
}
}
return dst;
}

浙公网安备 33010602011771号