harris角点

来源:互联网 发布:yum 安装vim 编辑:程序博客网 时间:2024/05/22 04:53

文章目录:

一、Harris角点检测基本理论

二、opencv代码实现

三、改进的Harris角点检测

四、FAST角点检测

五、参考文献

六、附录(资料和源码)


一、Harris角点检测基本理论(要讲清楚东西太多,附录提供文档详细说明)

1.1 简略表达:

角点:最直观的印象就是在水平、竖直两个方向上变化均较大的点,即Ix、Iy都较大 
边缘:仅在水平、或者仅在竖直方向有较大的变化量,即Ix和Iy只有其一较大 
平坦地区:在水平、竖直方向的变化量均较小,即Ix、Iy都较小




角点响应

R=det(M)-k*(trace(M)^2)   (附录资料给出k=0.04~0.06,opencv指出是0.05-0.5,浮动较大)

det(M)=λ1*λ2      trace(M)=λ1+λ2

R取决于M的特征值,对于角点|R|很大,平坦的区域|R|很小,边缘的R为负值。


1.2 详细描述:见附录里的ppt

1.3 算法步骤



其中,局部极大值可用先膨胀后与原图比较的方法求得,具体见二中源码。


二、opencv代码实现

harris类

[cpp] view plain copy
  1. #ifndef HARRIS_H  
  2. #define HARRIS_H  
  3. #include "opencv2/opencv.hpp"  
  4.   
  5. class harris  
  6. {  
  7. private:  
  8.     cv::Mat  cornerStrength;  //opencv harris函数检测结果,也就是每个像素的角点响应函数值  
  9.     cv::Mat cornerTh; //cornerStrength阈值化的结果  
  10.     cv::Mat localMax; //局部最大值结果  
  11.     int neighbourhood; //邻域窗口大小  
  12.     int aperture;//sobel边缘检测窗口大小(sobel获取各像素点x,y方向的灰度导数)  
  13.     double k;  
  14.     double maxStrength;//角点响应函数最大值  
  15.     double threshold;//阈值除去响应小的值  
  16.     int nonMaxSize;//这里采用默认的3,就是最大值抑制的邻域窗口大小  
  17.     cv::Mat kernel;//最大值抑制的核,这里也就是膨胀用到的核  
  18. public:  
  19.     harris():neighbourhood(3),aperture(3),k(0.01),maxStrength(0.0),threshold(0.01),nonMaxSize(3){  
  20.   
  21.     };  
  22.   
  23.     void setLocalMaxWindowsize(int nonMaxSize){  
  24.         this->nonMaxSize = nonMaxSize;  
  25.     };  
  26.   
  27.     //计算角点响应函数以及非最大值抑制  
  28.     void detect(const cv::Mat &image){  
  29.             //opencv自带的角点响应函数计算函数  
  30.             cv::cornerHarris (image,cornerStrength,neighbourhood,aperture,k);  
  31.             double minStrength;  
  32.             //计算最大最小响应值  
  33.             cv::minMaxLoc (cornerStrength,&minStrength,&maxStrength);  
  34.   
  35.             cv::Mat dilated;  
  36.             //默认3*3核膨胀,膨胀之后,除了局部最大值点和原来相同,其它非局部最大值点被  
  37.             //3*3邻域内的最大值点取代  
  38.             cv::dilate (cornerStrength,dilated,cv::Mat());  
  39.             //与原图相比,只剩下和原图值相同的点,这些点都是局部最大值点,保存到localMax  
  40.             cv::compare(cornerStrength,dilated,localMax,cv::CMP_EQ);  
  41.     }  
  42.   
  43.     //获取角点图  
  44.     cv::Mat getCornerMap(double qualityLevel) {  
  45.             cv::Mat cornerMap;  
  46.             // 根据角点响应最大值计算阈值  
  47.             threshold= qualityLevel*maxStrength;  
  48.             cv::threshold(cornerStrength,cornerTh,  
  49.             threshold,255,cv::THRESH_BINARY);  
  50.             // 转为8-bit图  
  51.             cornerTh.convertTo(cornerMap,CV_8U);  
  52.             // 和局部最大值图与,剩下角点局部最大值图,即:完成非最大值抑制  
  53.             cv::bitwise_and(cornerMap,localMax,cornerMap);  
  54.             return cornerMap;  
  55.     }  
  56.   
  57.     void getCorners(std::vector<cv::Point> &points,  
  58.             double qualityLevel) {  
  59.             //获取角点图  
  60.             cv::Mat cornerMap= getCornerMap(qualityLevel);  
  61.             // 获取角点  
  62.             getCorners(points, cornerMap);  
  63.     }  
  64.   
  65.     // 遍历全图,获得角点  
  66.     void getCorners(std::vector<cv::Point> &points,  
  67.     const cv::Mat& cornerMap) {  
  68.   
  69.             forint y = 0; y < cornerMap.rows; y++ ) {  
  70.                     const uchar* rowPtr = cornerMap.ptr<uchar>(y);  
  71.                     forint x = 0; x < cornerMap.cols; x++ ) {  
  72.                     // 非零点就是角点  
  73.                           if (rowPtr[x]) {  
  74.                                 points.push_back(cv::Point(x,y));  
  75.                           }  
  76.                      }  
  77.                 }  
  78.           }  
  79.   
  80.     //用圈圈标记角点  
  81.     void drawOnImage(cv::Mat &image,  
  82.     const std::vector<cv::Point> &points,  
  83.             cv::Scalar color= cv::Scalar(255,255,255),  
  84.             int radius=3, int thickness=2) {  
  85.                     std::vector<cv::Point>::const_iterator it=points.begin();  
  86.                     while (it!=points.end()) {  
  87.                     // 角点处画圈  
  88.                     cv::circle(image,*it,radius,color,thickness);  
  89.                     ++it;  
  90.             }  
  91.     }  
  92.   
  93. };  
  94.   
  95. #endif // HARRIS_H  
相关测试代码:

[cpp] view plain copy
  1. cv::Mat  image, image1 = cv::imread ("test.jpg");  
  2.    //灰度变换  
  3.    cv::cvtColor (image1,image,CV_BGR2GRAY);  
  4.   
  5.   
  6.    // 经典的harris角点方法  
  7.    harris Harris;  
  8.    // 计算角点  
  9.    Harris.detect(image);  
  10.    //获得角点  
  11.    std::vector<cv::Point> pts;  
  12.    Harris.getCorners(pts,0.01);  
  13.    // 标记角点  
  14.    Harris.drawOnImage(image,pts);  
  15.   
  16.    cv::namedWindow ("harris");  
  17.    cv::imshow ("harris",image);  
  18.    cv::waitKey (0);  
  19.    return 0;  
相关测试结果:


三、改进的Harris角点检测

    从经典的Harris角点检测方法不难看出,该算法的稳定性和k有关,而k是个经验值,不好把握,浮动也有可能较大。鉴于此,改进的Harris方法()直接计算出两个特征值,通过比较两个特征值直接分类,这样就不用计算Harris响应函数了。

    另一方面,我们不再用非极大值抑制了,而选取容忍距离:容忍距离内只有一个特征点。
    该算法首先选取一个具有最大   最小特征值的点(即:max(min(e1,e2)),e1,e2是harris矩阵的特征值)作为角点,然后依次按照最大最小特征值顺序寻找余下的角点,当然和前一角点距离在容忍距离内的新角点呗忽略。

    opencv测试该算法代码如下:

[cpp] view plain copy
  1.     cv::Mat  image, image1 = cv::imread ("test.jpg");  
  2.     //灰度变换  
  3.     cv::cvtColor (image1,image,CV_BGR2GRAY);  
  4.     // 改进的harris角点检测方法  
  5.     std::vector<cv::Point> corners;  
  6.     cv::goodFeaturesToTrack(image,corners,  
  7.     200,  
  8.     //角点最大数目  
  9.     0.01,  
  10.     // 质量等级,这里是0.01*max(min(e1,e2)),e1,e2是harris矩阵的特征值  
  11.     10);  
  12.     // 两个角点之间的距离容忍度  
  13.     harris().drawOnImage(image,corners);//标记角点  
    测试结果如下:


四、FAST角点检测

    算法原理比较简单,但实时性很强。

    该算法的角点定义为:若某像素点圆形邻域圆周上有3/4的点和该像素点不同(编程时不超过某阈值th),则认为该点就是候选角点。opencv更极端,选用半径为3的圆周上(上下左右)四个点,若超过三个点和该像素点不同,则该点为候选角点。

    和Harris算法类似,该算法需要非极大值抑制。

opencv代码:

[cpp] view plain copy
  1. cv::Mat  image, image1 = cv::imread ("test.jpg");  
  2. cv::cvtColor (image1,image,CV_BGR2GRAY);  
  3. //快速角点检测  
  4. std::vector<cv::KeyPoint> keypoints;  
  5. cv::FastFeatureDetector fast(40,true);  
  6. fast .detect (image,keypoints);  
  7. cv::drawKeypoints (image,keypoints,image,cv::Scalar::all(255),cv::DrawMatchesFlags::DRAW_OVER_OUTIMG);  


测试结果如下:





本文作者附:百度文库中有个详细介绍上面公式意义的:

PPT链接地址



0 0
原创粉丝点击