代码改变世界

角点检测:Harris角点及Shi-Tomasi角点检测

2016-01-09 14:18  GarfieldEr007  阅读(517)  评论(0编辑  收藏  举报

角点

特征检测与匹配是Computer Vision 应用总重要的一部分,这需要寻找图像之间的特征建立对应关系。点,也就是图像中的特殊位置,是很常用的一类特征,点的局部特征也可以叫做“关键特征点”(keypoint feature),或“兴趣点”(interest point),或“角点”(conrner)。

关于角点的具体描述可以有几种:

  • 一阶导数(即灰度的梯度)的局部最大所对应的像素点;
  • 两条及两条以上边缘的交点;
  • 图像中梯度值和梯度方向的变化速率都很高的点;
  • 角点处的一阶导数最大,二阶导数为零,指示物体边缘变化不连续的方向。

 

Harris角点检测

当一个窗口在图像上移动,在平滑区域如图(a),窗口在各个方向上没有变化。在边缘上如图(b),窗口在边缘的方向上没有变化。在角点处如图(c),窗口在各个方向上具有变化。Harris角点检测正是利用了这个直观的物理现象,通过窗口在各个方向上的变化程度,决定是否为角点。

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

由:, 得到:

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

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

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

 

定义角点响应函数 R 为:

Harris角点检测算法就是对角点响应函数R进行阈值处理:R > threshold,即提取R的局部极大值。

 

【相关代码】

OpenCV中定义了 cornerHarris 函数:

[cpp] view plaincopy
 
 
  1. void cornerHarris( InputArray src, OutputArray dst, int blockSize,  
  2.                                 int ksize, double k,  
  3.                                 int borderType=BORDER_DEFAULT );  

可以结合 convertScaleAbs 函数,通过阈值取角点:

[cpp] view plaincopy
 
 
  1. void cornerHarris_demo( int, void* )  
  2. {  
  3.   Mat dst, dst_norm;  
  4.   dst = Mat::zeros( src.size(), CV_32FC1 );  
  5.   /// Detector parameters  
  6.   int blockSize = 2;  
  7.   int apertureSize = 3;  
  8.   double k = 0.04;  
  9.   /// Detecting corners  
  10.   cornerHarris( src_gray, dst, blockSize, apertureSize, k, BORDER_DEFAULT );  
  11.   /// Normalizing  
  12.   normalize( dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );  
  13.   convertScaleAbs( dst_norm, dst_norm_scaled );   
  14.   /// Drawing a circle around corners  
  15.   for( int j = 0; j < dst_norm.rows ; j++ )  
  16.      { for( int i = 0; i < dst_norm.cols; i++ )  
  17.           {  
  18.             if( (int) dst_norm.at<float>(j,i) > thresh )  
  19.               {   
  20.                 circle( dst_norm_scaled, Point( i, j ), 5,  Scalar(0), 2, 8, 0 );   
  21.                 circle(src,Point( i, j ), 5,  Scalar(255,0,0), -1, 8, 0 );  
  22.               }  
  23.           }   
  24.      }      
  25.   /// Showing the result  
  26.   imshow( corners_window, dst_norm_scaled );  
  27.   imshow( source_window, src );    
  28. }  

 
 

Shi-Tomasi 算法

Shi-Tomasi 算法是Harris 算法的改进。Harris 算法最原始的定义是将矩阵 M 的行列式值与 M 的迹相减,再将差值同预先给定的阈值进行比较。后来Shi 和Tomasi 提出改进的方法,若两个特征值中较小的一个大于最小阈值,则会得到强角点。

如上面第二幅图中,对自相关矩阵 M 进行特征值分析,产生两个特征值和两个特征方向向量。因为较大的不确定度取决于较小的特征值,也就是,所以通过寻找最小特征值的最大值来寻找好的特征点也就解释的通了。
Shi 和Tomasi 的方法比较充分,并且在很多情况下可以得到比使用Harris 算法更好的结果。

 

【相关代码】

由于这种Shi-Tomasi算子与1994年在文章 Good Features to Track [1]中提出,OpenCV 实现的算法的函数名定义为 goodFeaturesToTrack:

[cpp] view plaincopy
 
 
  1. void goodFeaturesToTrack( InputArray image, OutputArray corners,  
  2.                                      int maxCorners, double qualityLevel, double minDistance,  
  3.                                      InputArray mask=noArray(), int blockSize=3,  
  4.                                      bool useHarrisDetector=false, double k=0.04 );  

自定义使用函数(以方便createTrackbar的响应)如下:

[cpp] view plaincopy
 
 
  1. void cornerShiTomasi_demo( int, void* )  
  2. {  
  3.   if( maxCorners < 1 ) { maxCorners = 1; }  
  4.   /// Parameters for Shi-Tomasi algorithm  
  5.   vector<Point2f> corners;  
  6.   double qualityLevel = 0.01;  
  7.   double minDistance = 10;  
  8.   int blockSize = 3;  
  9.   bool useHarrisDetector = false;  
  10.   double k = 0.04;  
  11.   /// Copy the source image  
  12.   Mat cormat;  
  13.   /// Apply corner detection :Determines strong corners on an image.  
  14.   goodFeaturesToTrack( src_gray,   
  15.                corners,  
  16.                maxCorners,  
  17.                qualityLevel,  
  18.                minDistance,  
  19.                Mat(),  
  20.                blockSize,  
  21.                useHarrisDetector,  
  22.                k );  
  23.   /// Draw corners detected  
  24.   for( int i = 0; i < corners.size(); i++ ){   
  25.       circle( dst_norm_scaled,  corners[i], 5,  Scalar(255), 2, 8, 0 );   
  26.       circle( src, corners[i], 4, Scalar(0,255,0), 2, 8, 0 );   
  27.   }  
  28.   
  29.   /// Show what you got  
  30.   imshow( corners_window, dst_norm_scaled );  
  31.   imshow( source_window, src );    
  32. }  

 
 

实践

在主函数中定义两个进度条方便调整阈值:

[cpp] view plaincopy
 
 
  1. namedWindow( source_window, CV_WINDOW_AUTOSIZE );  
  2. createTrackbar( "Threshold: ", source_window, &thresh, max_thresh, cornerHarris_demo );  
  3. createTrackbar( "Max  corners:", source_window, &maxCorners, maxTrackbar, cornerShiTomasi_demo );    
  4.   
  5. namedWindow( corners_window, CV_WINDOW_AUTOSIZE );  
  6. namedWindow( source_window, CV_WINDOW_AUTOSIZE );  
  7. imshow( source_window, src );    
  8.   
  9. cornerHarris_demo( 0, 0 );  
  10. cornerShiTomasi_demo( 0, 0 );  


这里还需要说的是OpenCV 2.4.2中给的角点检测跟踪的示例代码有些问题,是应为SURF等不再定义在 feature2d模块中,而是legacy和nonfree,所以需要加入引用:

[cpp] view plaincopy
 
 
  1. #include "opencv2/legacy/legacy.hpp"  
  2. #include "opencv2/nonfree/nonfree.hpp"  

 

角点检测结果:

蓝色实心点为Harris检测结果,绿色空心圈为goodFeaturetoTrack检测结果。

M特征值分解后每个像素点相减的图(也就是Harris阈值判断的图)如下:

黑色实心点为Harris阈值检测结果,白色空心圈为阈值为27时Shi-Tomasi检测结果。

转载请注明出处:http://blog.csdn.net/xiaowei_cqu/article/details/7805206
源码及资料下载: http://download.csdn.net/detail/xiaowei_cqu/4466627

参考资料:

[1] Shi and C. Tomasi. Good Features to Track. Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition, pages 593-600, June 1994.

[2] Richard Szeliski. Computer Vision: Algorithms and Applications. Springer, New York, 2010.

[3] 图像特征点提取PPT http://wenku.baidu.com/view/f61bc369561252d380eb6ef0.html