• opencv学习之路(32)、角点检测


     一、角点检测的相关概念

    二、Harris角点检测——cornerHarris()

    参考网址: http://www.cnblogs.com/ronny/p/4009425.html

     

    #include "opencv2/opencv.hpp"
    #include<iostream>
    using namespace std;
    using namespace cv;
    
    void main()
    {
        Mat img = imread("E://3.jpg");
        imshow("src", img);
        Mat result = img.clone();
        Mat gray, dst , corner_img;//corner_img存放检测后的角点图像
        cvtColor(img, gray, CV_BGR2GRAY);
    
        cornerHarris(gray, corner_img, 2, 3, 0.04);//cornerHarris角点检测
        //imshow("corner", corner_img);
        threshold(corner_img, dst, 0.015, 255, CV_THRESH_BINARY);
        imshow("dst", dst);
    
        int rowNumber = gray.rows;  //获取行数
        int colNumber = gray.cols;  //获取每一行的元素
        cout << rowNumber << endl;
        cout << colNumber << endl;
        cout << dst.type() << endl;
    
        for (int i = 0; i<rowNumber; i++)
        {
            for (int j = 0; j<colNumber; j++)
            {
                if (dst.at<float>(i, j) == 255)//二值化后,灰度值为255为角点
                {
                    circle(result, Point(j, i),3, Scalar(0, 255, 0), 2, 8);
                }
            }
        }
    
        imshow("result", result);
        waitKey(0);
    }

    浅墨代码

    http://blog.csdn.net/poem_qianmo/article/details/29356187

    #include "opencv2/opencv.hpp"
    #include<iostream>
    using namespace std;
    using namespace cv;
    
    #define WINDOW_NAME1 "【程序窗口1】"       
    #define WINDOW_NAME2 "【程序窗口2】"         
    Mat g_srcImage, g_srcImage1, g_grayImage;
    int thresh = 30; //当前阈值  
    int max_thresh = 175; //最大阈值  
    
    void on_CornerHarris(int, void*)
    {
        Mat dstImage;//目标图  
        Mat normImage;//归一化后的图  
        Mat scaledImage;//线性变换后的八位无符号整型的图  
    
        //初始化:置零当前需要显示的两幅图,即清除上一次调用此函数时他们的值  
        dstImage = Mat::zeros(g_srcImage.size(), CV_32FC1);
        g_srcImage1 = g_srcImage.clone();
    
        //进行角点检测  
        cornerHarris(g_grayImage, dstImage, 2, 3, 0.04);
        // 归一化与转换  
        normalize(dstImage, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
        convertScaleAbs(normImage, scaledImage);//将归一化后的图线性变换成8位无符号整型   
    
        // 进行绘制:将检测到的,且符合阈值条件的角点绘制出来  
        for (int j = 0; j < normImage.rows; j++)
        {
            for (int i = 0; i < normImage.cols; i++)
            {
                if ((int)normImage.at<float>(j, i) > thresh + 80)
                {
                    circle(g_srcImage1, Point(i, j), 5, Scalar(10, 10, 255), 2, 8, 0);
                    circle(scaledImage, Point(i, j), 5, Scalar(0, 10, 255), 2, 8, 0);
                }
            }
        }
        imshow(WINDOW_NAME1, g_srcImage1);
        imshow(WINDOW_NAME2, scaledImage);
    
    }
    
    static void ShowHelpText()
    {
        printf("
    
    
    			【欢迎来到Harris角点检测示例程序~】
    
    ");
        printf("
    
    
    	请调整滚动条观察图像效果~
    
    ");
        printf("
    
    								 by浅墨");
    }
    
    
    void main()
    {
        system("color 3F");
        ShowHelpText();
    
        //载入原始图并进行克隆保存  
        g_srcImage = imread("E://1.jpg", 1);
        if (!g_srcImage.data) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! 
    "); return ; }
        imshow("原始图", g_srcImage);
        g_srcImage1 = g_srcImage.clone();
        cvtColor(g_srcImage1, g_grayImage, CV_BGR2GRAY);
    
        //创建窗口和滚动条  
        namedWindow(WINDOW_NAME1, CV_WINDOW_NORMAL);
        createTrackbar("阈值: ", WINDOW_NAME1, &thresh, max_thresh, on_CornerHarris);
        on_CornerHarris(0, 0);//调用一次回调函数,进行初始化
        
        waitKey(0);
    }

    三、Shi-Tomasi角点检测——goodFeaturesToTrack()

    #include "opencv2/opencv.hpp"
    #include<iostream>
    using namespace std;
    using namespace cv;
    
    void main()
    {
        Mat src = imread("E://0.jpg");
        imshow("src", src);
        Mat result = src.clone();
        Mat gray;
        cvtColor(src, gray,CV_BGR2GRAY);
        
        vector<Point2f>corners;//Point2f类型的向量:存储每个角点的坐标
        //输入图,向量,最大角点数量,角点的最小特征值,角点间最小距离,掩码(Mat()表示掩码为空),blocksize,是否使用Harris角点检测,权重系数
        goodFeaturesToTrack(gray, corners, 100,0.01,10,Mat(),3,false,0.04);
        cout << "角点数量" << corners.size() << endl;
    
        //画圆标注角点
        for (int i = 0; i < corners.size(); i++)
            circle(result, corners[i], 5, Scalar(0, 255, 0),2,8);
        imshow("result", result);
        waitKey(0);
    }
     

    浅墨大神代码(加了滑动条效果)

    #include "opencv2/opencv.hpp"
    #include <iostream>
    using namespace cv;
    using namespace std;
    
    #define WINDOW_NAME "【Shi-Tomasi角点检测】" 
    Mat g_srcImage, g_grayImage;
    int g_maxCornerNumber = 33;
    int g_maxTrackbarNumber = 500;
    RNG g_rng(12345);//初始化随机数生成器
    
    
                     //-----------------------------【on_GoodFeaturesToTrack( )函数】----------------------------
                     //          描述:响应滑动条移动消息的回调函数
                     //----------------------------------------------------------------------------------------------
    void on_GoodFeaturesToTrack(int, void*)
    {
        //【1】对变量小于等于1时的处理
        if (g_maxCornerNumber <= 1) { g_maxCornerNumber = 1; }
    
        //【2】Shi-Tomasi算法(goodFeaturesToTrack函数)的参数准备
        vector<Point2f> corners;
        double qualityLevel = 0.01;//角点检测可接受的最小特征值
        double minDistance = 10;//角点之间的最小距离
        int blockSize = 3;//计算导数自相关矩阵时指定的邻域范围
        double k = 0.04;//权重系数
        Mat copy = g_srcImage.clone();    //复制源图像到一个临时变量中,作为感兴趣区域
    
                                        //【3】进行Shi-Tomasi角点检测
        goodFeaturesToTrack(g_grayImage,//输入图像
            corners,//检测到的角点的输出向量
            g_maxCornerNumber,//角点的最大数量
            qualityLevel,//角点检测可接受的最小特征值
            minDistance,//角点之间的最小距离
            Mat(),//感兴趣区域
            blockSize,//计算导数自相关矩阵时指定的邻域范围
            false,//不使用Harris角点检测
            k);//权重系数
    
    
               //【4】输出文字信息
        cout << "	>此次检测到的角点数量为:" << corners.size() << endl;
    
        //【5】绘制检测到的角点
        int r = 4;
        for (int i = 0; i < corners.size(); i++)
        {
            //以随机的颜色绘制出角点
            circle(copy, corners[i], r, Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255),
                g_rng.uniform(0, 255)), -1, 8, 0);
        }
    
        //【6】显示(更新)窗口
        imshow(WINDOW_NAME, copy);
    }
    
    static void ShowHelpText()
    {
        //输出欢迎信息和OpenCV版本
        printf("
    
    			非常感谢购买《OpenCV3编程入门》一书!
    ");
        printf("
    
    			此为本书OpenCV2版的第87个配套示例程序
    ");
        printf("
    
    			   当前使用的OpenCV版本为:" CV_VERSION);
        printf("
    
      ----------------------------------------------------------------------------
    ");
        //输出一些帮助信息
        printf("
    
    
    	欢迎来到【Shi-Tomasi角点检测】示例程序
    ");
        printf("
    	请调整滑动条观察图像效果
    
    ");
    
    }
    
    void main()
    {
        system("color 2F");
        ShowHelpText();
    
        //【1】载入源图像并将其转换为灰度图
        g_srcImage = imread("3.jpg", 1);
        cvtColor(g_srcImage, g_grayImage, CV_BGR2GRAY);
    
        //【2】创建窗口和滑动条,并进行显示和回调函数初始化
        namedWindow(WINDOW_NAME, CV_WINDOW_AUTOSIZE);
        createTrackbar("最大角点数", WINDOW_NAME, &g_maxCornerNumber, g_maxTrackbarNumber, on_GoodFeaturesToTrack);
        imshow(WINDOW_NAME, g_srcImage);
        on_GoodFeaturesToTrack(0, 0);
    
        waitKey(0);
    }

    由于VS2015和opencv2有些兼容问题,会出现断言错误(具体原因在上一篇博客有讲),这里就不贴效果图了。

    四、亚像素角点检测——cornerSubPix()

    #include "opencv2/opencv.hpp"
    #include<iostream>
    using namespace std;
    using namespace cv;
    
    void main()
    {
        Mat img = imread("E://2.jpg");
        imshow("src", img);
        Mat result = img.clone();
        Mat gray;
        cvtColor(img, gray, CV_BGR2GRAY);
    
        //Shi-Tomasi角点检测
        vector<Point2f> corners;
        goodFeaturesToTrack(gray, corners, 100, 0.01, 10, Mat(), 3, false, 0.04);
        cout << "角点数量" << corners.size() << endl;
    
        for (int i = 0; i<corners.size(); i++)
        {
            cout << "像素坐标:(" << corners[i].x << ", " << corners[i].y << ")" << endl;
            circle(result, corners[i], 5, Scalar(0, 255, 0), 2, 8);
        }
        imshow("result", result);
    
        Size winSize = Size(5, 5);
        Size zeroZone = Size(-1, -1);
                                            //精度或最大迭代数目,其中任意一个达到  迭代次数40,精度0.001
        TermCriteria criteria = TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 40, 0.001);
        cornerSubPix(gray, corners, winSize, zeroZone, criteria);
    
        for (int j = 0; j<corners.size(); j++)
        {
            cout << "亚像素坐标:(" << corners[j].x << ", " << corners[j].y << ")" << endl;
            circle(img, corners[j], 5, Scalar(0, 255, 0), -1, 8);
        }
        imshow("subPix", img);
    
        waitKey(0);
    }

  • 相关阅读:
    工作中遇到新知识应该怎么办
    Java中的集合
    JSTL学习(二)自定义标签库
    别跟我扯依赖注入
    经典算法的分析
    Debian
    C 底层细节【转】
    C文件操作 【转】
    利用strstr和sscanf解析GPS信息
    算法学习建议 ACM()转
  • 原文地址:https://www.cnblogs.com/little-monkey/p/7608427.html
Copyright © 2020-2023  润新知