加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Opencv学习笔记五:harris角点特征提取

(2017-03-09 17:04:35)
分类: 上下求索
1、前两天分别使用了SIFT、SURF、ORB实现特征匹配,这三种方法SURF方法效果较优,但是比较耗时,使用Harris方法进行改进测试,效果和SURF方法可以向媲美,并且测试用一幅图像,匹配时间提高了接近3/4,由时间1000ms多提速到250ms左右。
2、在Opencv中有三种方法实现:
1> opencv自带的函数检测角点特征,其检测效果与k值有关,需要经验设置;
2> 改进后的角点检测,受k值影响不大;
3> 使用fastDetector方法,此方法检测速度快,匹配效果好。
如下列代码实现,三种方法,分别通过设置nMethod方法实现:
int nMethod = 2;

    if (nMethod == 0)    // 使用opencv自带的函数检测,检测角点数与k值有关

    {

        // opencv自带的角点响应函数计算

        Mat matCornerStrength // opencv函数检测结果,也就是每个像素的角点响应函数值

        int nBlockSize = 3, nKSize = 3;

        double dK = 0.01;

        cv::cornerHarris(matSrc, matCornerStrength, nBlockSize, nKSize, dK);

 

        // 计算最小最大响应值

        double dMinStrength = 0.0, dMaxStrength = 0.0;

        cv::minMaxLoc(matCornerStrength, &dMinStrength, &dMaxStrength);

 

        // 默认3*3核膨胀,膨胀之后,除了局部最大值点和原来相同,其他非局部最大值点

        // 3*3邻域内的最大值点取代

        Mat matDilated;

        Mat matKernel = Mat();       // 最大值抑制的核,也就是膨胀用到的核

        cv::dilate(matCornerStrength, matDilated, matKernel);

 

        // 和原图相比,只剩下和原图值相同的点,这些点都是局部最大值点,保存到matLocalMax

        Mat matLocalMax    // 局部最大值结果

        cv::compare(matCornerStrength, matDilated, matLocalMax, cv::CMP_EQ);

 

        double dQulityLevel = 0.1;

        // 根据角点响应最大值计算阈值

        double dThreshold = dQulityLevel * dMaxStrength;

        Mat matCornerTh    // matCornerStrength阈值化后的结果

        cv::threshold(matCornerStrength, matCornerTh, dThreshold, 255, cv::THRESH_BINARY);

 

        // 转化为8bit

        Mat matCornerMap;

        matCornerTh.convertTo(matCornerMap, CV_8U);

 

        // 和局部最大值图比,剩下角点局部最大值图,即:完成非最大值抑制

        cv::bitwise_and(matCornerMap, matLocalMax, matCornerMap);

 

        // 获取角点,遍历全图

        std::vector<</span>Point2f> vtPoints;

        for (int y = 0; y < matCornerMap.rows; y++)

        {

             const uchar *pRowPtr = matCornerMap.ptr<</span>uchar>(y);

             for (int x = 0; x < matCornerMap.cols; x++)

             {

                 if (pRowPtr[x])

                 {

                     vtPoints.push_back(cv::Point2f(x, y));

                 }

             }

        }

 

        cv::KeyPoint::convert(vtPoints, vtCorners, 1, 1, 0, -1);

    }

    else if(nMethod == 1)    // 改进的harris方法

    {

        // 直接计算两个特征值,通过比较两个特征值进行分类,不在使用极大值抑制的方法

        // 选取容忍距离:容忍距离内只有一个特征点

        // 首先选取一个具有最大最小特征值的点(即:max(min(e1, e2)), e1e2harris矩阵的特征值)作为角点

        // 然后依次按照最大最小特征值顺序寻找余下的角点,当然和前一角点距离在容忍距离内的新角点被忽略

        int nMaxNum = 200;   // 角点最大数目

        double dQuality = 0.01; // 质量等级,这里是0.01*max(min(e1, e2)),e1e2harris矩阵的特征值

        double dMinDistance = 10;    // 两个角点之间的容忍度

        int nBlockSize = 3;

        double dK = 0.04;

        std::vector<</span>Point2f> vtPoints;

        cv::goodFeaturesToTrack(matSrc, vtPoints, nMaxNum, dQuality, dMinDistance, Mat(), nBlockSize, false, dK);

        cv::KeyPoint::convert(vtPoints, vtCorners, 1, 1, 0, -1);

    }

    else if (nMethod == 2)       // fast Harris方法

    {

        // 原理:若像素点圆形领域圆周上有3/4的点和该像素点不同(编程时不超过某阈值th),则认为该点就是候选角点

        // opencv内选用半径为3的圆周上(上下左右)四个点,若超过三个点和该像素点不同,则该点为候选角点

        // 该算法需要非极大值抑制

        int nThreshold = 20;

        cv::Ptr<</span>Feature2D> fastDetector = cv::FastFeatureDetector::create(nThreshold, true);

        fastDetector->detect(matSrc, vtCorners);

    }

3、结果测试,分别包括时间和特征点匹配效果,FastFeatrueDetctor效果较好,时间较短,暂时选择此特征匹配方法:

http://s12/mw690/003eu7RDzy79n1CpDB14b&690


http://s10/mw690/003eu7RDzy79n1CvZrz29&690

http://s15/mw690/003eu7RDzy79n1CCTmu9e&690

http://s5/mw690/003eu7RDzy79n1CFQoI04&690


http://s10/mw690/003eu7RDzy79n1V47K9d9&690

http://s15/mw690/003eu7RDzy79n1V6C9o5e&690


0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有