【OpenCV】角点检测:Harris角点及Shi-Tomasi角点检测
角点检测总结
核心内容
角点定义:
- 角点是图像中特殊位置的像素点,在多个方向上具有显著变化。
- 包括基于梯度的变化、边缘交界处、高变化率位置以及特定方向上的变化。
Harris角点检测:- 通过计算窗口平移后的灰度变化矩阵M。
- 使用矩阵M的迹和行列式的差值(即det(M) - k(trace(M))²)判断是否为角点。
- 适用于提取稳定的特征。
Shi-Tomasi改进:- 考虑最小特征值的最大化来选择特征点。
- 提供更好的结果,在许多情况下优于Harris方法。
实现与代码示例:- OpenCV中的cornerHarris函数用于Harris检测。
- goodFeaturesToTrack函数用于Shi-Tomasi检测。
- 可调整阈值以优化检测效果。
实践与应用:- 使用滑动条调整阈值进行实时跟踪。
- 提供了详细的代码示例和结果展示。
参考资料:- Shi and Tomasi的论文《Good Features to Track》。
- Szeliski的《Computer Vision: Algorithms and Applications》。
总结:本文全面介绍了角点检测的基本概念、方法及其实现,特别强调了Harris和Shi-Tomasi算法的优势,并提供了相应的代码示例以供参考。
角点
在Computer Vision领域中扮演着十分重要的角色的是关键信息提取技术,在这一过程中,在图像中识别出独特的元素并建立它们之间的联系至关重要。其中一种常见的元素类型是基于图像中的特殊位置定义的关键信息标记(key information markers),这类标记也被称为焦点区域标记(focus region markers)或交叉标记(cross markers)。
关于角点的具体描述可以有几种:
- 在图像中具有灰度梯度局部极大值的位置;
- 图像中多个边缘交叉的位置;
- 梯度幅值和方向均发生显著变化的区域;
- 角落位置上的一阶导数值达到最大,并且二阶导数值为零;该区域表明物体边缘变化方向上的不连续性。
Harris角点检测
当一个移动窗口在一个图像中滑动时,在平滑区域(如图a所示),无论从哪个方向观察该窗口其位置均未发生变化;沿着边缘(如图b所示)该窗口的位置仅沿边缘方向发生微小位移;位于角点处(如图c所示)的窗口无论从哪个方向观察其位置均发生显著变化;Harris角点检测算法正是基于这一物理现象的特点设计的通过分析不同方向上的位移程度来判断图像中的特征点是否为角点

将图像窗口平移[u,v]产生灰度变化E(u,v)

由:

, 得到:

对于局部微小的移动量 [u,v],近似表达为:

其中M是 2*2 矩阵,可由图像的导数求得:

E(u,v)的椭圆形式如下图:

该函数可表示为:[ R 等于:

该算法通过对其响应函数R实施阈值处理来实现对角点的检测。具体而言,在计算得到响应函数R后,在每个像素位置上判断其是否大于预设阈值threshold(即 R > threshold ),若满足条件,则识别为图像中的角点候选。
【相关代码】
OpenCV中定义了 cornerHarris 函数:
void cornerHarris( InputArray src, OutputArray dst, int blockSize,
int ksize, double k,
int borderType=BORDER_DEFAULT );
可以结合 convertScaleAbs 函数,通过阈值取角点:
void cornerHarris_demo( int, void* )
{
Mat dst, dst_norm;
dst = Mat::zeros( src.size(), CV_32FC1 );
/// Detector parameters
int blockSize = 2;
int apertureSize = 3;
double k = 0.04;
/// Detecting corners
cornerHarris( src_gray, dst, blockSize, apertureSize, k, BORDER_DEFAULT );
/// Normalizing
normalize( dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );
convertScaleAbs( dst_norm, dst_norm_scaled );
/// Drawing a circle around corners
for( int j = 0; j < dst_norm.rows ; j++ )
{ for( int i = 0; i < dst_norm.cols; i++ )
{
if( (int) dst_norm.at<float>(j,i) > thresh )
{
circle( dst_norm_scaled, Point( i, j ), 5, Scalar(0), 2, 8, 0 );
circle(src,Point( i, j ), 5, Scalar(255,0,0), -1, 8, 0 );
}
}
}
/// Showing the result
imshow( corners_window, dst_norm_scaled );
imshow( source_window, src );
}
Shi-Tomasi 算法
Shi-Tomasi算法基于Harris算法的改进技术发展而来。该算法的基本定义为利用矩阵M的行列式与迹进行计算并将其与预设阈值进行比较。随后Shi和Tomasi提出了一种新的检测方法用于检测两个特征值中的较小者是否超过最小阈值从而实现对强角点的有效识别。
如上面第二幅图中,对自相关矩阵 M 进行特征值分析,产生两个特征值

和两个特征方向向量。因为较大的不确定度取决于较小的特征值,也就是

因此,在寻求具有最大最小特征值的特征点方面取得进展也就合乎情理了。 Shi 和Tomasi 方法较为完善,在多数情况下能够优于Harris算法的结果。
【相关代码】
该Shi-Tomasi算子源于1994年 Good Features to Track 这一历史文献中首次提出;基于 OpenCV 实现的算法将函数名称命名为 goodFeaturesToTrack。
void goodFeaturesToTrack( InputArray image, OutputArray corners,
int maxCorners, double qualityLevel, double minDistance,
InputArray mask=noArray(), int blockSize=3,
bool useHarrisDetector=false, double k=0.04 );
自定义使用函数(以方便createTrackbar的响应)如下:
void cornerShiTomasi_demo( int, void* )
{
if( maxCorners < 1 ) { maxCorners = 1; }
/// Parameters for Shi-Tomasi algorithm
vector<Point2f> corners;
double qualityLevel = 0.01;
double minDistance = 10;
int blockSize = 3;
bool useHarrisDetector = false;
double k = 0.04;
/// Copy the source image
Mat cormat;
/// Apply corner detection :Determines strong corners on an image.
goodFeaturesToTrack( src_gray,
corners,
maxCorners,
qualityLevel,
minDistance,
Mat(),
blockSize,
useHarrisDetector,
k );
/// Draw corners detected
for( int i = 0; i < corners.size(); i++ ){
circle( dst_norm_scaled, corners[i], 5, Scalar(255), 2, 8, 0 );
circle( src, corners[i], 4, Scalar(0,255,0), 2, 8, 0 );
}
/// Show what you got
imshow( corners_window, dst_norm_scaled );
imshow( source_window, src );
}
实践
在主函数中定义两个进度条方便调整阈值:
namedWindow( source_window, CV_WINDOW_AUTOSIZE );
createTrackbar( "Threshold: ", source_window, &thresh, max_thresh, cornerHarris_demo );
createTrackbar( "Max corners:", source_window, &maxCorners, maxTrackbar, cornerShiTomasi_demo );
namedWindow( corners_window, CV_WINDOW_AUTOSIZE );
namedWindow( source_window, CV_WINDOW_AUTOSIZE );
imshow( source_window, src );
cornerHarris_demo( 0, 0 );
cornerShiTomasi_demo( 0, 0 );
需要注意的是,在OpenCV 2.4.2中的角点检测跟踪示例代码存在不足之处。这是因为SURF等算法不再定义在feature2d模块中,并且它们现在位于legacy和nonfree模块中。因此,在实际应用中建议采用以下方法进行引用:
#include "opencv2/legacy/legacy.hpp"
#include "opencv2/nonfree/nonfree.hpp"
角点检测结果:

蓝色实心点代表Harris角点检测的结果,绿色空心圈代表goodFeatureToTrack角点检测的结果。
M特征值分解后每个像素点相减的图(也就是Harris阈值判断的图)如下:

黑色实心圆点代表Harris阈值检测的结果,在图像中显示出来;而白色空心圆圈则代表使用Shi-Tomasi检测方法(当阈值设置为27时)得到的结果
转载请注明出处:<>
源码及资料下载: https://github.com/xiaoweicqu/corner-detect
参考资料:
[1] S. Shi and C. Tomasi. Excellence in Feature Matching. Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition, pages 593-600, June 1994.
Richard Szeliski博士的《计算机视觉:算法与应用》由斯普林格出版社在纽约于2010年出版。
用于图像关键点检测的演示文稿 http://wenku.baidu.com/view/f61bc369561252d380eb6ef0.html
