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

Posted 进击的小猴子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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("\\n\\n\\n\\t\\t\\t【欢迎来到Harris角点检测示例程序~】\\n\\n");
    printf("\\n\\n\\n\\t请调整滚动条观察图像效果~\\n\\n");
    printf("\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t by浅墨");
}


void main()
{
    system("color 3F");
    ShowHelpText();

    //载入原始图并进行克隆保存  
    g_srcImage = imread("E://1.jpg", 1);
    if (!g_srcImage.data) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \\n"); 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 << "\\t>此次检测到的角点数量为:" << 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("\\n\\n\\t\\t\\t非常感谢购买《OpenCV3编程入门》一书!\\n");
    printf("\\n\\n\\t\\t\\t此为本书OpenCV2版的第87个配套示例程序\\n");
    printf("\\n\\n\\t\\t\\t   当前使用的OpenCV版本为:" CV_VERSION);
    printf("\\n\\n  ----------------------------------------------------------------------------\\n");
    //输出一些帮助信息
    printf("\\n\\n\\n\\t欢迎来到【Shi-Tomasi角点检测】示例程序\\n");
    printf("\\n\\t请调整滑动条观察图像效果\\n\\n");

}

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);
}

 

以上是关于opencv学习之路(32)角点检测的主要内容,如果未能解决你的问题,请参考以下文章

opencv学习-Harris角点检测

OpenCV角点检测源代码分析(Harris和ShiTomasi角点)

OpenCV亚像素级的角点检测

OpenCV——Harris角点检测

OpenCV ⚠️高手勿入! 半小时学会基本操作 23⚠️ 角点检测

OpenCV ⚠️高手勿入! 半小时学会基本操作 23⚠️ 角点检测