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类
- #ifndef HARRIS_H
- #define HARRIS_H
- #include "opencv2/opencv.hpp"
-
- class harris
- {
- private:
- cv::Mat cornerStrength;
- cv::Mat cornerTh;
- cv::Mat localMax;
- int neighbourhood;
- int aperture;
- double k;
- double maxStrength;
- double threshold;
- int nonMaxSize;
- cv::Mat kernel;
- public:
- harris():neighbourhood(3),aperture(3),k(0.01),maxStrength(0.0),threshold(0.01),nonMaxSize(3){
-
- };
-
- void setLocalMaxWindowsize(int nonMaxSize){
- this->nonMaxSize = nonMaxSize;
- };
-
-
- void detect(const cv::Mat &image){
-
- cv::cornerHarris (image,cornerStrength,neighbourhood,aperture,k);
- double minStrength;
-
- cv::minMaxLoc (cornerStrength,&minStrength,&maxStrength);
-
- cv::Mat dilated;
-
-
- cv::dilate (cornerStrength,dilated,cv::Mat());
-
- cv::compare(cornerStrength,dilated,localMax,cv::CMP_EQ);
- }
-
-
- cv::Mat getCornerMap(double qualityLevel) {
- cv::Mat cornerMap;
-
- threshold= qualityLevel*maxStrength;
- cv::threshold(cornerStrength,cornerTh,
- threshold,255,cv::THRESH_BINARY);
-
- cornerTh.convertTo(cornerMap,CV_8U);
-
- cv::bitwise_and(cornerMap,localMax,cornerMap);
- return cornerMap;
- }
-
- void getCorners(std::vector<cv::Point> &points,
- double qualityLevel) {
-
- cv::Mat cornerMap= getCornerMap(qualityLevel);
-
- getCorners(points, cornerMap);
- }
-
-
- void getCorners(std::vector<cv::Point> &points,
- const cv::Mat& cornerMap) {
-
- for( int y = 0; y < cornerMap.rows; y++ ) {
- const uchar* rowPtr = cornerMap.ptr<uchar>(y);
- for( int x = 0; x < cornerMap.cols; x++ ) {
-
- if (rowPtr[x]) {
- points.push_back(cv::Point(x,y));
- }
- }
- }
- }
-
-
- void drawOnImage(cv::Mat &image,
- const std::vector<cv::Point> &points,
- cv::Scalar color= cv::Scalar(255,255,255),
- int radius=3, int thickness=2) {
- std::vector<cv::Point>::const_iterator it=points.begin();
- while (it!=points.end()) {
-
- cv::circle(image,*it,radius,color,thickness);
- ++it;
- }
- }
-
- };
-
- #endif // HARRIS_H
相关测试代码:- cv::Mat image, image1 = cv::imread ("test.jpg");
-
- cv::cvtColor (image1,image,CV_BGR2GRAY);
-
-
-
- harris Harris;
-
- Harris.detect(image);
-
- std::vector<cv::Point> pts;
- Harris.getCorners(pts,0.01);
-
- Harris.drawOnImage(image,pts);
-
- cv::namedWindow ("harris");
- cv::imshow ("harris",image);
- cv::waitKey (0);
- return 0;
相关测试结果:
三、改进的Harris角点检测
从经典的Harris角点检测方法不难看出,该算法的稳定性和k有关,而k是个经验值,不好把握,浮动也有可能较大。鉴于此,改进的Harris方法()直接计算出两个特征值,通过比较两个特征值直接分类,这样就不用计算Harris响应函数了。
另一方面,我们不再用非极大值抑制了,而选取容忍距离:容忍距离内只有一个特征点。
该算法首先选取一个具有最大 最小特征值的点(即:max(min(e1,e2)),e1,e2是harris矩阵的特征值)作为角点,然后依次按照最大最小特征值顺序寻找余下的角点,当然和前一角点距离在容忍距离内的新角点呗忽略。
opencv测试该算法代码如下:
- cv::Mat image, image1 = cv::imread ("test.jpg");
-
- cv::cvtColor (image1,image,CV_BGR2GRAY);
-
- std::vector<cv::Point> corners;
- cv::goodFeaturesToTrack(image,corners,
- 200,
-
- 0.01,
-
- 10);
-
- harris().drawOnImage(image,corners);
测试结果如下:
四、FAST角点检测
算法原理比较简单,但实时性很强。
该算法的角点定义为:若某像素点圆形邻域圆周上有3/4的点和该像素点不同(编程时不超过某阈值th),则认为该点就是候选角点。opencv更极端,选用半径为3的圆周上(上下左右)四个点,若超过三个点和该像素点不同,则该点为候选角点。
和Harris算法类似,该算法需要非极大值抑制。
opencv代码:
- cv::Mat image, image1 = cv::imread ("test.jpg");
- cv::cvtColor (image1,image,CV_BGR2GRAY);
-
- std::vector<cv::KeyPoint> keypoints;
- cv::FastFeatureDetector fast(40,true);
- fast .detect (image,keypoints);
- cv::drawKeypoints (image,keypoints,image,cv::Scalar::all(255),cv::DrawMatchesFlags::DRAW_OVER_OUTIMG);
测试结果如下:
本文作者附:百度文库中有个详细介绍上面公式意义的:
PPT链接地址
0 0