OpenCV学习25--Harris角点检测

在图像处理和与计算机视觉领域,兴趣点(interest points),或称作关键点(keypoints)、特征点(feature points) 被大量用于解决物体识别,图像识别、图像匹配、视觉跟踪、三维重建等一系列的问题。我们不再观察整幅图,而是选择某些特殊的点,然后对他们进行局部有的放矢的分析。如果能检测到足够多的这种点,同时他们的区分度很高,并且可以精确定位稳定的特征,那么这个方法就有使用价值。


图像特征类型可以被分为如下三种:


<1>边缘

<2>角点 (感兴趣关键点)

<3>斑点(Blobs)(感兴趣区域)


其中,角点是个很特殊的存在。他们在图像中可以轻易地定位,同时,他们在人造物体场景,比如门、窗、桌等出随处可见。因为角点位于两条边缘的交点处,代表了两个边缘变化的方向上的点,,所以他们是可以精确定位的二维特征,甚至可以达到亚像素的精度。且其图像梯度有很高的变化,这种变化是可以用来帮助检测角点的。需要注意的是,角点与位于相同强度区域上的点不同,与物体轮廓上的点也不同,因为轮廓点难以在相同的其他物体上精确定位。


在当前的图像处理领域,角点检测算法可归纳为三类:


<1>基于灰度图像的角点检测

<2>基于二值图像的角点检测

<3>基于轮廓曲线的角点检测

而基于灰度图像的角点检测又可分为基于梯度、基于模板和基于模板梯度组合三类方法,其中基于模板的方法主要考虑像素领域点的灰度变化,即图像亮度的变化,将与邻点亮度对比足够大的点定义为角点。常见的基于模板的角点检测算法有Kitchen-Rosenfeld角点检测算法,Harris角点检测算法、KLT角点检测算法及SUSAN角点检测算法。和其他角点检测算法相比,SUSAN角点检测算法具有算法简单、位置准确、抗噪声能力强等特点。

角点通常被定义为两条边的交点,更严格的说,角点的局部邻域应该具有两个不同区域的不同方向的边界。而实际应用中,大多数所谓的角点检测方法检测的是拥有特定特征的图像点,而不仅仅是“角点”。这些特征点在图像中有具体的坐标,并具有某些数学特征,如局部最大或最小灰度、某些梯度特征等。


关于角点的具体描述可以有几种:

一阶导数(即灰度的梯度)的局部最大所对应的像素点;

两条及两条以上边缘的交点;

图像中梯度值和梯度方向的变化速率都很高的点;

角点处的一阶导数最大,二阶导数为零,指示物体边缘变化不连续的方向。


ornerHarris 函数对于每一个像素(x,y)在blockSize x blockSize 邻域内,计算2x2梯度的协方差矩阵M(x,y),接着它计算如下式子:

image.png

即可以找出输出图中的局部最大值,即找出了角点。
函数原型和参数解析:

void cornerHarris(InputArray src,OutputArray dst, int blockSize, int ksize, 
double k, intborderType=BORDER_DEFAULT )

第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位或者浮点型图像。

第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放Harris角点检测的输出结果,和源图片有一样的尺寸和类型。

第三个参数,int类型的blockSize,表示邻域的大小,更多的详细信息在cornerEigenValsAndVecs()中有讲到。

第四个参数,int类型的ksize,表示Sobel()算子的孔径大小。

第五个参数,double类型的k,Harris参数。

第六个参数,int类型的borderType,图像像素的边界模式,注意它有默认值BORDER_DEFAULT。更详细的解释,参考borderInterpolate( )函数。

完整源代码:

//-----------------------------------【头文件包含部分】---------------------------------------  
//      描述:包含程序所依赖的头文件  
//----------------------------------------------------------------------------------------------   
#include <opencv2/opencv.hpp>  
#include "opencv2/highgui/highgui.hpp"  
#include "opencv2/imgproc/imgproc.hpp"  

//-----------------------------------【命名空间声明部分】--------------------------------------  
//      描述:包含程序所使用的命名空间  
//-----------------------------------------------------------------------------------------------   
using namespace cv;  
using namespace std;  

//-----------------------------------【宏定义部分】--------------------------------------------    
//  描述:定义一些辅助宏    
//------------------------------------------------------------------------------------------------    
#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* );//回调函数  
static void ShowHelpText();  

//-----------------------------------【main( )函数】--------------------------------------------  
//      描述:控制台应用程序的入口函数,我们的程序从这里开始执行  
//-----------------------------------------------------------------------------------------------  
int main( int argc, char** argv )  
{  
    //【0】改变console字体颜色  
    system("color 3F");    

    //【0】显示帮助文字  
    ShowHelpText();  

    //【1】载入原始图并进行克隆保存  
    g_srcImage = imread( "1.jpg", 1 );  
     if(!g_srcImage.data ) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); return false; }    
     imshow("原始图",g_srcImage);  
    g_srcImage1=g_srcImage.clone( );  

    //【2】存留一张灰度图  
    cvtColor( g_srcImage1, g_grayImage, CV_BGR2GRAY );  

    //【3】创建窗口和滚动条  
    namedWindow( WINDOW_NAME1, CV_WINDOW_AUTOSIZE );  
    createTrackbar( "阈值: ", WINDOW_NAME1, &thresh, max_thresh, on_CornerHarris );  

    //【4】调用一次回调函数,进行初始化  
    on_CornerHarris( 0, 0 );  

    waitKey(0);  
    return(0);  
}  

//-----------------------------------【on_HoughLines( )函数】--------------------------------  
//      描述:回调函数  
//----------------------------------------------------------------------------------------------  

void on_CornerHarris( int, void* )  
{  
    //---------------------------【1】定义一些局部变量-----------------------------  
    Mat dstImage;//目标图  
    Mat normImage;//归一化后的图  
    Mat scaledImage;//线性变换后的八位无符号整型的图  

    //---------------------------【2】初始化---------------------------------------  
    //置零当前需要显示的两幅图,即清除上一次调用此函数时他们的值  
    dstImage = Mat::zeros( g_srcImage.size(), CV_32FC1 );  
    g_srcImage1=g_srcImage.clone( );  

    //---------------------------【3】正式检测-------------------------------------  
    //进行角点检测  
    cornerHarris( g_grayImage, dstImage, 2, 3, 0.04, BORDER_DEFAULT );  

    // 归一化与转换  
    normalize( dstImage, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );  
    convertScaleAbs( normImage, scaledImage );//将归一化后的图线性变换成8位无符号整型   

    //---------------------------【4】进行绘制-------------------------------------  
    // 将检测到的,且符合阈值条件的角点绘制出来  
    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 );  
        }  
    }  
    }  
    //---------------------------【4】显示最终效果---------------------------------  
    imshow( WINDOW_NAME1, g_srcImage1 );  
    imshow( WINDOW_NAME2, scaledImage );  

}  

//-----------------------------------【ShowHelpText( )函数】----------------------------------  
//      描述:输出一些帮助信息  
//----------------------------------------------------------------------------------------------  
static void ShowHelpText()  
{  
    //输出一些帮助信息  
    printf("\n\n\n\t\t\t【欢迎来到Harris角点检测示例程序~】\n\n");    
    printf("\n\n\n\t请调整滚动条观察图像效果~\n\n");   
}


————————————————

版权声明:本文为CSDN博主「南山二毛」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/qq_16481211/article/details/79633979



本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864