目标检测之harr---角点检测harr 的opencv实现

  • 本系列文章由@浅墨_毛星云 出品,转载请注明出处。

    文章链接: http://blog.csdn.net/poem_qianmo/article/details/29356187

    作者:毛星云(浅墨) 微博:http://weibo.com/u/1723155442

    知乎:http://www.zhihu.com/people/mao-xing-yun

    邮箱: [email protected]

    写作当前博文时配套使用的OpenCV版本: 2.4.9

    本篇文章中,我们一起探讨了OpenCV中Harris角点检测相关的知识点,学习了OpenCV中实现Harris角点检测的cornerHarris函数的使用方法。此博文一共有两个配套的麻雀虽小但五脏俱全的示例程序,其经过浅墨详细注释过的代码都在文中贴出,且文章最后提供了综合示例程序的下载。

    依然是先看看程序运行截图:

     

    一、引言:关于兴趣点(interest points)

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

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

    <1>边缘<2>角点 (感兴趣关键点)<3>斑点(Blobs)(感兴趣区域)

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

    二、角点检测算法的分类

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

    <1>基于灰度图像的角点检测<2>基于二值图像的角点检测<3>基于轮廓曲线的角点检测

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

    三、角点的定义

    “如果某一点在任意方向的一个微小变动都会引起灰度很大的变化,那么我们就把它称之为角点”

    角点检测(Corner Detection)是计算机视觉系统中用来获得图像特征的一种方法,广泛应用于运动检测、图像匹配、视频跟踪、三维建模和目标识别等领域中。也称为特征点检测。

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

    现有的角点检测算法并不是都十分的健壮。很多方法都要求有大量的训练集和冗余数据来防止或减少错误特征的出现。另外,角点检测方法的一个很重要的评价标准是其对多幅图像中相同或相似特征的检测能力,并且能够应对光照变化、图像旋转等图像变化。

    在我们解决问题时,往往希望找到特征点,“特征”顾名思义,指能描述物体本质的东西,还有一种解释就是这个特征微小的变化都会对物体的某一属性产生重大的影响。而角点就是这样的特征。

    观察日常生活中的“角落”就会发现,“角落”可以视为所有平面的交汇处,或者说是所有表面的发起处。假设我们要改变一个墙角的位置,那么由它而出发的平面势必都要有很大的变化。所以,这就引出了图像角点的定义。

    我们知道,特征检测与匹配是计算机视觉应用中非常重要的一部分,这需要寻找图像之间的特征建立对应关系。图像中的点作为图像的特殊位置,是很常用的一类特征,点的局部特征也可以叫做“关键特征点”(keypoint feature),或“兴趣点”(interest point),或“角点”(conrner)。

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

    一阶导数(即灰度的梯度)的局部最大所对应的像素点;两条及两条以上边缘的交点;图像中梯度值和梯度方向的变化速率都很高的点;角点处的一阶导数最大,二阶导数为零,指示物体边缘变化不连续的方向。

    四、cornerHarris函数详解

    cornerHarris 函数用于在OpenCV中运行Harris角点检测算子处理图像。和cornerMinEigenVal( )以及cornerEigenValsAndVecs( )函数类似,cornerHarris 函数对于每一个像素(x,y)在邻域内,计算2x2梯度的协方差矩阵,接着它计算如下式子:

    即可以找出输出图中的局部最大值,即找出了角点。

    其函数原型和参数解析:

    view sourceprint?

    1.C++: 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( )函数。

    接着我们一起过一遍稍后需要用到的Threshold函数的解析,然后看一个以cornerHarris为核心的示例程序。

    五、Threshold函数详解

    函数Threshold( ) 对单通道数组应用固定阈值操作。该函数的典型应用是对灰度图像进行阈值操作得到二值图像。(另外,compare( )函数也可以达到此目的) 或者是去掉噪声,例如过滤很小或很大象素值的图像点。

    view sourceprint?

    1.C++: double threshold(InputArray src,OutputArray dst, double thresh, double maxval, int type)

    第一个参数,InputArray类型的src,输入数组,填单通道 , 8或32位浮点类型的Mat即可。第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放输出结果,且和第一个参数中的Mat变量有一样的尺寸和类型。第三个参数,double类型的thresh,阈值的具体值。第四个参数,double类型的maxval,当第五个参数阈值类型type取 CV_THRESH_BINARY 或CV_THRESH_BINARY_INV 阈值类型时的最大值.第五个参数,int类型的type,阈值类型,。threshold( )函数支持的对图像取阈值的方法由其确定,具体用法如下图:

    而图形化的阈值描述如下图:

    讲解完这两个函数,让我们看一个调用示例程序:

    view sourceprint?

    01.//-----------------------------------【头文件包含部分】--------------------------------------- 

    02.//      描述:包含程序所依赖的头文件 

    03.//----------------------------------------------------------------------------------------------  

    04.#include <opencv2/opencv.hpp> 

    05.#include <opencv2/imgproc/imgproc.hpp> 

    06.

    07.//-----------------------------------【命名空间声明部分】--------------------------------------- 

    08.//      描述:包含程序所使用的命名空间 

    09.//-----------------------------------------------------------------------------------------------  

    10.using namespace cv; 

    11.

    12.int main() 

    13.

    14.//以灰度模式载入图像并显示

    15.Mat srcImage = imread("1.jpg"0); 

    16.imshow("原始图", srcImage); 

    17.

    18.//进行Harris角点检测找出角点

    19.Mat cornerStrength; 

    20.cornerHarris(srcImage, cornerStrength, 230.01);

    21.

    22.//对灰度图进行阈值操作,得到二值图并显示 

    23.Mat harrisCorner; 

    24.threshold(cornerStrength, harrisCorner, 0.00001255, THRESH_BINARY); 

    25.imshow("角点检测后的二值效果图", harrisCorner); 

    26.

    27.waitKey(0); 

    28.return 0

    29.}

    运行截图:

     

    六、本文相关核心函数在OpenCV中的实现源代码

    这个部分贴出OpenCV中本文相关函数的源码实现细节,来给想了解实现细节的小伙伴们参考。浅墨暂时不在源码的细节上挖深作详细注释。

    6.1 OpenCV2.X中cornerHarris函数源代码

    源码路径: …opencvsourcesmodulesimgprocsrccorner.cpp

    view sourceprint?

    1.void cv::cornerHarris( InputArray _src,OutputArray _dst, int blockSize, int ksize, double k, int borderType )

    2.{

    3.Mat src = _src.getMat();

    4._dst.create( src.size(), CV_32F );

    5.Mat dst = _dst.getMat();

    6.cornerEigenValsVecs( src, dst, blockSize, ksize, HARRIS, k, borderType);

    7.}

    可见cornerHarris内部其实是调用了cornerEigenValsVecs函数,我们看看其实现源码:

    view sourceprint?

    01.static void

    02.cornerEigenValsVecs( const Mat& src,Mat& eigenv, int block_size,

    03.int aperture_size, intop_type, double k=0.,

    04.intborderType=BORDER_DEFAULT )

    05.{

    06.#ifdef HAVE_TEGRA_OPTIMIZATION

    07.if (tegra::cornerEigenValsVecs(src, eigenv, block_size, aperture_size,op_type, k, borderType))

    08.return;

    09.#endif

    10.

    11.int depth = src.depth();

    12.double scale = (double)(1 << ((aperture_size > 0 ?aperture_size : 3) - 1)) * block_size;

    13.if( aperture_size < 0 )

    14.scale *= 2.;

    15.if( depth == CV_8U )

    16.scale *= 255.;

    17.scale = 1./scale;

    18.

    19.CV_Assert( src.type() == CV_8UC1 || src.type() == CV_32FC1 );

    20.

    21.Mat Dx, Dy;

    22.if( aperture_size > 0 )

    23.{

    24.Sobel( src, Dx, CV_32F, 10, aperture_size, scale, 0, borderType );

    25.Sobel( src, Dy, CV_32F, 01, aperture_size, scale, 0, borderType );

    26.}

    27.else

    28.{

    29.Scharr( src, Dx, CV_32F, 10, scale, 0, borderType );

    30.Scharr( src, Dy, CV_32F, 01, scale, 0, borderType );

    31.}

    32.

    33.Size size = src.size();

    34.Mat cov( size, CV_32FC3 );

    35.int i, j;

    36.

    37.for( i = 0; i < size.height; i++ )

    38.{

    39.float* cov_data = (float*)(cov.data + i*cov.step);

    40.const float* dxdata = (const float*)(Dx.data + i*Dx.step);

    41.const float* dydata = (const float*)(Dy.data + i*Dy.step);

    42.

    43.for( j = 0; j < size.width; j++ )

    44.{

    45.float dx = dxdata[j];

    46.float dy = dydata[j];

    47.

    48.cov_data[j*3] = dx*dx;

    49.cov_data[j*3+1] = dx*dy;

    50.cov_data[j*3+2] = dy*dy;

    51.}

    52.}

    53.

    54.boxFilter(cov, cov, cov.depth(), Size(block_size, block_size),

    55.Point(-1,-1), false, borderType );

    56.

    57.if( op_type == MINEIGENVAL )

    58.calcMinEigenVal( cov, eigenv );

    59.else if( op_type == HARRIS )

    60.calcHarris( cov, eigenv, k );

    61.else if( op_type == EIGENVALSVECS )

    62.calcEigenValsVecs( cov, eigenv );

    63.}

    64.

    65.}

    6.1 OpenCV2.X中Threshold函数源代码

    路径:…opencvsourcesmodulesimgprocsrc hresh.cpp

    view sourceprint?

    01.double cv::threshold( InputArray _src,OutputArray _dst, double thresh, double maxval, int type )

    02.{

    03.Mat src = _src.getMat();

    04.bool use_otsu = (type & THRESH_OTSU) != 0;

    05.type &= THRESH_MASK;

    06.

    07.if( use_otsu )

    08.{

    09.CV_Assert( src.type() == CV_8UC1 );

    10.thresh = getThreshVal_Otsu_8u(src);

    11.}

    12.

    13._dst.create( src.size(), src.type() );

    14.Mat dst = _dst.getMat();

    15.

    16.if( src.depth() == CV_8U )

    17.{

    18.int ithresh = cvFloor(thresh);

    19.thresh = ithresh;

    20.int imaxval = cvRound(maxval);

    21.if( type == THRESH_TRUNC )

    22.imaxval = ithresh;

    23.imaxval = saturate_cast<uchar>(imaxval);

    24.

    25.if( ithresh < 0 || ithresh >= 255 )

    26.{

    27.if( type == THRESH_BINARY || type == THRESH_BINARY_INV ||

    28.((type == THRESH_TRUNC || type== THRESH_TOZERO_INV) && ithresh < 0) ||

    29.(type == THRESH_TOZERO&& ithresh >= 255) )

    30.{

    31.int v = type ==THRESH_BINARY ? (ithresh >= 255 0 : imaxval) :

    32.type ==THRESH_BINARY_INV ? (ithresh >= 255 ? imaxval : 0) :

    33./*type == THRESH_TRUNC? imaxval :*/ 0;

    34.dst.setTo(v);

    35.}

    36.else

    37.src.copyTo(dst);

    38.return thresh;

    39.}

    40.thresh = ithresh;

    41.maxval = imaxval;

    42.}

    43.else if( src.depth() == CV_16S )

    44.{

    45.int ithresh = cvFloor(thresh);

    46.thresh = ithresh;

    47.int imaxval = cvRound(maxval);

    48.if( type == THRESH_TRUNC )

    49.imaxval = ithresh;

    50.imaxval = saturate_cast<short>(imaxval);

    51.

    52.if( ithresh < SHRT_MIN || ithresh >= SHRT_MAX )

    53.{

    54.if( type == THRESH_BINARY || type == THRESH_BINARY_INV ||

    55.((type == THRESH_TRUNC || type== THRESH_TOZERO_INV) && ithresh < SHRT_MIN) ||

    56.(type == THRESH_TOZERO&& ithresh >= SHRT_MAX) )

    57.{

    58.int v = type == THRESH_BINARY ?(ithresh >= SHRT_MAX ? 0 : imaxval) :

    59.type == THRESH_BINARY_INV ?(ithresh >= SHRT_MAX ? imaxval : 0) :

    60./*type == THRESH_TRUNC ?imaxval :*/ 0;

    61.dst.setTo(v);

    62.}

    63.else

    64.src.copyTo(dst);

    65.return thresh;

    66.}

    67.thresh = ithresh;

    68.maxval = imaxval;

    69.}

    70.else if( src.depth() == CV_32F )

    71.;

    72.else

    73.CV_Error( CV_StsUnsupportedFormat, "" );

    74.

    75.parallel_for_(Range(0, dst.rows),

    76.ThresholdRunner(src, dst,thresh, maxval, type),

    77.dst.total()/(double)(1<<16));

    78.return thresh;

    79.}

    另外在贴上与之相关的自适应阈值操作函数的源码adaptiveThreshold:

    view sourceprint?

    01.void cv::adaptiveThreshold( InputArray_src, OutputArray _dst, double maxValue,

    02.int method, inttype, int blockSize, double delta )

    03.{

    04.Mat src = _src.getMat();

    05.CV_Assert( src.type() == CV_8UC1 );

    06.CV_Assert( blockSize % 2 == 1 && blockSize > 1 );

    07.Size size = src.size();

    08.

    09._dst.create( size, src.type() );

    10.Mat dst = _dst.getMat();

    11.

    12.if( maxValue < 0 )

    13.{

    14.dst = Scalar(0);

    15.return;

    16.}

    17.

    18.Mat mean;

    19.

    20.if( src.data != dst.data )

    21.mean = dst;

    22.

    23.if( method == ADAPTIVE_THRESH_MEAN_C )

    24.boxFilter( src, mean, src.type(), Size(blockSize, blockSize),

    25.Point(-1,-1), true,BORDER_REPLICATE );

    26.else if( method == ADAPTIVE_THRESH_GAUSSIAN_C )

    27.GaussianBlur( src, mean, Size(blockSize, blockSize), 00,BORDER_REPLICATE );

    28.else

    29.CV_Error( CV_StsBadFlag, "Unknown/unsupported adaptive thresholdmethod" );

    30.

    31.int i, j;

    32.uchar imaxval = saturate_cast<uchar>(maxValue);

    33.int idelta = type == THRESH_BINARY ? cvCeil(delta) : cvFloor(delta);

    34.uchar tab[768];

    35.

    36.if( type == CV_THRESH_BINARY )

    37.for( i = 0; i < 768; i++ )

    38.tab[i] = (uchar)(i - 255 > -idelta ? imaxval : 0);

    39.else if( type == CV_THRESH_BINARY_INV )

    40.for( i = 0; i < 768; i++ )

    41.tab[i] = (uchar)(i - 255 <= -idelta ? imaxval : 0);

    42.else

    43.CV_Error( CV_StsBadFlag, "Unknown/unsupported threshold type");

    44.

    45.if( src.isContinuous() && mean.isContinuous() &&dst.isContinuous() )

    46.{

    47.size.width *= size.height;

    48.size.height = 1;

    49.}

    50.

    51.for( i = 0; i < size.height; i++ )

    52.{

    53.const uchar* sdata = src.data + src.step*i;

    54.const uchar* mdata = mean.data + mean.step*i;

    55.uchar* ddata = dst.data + dst.step*i;

    56.

    57.for( j = 0; j < size.width; j++ )

    58.ddata[j] = tab[sdata[j] - mdata[j] + 255];

    59.}

    60.}

    七、综合示例部分

    本次综合示例为调节滚动条来控制阈值,以控制的harris检测角点的数量。一共有三个图片窗口,分别为显示原始图的窗口,包含滚动条的彩色效果图窗口,以及灰度图效果图窗口。

    废话不多说,让我们一起来欣赏详细注释过后的完整源代码:

    view sourceprint?

    001.//-----------------------------------【程序说明】----------------------------------------------

    002.//      程序名称::《【OpenCV入门教程之十六】OpenCV角点检测之Harris角点检测》 博文配套源码

    003.//      开发所用IDE版本:Visual Studio 2010

    004.//      开发所用OpenCV版本:   2.4.9

    005.//      2014年6月8日 Created by 浅墨

    006.//      浅墨的微博:@浅墨_毛星云 http://weibo.com/1723155442

    007.//      浅墨的知乎:http://www.zhihu.com/people/mao-xing-yun

    008.//      浅墨的豆瓣:http://www.douban.com/people/53426472/

    009.//----------------------------------------------------------------------------------------------

    010.

    011.//-----------------------------------【头文件包含部分】---------------------------------------

    012.//      描述:包含程序所依赖的头文件

    013.//----------------------------------------------------------------------------------------------

    014.#include <opencv2/opencv.hpp>

    015.#include "opencv2/highgui/highgui.hpp"

    016.#include "opencv2/imgproc/imgproc.hpp"

    017.

    018.//-----------------------------------【命名空间声明部分】--------------------------------------

    019.//      描述:包含程序所使用的命名空间

    020.//-----------------------------------------------------------------------------------------------

    021.using namespace cv;

    022.using namespace std;

    023.

    024.//-----------------------------------【宏定义部分】-------------------------------------------- 

    025.//  描述:定义一些辅助宏 

    026.//------------------------------------------------------------------------------------------------ 

    027.#define WINDOW_NAME1 "【程序窗口1】"        //为窗口标题定义的宏 

    028.#define WINDOW_NAME2 "【程序窗口2】"        //为窗口标题定义的宏 

    029.

    030.//-----------------------------------【全局变量声明部分】--------------------------------------

    031.//      描述:全局变量声明

    032.//-----------------------------------------------------------------------------------------------

    033.Mat g_srcImage, g_srcImage1,g_grayImage;

    034.int thresh = 30//当前阈值

    035.int max_thresh = 175//最大阈值

    036.

    037.

    038.//-----------------------------------【全局函数声明部分】--------------------------------------

    039.//      描述:全局函数声明

    040.//-----------------------------------------------------------------------------------------------

    041.void on_CornerHarris( intvoid* );//回调函数

    042.static void ShowHelpText();

    043.

    044.//-----------------------------------【main( )函数】--------------------------------------------

    045.//      描述:控制台应用程序的入口函数,我们的程序从这里开始执行

    046.//-----------------------------------------------------------------------------------------------

    047.int main( int argc, char** argv )

    048.{

    049.//【0】改变console字体颜色

    050.system("color 3F"); 

    051.

    052.//【0】显示帮助文字

    053.ShowHelpText();

    054.

    055.//【1】载入原始图并进行克隆保存

    056.g_srcImage = imread( "1.jpg"1 );

    057.if(!g_srcImage.data ) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~!

    058."); return false; } 

    059.imshow("原始图",g_srcImage);

    060.g_srcImage1=g_srcImage.clone( );

    061.

    062.//【2】存留一张灰度图

    063.cvtColor( g_srcImage1, g_grayImage, CV_BGR2GRAY );

    064.

    065.//【3】创建窗口和滚动条

    066.namedWindow( WINDOW_NAME1, CV_WINDOW_AUTOSIZE );

    067.createTrackbar( "阈值: ", WINDOW_NAME1, &thresh, max_thresh, on_CornerHarris );

    068.

    069.//【4】调用一次回调函数,进行初始化

    070.on_CornerHarris( 00 );

    071.

    072.waitKey(0);

    073.return(0);

    074.}

    075.

    076.//-----------------------------------【on_HoughLines( )函数】--------------------------------

    077.//      描述:回调函数

    078.//----------------------------------------------------------------------------------------------

    079.

    080.void on_CornerHarris( intvoid* )

    081.{

    082.//---------------------------【1】定义一些局部变量-----------------------------

    083.Mat dstImage;//目标图

    084.Mat normImage;//归一化后的图

    085.Mat scaledImage;//线性变换后的八位无符号整型的图

    086.

    087.//---------------------------【2】初始化---------------------------------------

    088.//置零当前需要显示的两幅图,即清除上一次调用此函数时他们的值

    089.dstImage = Mat::zeros( g_srcImage.size(), CV_32FC1 );

    090.g_srcImage1=g_srcImage.clone( );

    091.

    092.//---------------------------【3】正式检测-------------------------------------

    093.//进行角点检测

    094.cornerHarris( g_grayImage, dstImage, 230.04, BORDER_DEFAULT );

    095.

    096.// 归一化与转换

    097.normalize( dstImage, normImage, 0255, NORM_MINMAX, CV_32FC1, Mat() );

    098.convertScaleAbs( normImage, scaledImage );//将归一化后的图线性变换成8位无符号整型

    099.

    100.//---------------------------【4】进行绘制-------------------------------------

    101.// 将检测到的,且符合阈值条件的角点绘制出来

    102.forint j = 0; j < normImage.rows ; j++ )

    103.forint i = 0; i < normImage.cols; i++ )

    104.{

    105.if( (int) normImage.at<float>(j,i) > thresh+80 )

    106.{

    107.circle( g_srcImage1, Point( i, j ), 5,  Scalar(10,10,255), 280 );

    108.circle( scaledImage, Point( i, j ), 5,  Scalar(0,10,255), 280 );

    109.}

    110.}

    111.}

    112.//---------------------------【4】显示最终效果---------------------------------

    113.imshow( WINDOW_NAME1, g_srcImage1 );

    114.imshow( WINDOW_NAME2, scaledImage );

    115.

    116.}

    117.

    118.//-----------------------------------【ShowHelpText( )函数】----------------------------------

    119.//      描述:输出一些帮助信息

    120.//----------------------------------------------------------------------------------------------

    121.static void ShowHelpText()

    122.{

    123.//输出一些帮助信息

    124.printf("

    125.

    126.

    127.【欢迎来到Harris角点检测示例程序~】

    128.

    129."); 

    130.printf("

    131.

    132.

    133.请调整滚动条观察图像效果~

    134.

    135.");

    136.printf("

    137.

    138.by浅墨"

    139.);

    140.}

    放出一些运行效果图。

    首先是原始图,非常美丽的异域建筑群:

    第一组阈值效果图:

     

    第二组阈值效果图:

     

    第三组阈值效果图:

     

    第四组阈值效果图:

     

    本篇文章的配套源代码请点击这里下载:

    【浅墨OpenCV入门教程之十六】配套源代码下载

    OK,今天的内容大概就是这些,我们下篇文章见:)

延伸阅读:

http://blog.csdn.net/poem_qianmo/article/details/29356187 微软毛新云

http://www.cnblogs.com/doucontorl/archive/2011/01/02/1924157.html

http://www.it165.net/pro/html/201406/15260.html

http://www.360doc.com/content/11/1214/11/3054335_172134464.shtml  角点检测的几种办法

http://blog.csdn.net/liulina603/article/details/8649339 一维的harr小波变换

时间: 2024-07-29 22:59:37

目标检测之harr---角点检测harr 的opencv实现的相关文章

Emgucv使用Harris角点检测和Fast角点检测

角点是两个边缘的连接点,代表了两个边缘变化的方向上的点,在这点上图像梯度有很高的变化.是图像中的重要特征点.在opencv中还有改进版的Harris角点检测:Shi-Tomasi 角点检测算法,但在Emgucv里并没有封装,所以目前无法直接使用. 一.Harris角点检测 Harris角点检测通过判断点在水平和竖直方向上的变化程度来判断是否为角点,使用CornerHarris函数,处理后再用阈值来判断是否为角点. public partial class Form1 : Form { publi

15、角点检测之Harris角点检测

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

【opencv入门】角点检测之Harris角点检测

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

33、【opencv入门】角点检测之Harris角点检测

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

图像处理之角点检测与亚像素角点定位

角点是图像中亮度变化最强地方反映了图像的本质特征,提取图像中的角点可以有效提高图像处理速度与精准度.所以对于整张图像来说特别重要,角点检测与提取的越准确图像处理与分析结果就越接近真实.同时角点检测对真实环境下的对象识别.对象匹配都起到决定性作用.Harr角点检测是图像处理中角点提取的经典算法之一,应用范围广发,在经典的SIFT特征提取算法中Harr角点检测起到关键作用.通常对角点检测算法都有如下要求: 1. 基于灰度图像.能够自动调整运行稳定,检测出角点的数目. 2. 对噪声不敏感.有一定的噪声

角点检测方法

看了将近十来天的OPENCV了,无论是从官方文档,还是learning opencv,还是看各论坛,心里总有种感觉是:无法把自己看的知识联系在一起,感觉都是各有特色功能的函数,可是这些各有特色功能的函数怎么组合在一起,实现什么样的功能就不得而知了. 下面从角点的角度来讲讲吧  --(要说的是有些并非是本人所写,觉得别人有的地方写的经典就复制下来了) 使用函数 cornerHarris 通过 Harris-Stephens方法检测角点: 我们到底要角点干什么?????????????? 下面我来回

OpenCV探索之路(十五):角点检测

角点检测是计算机视觉系统中用来获取图像特征的一种方法.我们都常说,这幅图像很有特点,但是一问他到底有哪些特点,或者这幅图有哪些特征可以让你一下子就识别出该物体,你可能就说不出来了.其实说图像的特征,你可以尝试说一下这幅图有几个矩形啊几个圆形啊,有几条直线啊,当然啦,你也可以说一下有几个角点. 什么是角点? 角点通常被定义为两条边的交点.比如,三角形有三个角,矩形有四个角,这些就是角点,也是他们叫做矩形.三角形的特征,我们看到一些几何图形具有三个角,那么我们便可以脱口而出说这是一个三角形. 上面所

Harris角点及Shi-Tomasi角点检测(转)

一.角点定义 有定义角点的几段话: 1.角点检测(Corner Detection)是计算机视觉系统中用来获得图像特征的一种方法,广泛应用于运动检测.图像匹配.视频跟踪.三维建模和目标识别等领域中.也称为特征点检测. 角点通常被定义为两条边的交点,更严格的说,角点的局部邻域应该具有两个不同区域的不同方向的边界.而实际应用中,大多数所谓的角点检测方法检测的是拥有特定特征的图像点,而不仅仅是"角点".这些特征点在图像中有具体的坐标,并具有某些数学特征,如局部最大或最小灰度.某些梯度特征等.

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

OpenCV中常用的角点检测为Harris角点和ShiTomasi角点. 以OpenCV源代码文件 .\opencv\sources\samples\cpp\tutorial_code\TrackingMotion\cornerDetector_Demo.cpp为例,主要分析其中的这两种角点检测源代码.角点检测数学原理请参考我之前转载的一篇博客 http://www.cnblogs.com/riddick/p/7645904.html,分析的很详细,不再赘述.本文主要分析其源代码: 1. Har

第十一节、Harris角点检测原理

OpenCV可以检测图像的主要特征,然后提取这些特征.使其成为图像描述符,这类似于人的眼睛和大脑.这些图像特征可作为图像搜索的数据库.此外,人们可以利用这些关键点将图像拼接起来,组成一个更大的图像,比如将许多图像放在一块,然后形成一个360度全景图像. 这里我们将学习使用OpenCV来检测图像特征,并利用这些特征进行图像匹配和搜索.我们会选取一些图像,并通过单应性,检测这些图像是否在另一张图像中. 一 特征检测算法 有许多用于特征检测和提取的算法,我们将会对其中大部分进行介绍.OpenCV最常使