角点检测(兴趣点、关键点、特征点)是计算机视觉系统中用来获得图像特征的一种方法,广泛用于运动检测、图像匹配、视频跟踪、三维重建和目标识别等领域中,也称为特征点检测。
角点并没有明确的定义,一般将图像中亮度变化剧烈的点或图像边缘上曲率取极大值的点认为是角点。角点作为图像的重要特征,保留了图像绝大部分的特征信息,又有效地减少了信息的数据量从而有效地提高了运算速度以及匹配的可靠性。
1. Moravec算子
Moravec在1981年提出Moravec角点检测算子,Moravec角点检测算法是最早的角点检测算法之一。
Moravec的原理如果有一句话来说就是:通过滑动二值矩形窗口寻找灰度变化的局部最大值。具体来说主要包括四个过程:
参考:
http://blog.csdn.net/kezunhai/article/details/11176065
http://blog.csdn.net/carson2005/article/details/39642923
2.Harris算子
Harris算子也称为Plessey算子,是由Harris和Stephens为了改善Moravec算子性能提出的。Harris算子以二阶矩阵(又称为自相关矩阵)为基础,二阶矩阵描述了像素点局部邻域内的梯度分布信息。定义M为像素点(x,y)的自相关矩阵,则
X、Y是一阶方向微分,反映了图像中每个像素的灰度变化方向。为了避免矩阵M进行特征值分解,方便运算,则将角点响应函数表示为:
k为经验值,一般在0.04-0.06之间取值。只要在某一点(x,y)处,超过某一设定的阈值,即认为该点为角点。
Harris算子的计算步骤:
Harris算子具有平移和旋转不变性,对光照条件的变化不敏感。在的角点特征的比较实验中,Harri s角点特征的重复性和区分性被证明是最好的。通过在局部极值点的邻域内对角点响应函数进行二次逼近,Harris算子可以达到亚像素的定位精度。
参考:
http://blog.csdn.net/kezunhai/article/details/11265167
3.SUSAN算子#include
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
Mat g_srcImage, g_srcImage1,g_grayImage;
int thresh=30;
void on_CornerHarris(); //Harris角点检测
void on_GoodFeaturesToTrack(); //Shi-Tomasi角点检测
void on_cornerSubPix(); //亚像素级角点检测
void on_FastFeatureDetector(); //fast特征点检测
int main( int argc, char** argv ){
g_srcImage = imread( "lena.png", 1 );
if(!g_srcImage.data ) { printf("读取图片错误!\n"); return false; }
g_srcImage1=g_srcImage.clone( );
cvtColor( g_srcImage1, g_grayImage, CV_BGR2GRAY );
//on_CornerHarris(); //Harris角点检测
//on_GoodFeaturesToTrack();//Shi-Tomasi角点检测
//on_cornerSubPix();
on_FastFeatureDetector();
waitKey(0);
return(0);
}
//Harris角点检测--------------------------------------------------------------------------------------------
void on_CornerHarris()
{
Mat dstImage;//目标图
Mat normImage;//归一化后的图
Mat scaledImage;//线性变换后的八位无符号整型的图
cornerHarris(g_grayImage, //Input single-channel 8-bit or floating-point image.
dstImage, //Image to store the Harris detector responses. It has the type CV_32FC1 and the same size as src .
2, //Neighborhood size
3, //Aperture parameter for the Sobel() operator
0.04, // Harris detector free parameter
BORDER_DEFAULT );// Pixel extrapolation method
normalize( dstImage, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );
convertScaleAbs( normImage, scaledImage );//将归一化后的图线性变换成8位无符号整型
for( int j = 0; j < normImage.rows ; j++ ){
for( int i = 0; i < normImage.cols; i++ ){
if( (int) normImage.at(j,i) > thresh+100 ){
circle( g_srcImage1, Point( i, j ), 5, Scalar(10,10,255), 2, 8, 0 );
circle( scaledImage, Point( i, j ), 5, Scalar(0,10,255), 2, 8, 0 );
}
}
}
imshow("g_srcImage1",g_srcImage1);
}
//Shi-Tomasi角点检测--------------------------------------------------------------------------------------------
void on_GoodFeaturesToTrack()
{
vector corners;
int g_maxCornerNumber = 33;
double qualityLevel = 0.01; //角点检测可接受的最小特征值
double minDistance = 10; //角点之间的最小距离
int blockSize = 3; //计算导数自相关矩阵时指定的邻域范围
double k = 0.04; //权重系数
Mat copy = g_srcImage.clone();
//进行Shi-Tomasi角点检测
goodFeaturesToTrack( g_grayImage, //Input 8-bit or floating-point 32-bit, single-channel image.
corners, //Output vector of detected corners.
g_maxCornerNumber, //Maximum number of corners to return.
qualityLevel, //Parameter characterizing the minimal accepted quality of image corners.
minDistance, //Minimum possible Euclidean distance between the returned corners.
Mat(), //Optional region of interest.
blockSize, //Size of an average block for computing a derivative covariation matrix over each pixel neighborhood.
false, //Parameter indicating whether to use a Harris detector
k ); // Free parameter of the Harris detector.
//point2f 转KeyPoint
vector keypoints;
for( size_t i = 0; i < corners.size(); i++ ) {
keypoints.push_back(KeyPoint(corners[i], 1.f));
}
//绘制关键点
drawKeypoints(copy,keypoints,copy,Scalar::all(-1),DrawMatchesFlags::DEFAULT);
imshow("Shi-Tomasi角点", copy );
}
//亚像素级角点检测角点检测--------------------------------------------------------------------------------------------
void on_cornerSubPix()
{
vector corners;
int g_maxCornerNumber = 33;
double qualityLevel = 0.01;
double minDistance = 10;
int blockSize = 3;
double k = 0.04;
Mat copy = g_srcImage.clone();
//进行Shi-Tomasi角点检测
goodFeaturesToTrack(g_grayImage,corners, g_maxCornerNumber,qualityLevel,minDistance,Mat(),blockSize,false,k);
//亚像素级角点检测角点检测
Size winSize = Size( 5, 5 );
Size zeroZone = Size( -1, -1 );
TermCriteria criteria = TermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 40, 0.001 );
cornerSubPix( g_grayImage, // Input image
corners, //Initial coordinates of the input corners and refined coordinates provided for output.
winSize, //Half of the side length of the search window.
zeroZone, // Half of the size of the dead region in the middle of the search zone over which the summation in the formula below is not done.
criteria ); //Criteria for termination of the iterative process of corner refinement.
cout< keypoints;
for( size_t i = 0; i < corners.size(); i++ ) {
keypoints.push_back(KeyPoint(corners[i], 1.f));
}
//绘制关键点
drawKeypoints(copy,keypoints,copy,Scalar::all(-1),DrawMatchesFlags::DEFAULT);
imshow("亚像素级角点检测角点检测", copy );
}
//fast特征点检测角点检测------------------------------------------------------------------------
void on_FastFeatureDetector(){
std::vector keyPoints;
FastFeatureDetector fast(50); // 检测的阈值为50
fast.detect(g_srcImage1,keyPoints);
drawKeypoints(g_srcImage1, keyPoints, g_srcImage1, Scalar::all(255), DrawMatchesFlags::DRAW_OVER_OUTIMG);
imshow("FAST feature", g_srcImage1);
}