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),接着它计算如下式子:
这里写图片描述
即可以找出输出图中的局部最大值,即找出了角点。
函数原型和参数解析:

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

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南山二毛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值