本篇文章中,我们一起探讨了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梯度的协方差矩阵,接着它计算如下式子:

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

其函数原型和参数解析:

[cpp] view plaincopy print?
  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( )函数也可以达到此目的) 或者是去掉噪声,例如过滤很小或很大象素值的图像点。

[cpp] view plaincopy print?
  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( )函数支持的对图像取阈值的方法由其确定,具体用法如下图:

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

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

[cpp] view plaincopy print?
  1. //-----------------------------------【头文件包含部分】---------------------------------------
  2. //      描述:包含程序所依赖的头文件
  3. //----------------------------------------------------------------------------------------------
  4. #include <opencv2/opencv.hpp>
  5. #include <opencv2/imgproc/imgproc.hpp>
  6. //-----------------------------------【命名空间声明部分】---------------------------------------
  7. //      描述:包含程序所使用的命名空间
  8. //-----------------------------------------------------------------------------------------------
  9. using namespace cv;
  10. int main()
  11. {
  12. //以灰度模式载入图像并显示
  13. Mat srcImage = imread("1.jpg", 0);
  14. imshow("原始图", srcImage);
  15. //进行Harris角点检测找出角点
  16. Mat cornerStrength;
  17. cornerHarris(srcImage, cornerStrength, 2, 3, 0.01);
  18. //对灰度图进行阈值操作,得到二值图并显示
  19. Mat harrisCorner;
  20. threshold(cornerStrength, harrisCorner, 0.00001, 255, THRESH_BINARY);
  21. imshow("角点检测后的二值效果图", harrisCorner);
  22. waitKey(0);
  23. return 0;
  24. }

运行截图:

   

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

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

6.1 OpenCV2.X中cornerHarris函数源代码

源码路径: …opencv\sources\modules\imgproc\src\corner.cpp

[cpp] view plaincopy print?
  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函数,我们看看其实现源码:

[cpp] view plaincopy print?
  1. static void
  2. cornerEigenValsVecs( const Mat& src,Mat& eigenv, int block_size,
  3. int aperture_size, intop_type, double k=0.,
  4. intborderType=BORDER_DEFAULT )
  5. {
  6. #ifdef HAVE_TEGRA_OPTIMIZATION
  7. if (tegra::cornerEigenValsVecs(src, eigenv, block_size, aperture_size,op_type, k, borderType))
  8. return;
  9. #endif
  10. int depth = src.depth();
  11. double scale = (double)(1 << ((aperture_size > 0 ?aperture_size : 3) - 1)) * block_size;
  12. if( aperture_size < 0 )
  13. scale *= 2.;
  14. if( depth == CV_8U )
  15. scale *= 255.;
  16. scale = 1./scale;
  17. CV_Assert( src.type() == CV_8UC1 || src.type() == CV_32FC1 );
  18. Mat Dx, Dy;
  19. if( aperture_size > 0 )
  20. {
  21. Sobel( src, Dx, CV_32F, 1, 0, aperture_size, scale, 0, borderType );
  22. Sobel( src, Dy, CV_32F, 0, 1, aperture_size, scale, 0, borderType );
  23. }
  24. else
  25. {
  26. Scharr( src, Dx, CV_32F, 1, 0, scale, 0, borderType );
  27. Scharr( src, Dy, CV_32F, 0, 1, scale, 0, borderType );
  28. }
  29. Size size = src.size();
  30. Mat cov( size, CV_32FC3 );
  31. int i, j;
  32. for( i = 0; i < size.height; i++ )
  33. {
  34. float* cov_data = (float*)(cov.data + i*cov.step);
  35. const float* dxdata = (const float*)(Dx.data + i*Dx.step);
  36. const float* dydata = (const float*)(Dy.data + i*Dy.step);
  37. for( j = 0; j < size.width; j++ )
  38. {
  39. float dx = dxdata[j];
  40. float dy = dydata[j];
  41. cov_data[j*3] = dx*dx;
  42. cov_data[j*3+1] = dx*dy;
  43. cov_data[j*3+2] = dy*dy;
  44. }
  45. }
  46. boxFilter(cov, cov, cov.depth(), Size(block_size, block_size),
  47. Point(-1,-1), false, borderType );
  48. if( op_type == MINEIGENVAL )
  49. calcMinEigenVal( cov, eigenv );
  50. else if( op_type == HARRIS )
  51. calcHarris( cov, eigenv, k );
  52. else if( op_type == EIGENVALSVECS )
  53. calcEigenValsVecs( cov, eigenv );
  54. }
  55. }

6.1 OpenCV2.X中Threshold函数源代码

路径:…opencv\sources\modules\imgproc\src\thresh.cpp

[cpp] view plaincopy print?
  1. double cv::threshold( InputArray _src,OutputArray _dst, double thresh, double maxval, int type )
  2. {
  3. Mat src = _src.getMat();
  4. bool use_otsu = (type & THRESH_OTSU) != 0;
  5. type &= THRESH_MASK;
  6. if( use_otsu )
  7. {
  8. CV_Assert( src.type() == CV_8UC1 );
  9. thresh = getThreshVal_Otsu_8u(src);
  10. }
  11. _dst.create( src.size(), src.type() );
  12. Mat dst = _dst.getMat();
  13. if( src.depth() == CV_8U )
  14. {
  15. int ithresh = cvFloor(thresh);
  16. thresh = ithresh;
  17. int imaxval = cvRound(maxval);
  18. if( type == THRESH_TRUNC )
  19. imaxval = ithresh;
  20. imaxval = saturate_cast<uchar>(imaxval);
  21. if( ithresh < 0 || ithresh >= 255 )
  22. {
  23. if( type == THRESH_BINARY || type == THRESH_BINARY_INV ||
  24. ((type == THRESH_TRUNC || type== THRESH_TOZERO_INV) && ithresh < 0) ||
  25. (type == THRESH_TOZERO&& ithresh >= 255) )
  26. {
  27. int v = type ==THRESH_BINARY ? (ithresh >= 255 ? 0 : imaxval) :
  28. type ==THRESH_BINARY_INV ? (ithresh >= 255 ? imaxval : 0) :
  29. /*type == THRESH_TRUNC? imaxval :*/ 0;
  30. dst.setTo(v);
  31. }
  32. else
  33. src.copyTo(dst);
  34. return thresh;
  35. }
  36. thresh = ithresh;
  37. maxval = imaxval;
  38. }
  39. else if( src.depth() == CV_16S )
  40. {
  41. int ithresh = cvFloor(thresh);
  42. thresh = ithresh;
  43. int imaxval = cvRound(maxval);
  44. if( type == THRESH_TRUNC )
  45. imaxval = ithresh;
  46. imaxval = saturate_cast<short>(imaxval);
  47. if( ithresh < SHRT_MIN || ithresh >= SHRT_MAX )
  48. {
  49. if( type == THRESH_BINARY || type == THRESH_BINARY_INV ||
  50. ((type == THRESH_TRUNC || type== THRESH_TOZERO_INV) && ithresh < SHRT_MIN) ||
  51. (type == THRESH_TOZERO&& ithresh >= SHRT_MAX) )
  52. {
  53. int v = type == THRESH_BINARY ?(ithresh >= SHRT_MAX ? 0 : imaxval) :
  54. type == THRESH_BINARY_INV ?(ithresh >= SHRT_MAX ? imaxval : 0) :
  55. /*type == THRESH_TRUNC ?imaxval :*/ 0;
  56. dst.setTo(v);
  57. }
  58. else
  59. src.copyTo(dst);
  60. return thresh;
  61. }
  62. thresh = ithresh;
  63. maxval = imaxval;
  64. }
  65. else if( src.depth() == CV_32F )
  66. ;
  67. else
  68. CV_Error( CV_StsUnsupportedFormat, "" );
  69. parallel_for_(Range(0, dst.rows),
  70. ThresholdRunner(src, dst,thresh, maxval, type),
  71. dst.total()/(double)(1<<16));
  72. return thresh;
  73. }

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

[cpp] view plaincopy print?
  1. void cv::adaptiveThreshold( InputArray_src, OutputArray _dst, double maxValue,
  2. int method, inttype, int blockSize, double delta )
  3. {
  4. Mat src = _src.getMat();
  5. CV_Assert( src.type() == CV_8UC1 );
  6. CV_Assert( blockSize % 2 == 1 && blockSize > 1 );
  7. Size size = src.size();
  8. _dst.create( size, src.type() );
  9. Mat dst = _dst.getMat();
  10. if( maxValue < 0 )
  11. {
  12. dst = Scalar(0);
  13. return;
  14. }
  15. Mat mean;
  16. if( src.data != dst.data )
  17. mean = dst;
  18. if( method == ADAPTIVE_THRESH_MEAN_C )
  19. boxFilter( src, mean, src.type(), Size(blockSize, blockSize),
  20. Point(-1,-1), true,BORDER_REPLICATE );
  21. else if( method == ADAPTIVE_THRESH_GAUSSIAN_C )
  22. GaussianBlur( src, mean, Size(blockSize, blockSize), 0, 0,BORDER_REPLICATE );
  23. else
  24. CV_Error( CV_StsBadFlag, "Unknown/unsupported adaptive thresholdmethod" );
  25. int i, j;
  26. uchar imaxval = saturate_cast<uchar>(maxValue);
  27. int idelta = type == THRESH_BINARY ? cvCeil(delta) : cvFloor(delta);
  28. uchar tab[768];
  29. if( type == CV_THRESH_BINARY )
  30. for( i = 0; i < 768; i++ )
  31. tab[i] = (uchar)(i - 255 > -idelta ? imaxval : 0);
  32. else if( type == CV_THRESH_BINARY_INV )
  33. for( i = 0; i < 768; i++ )
  34. tab[i] = (uchar)(i - 255 <= -idelta ? imaxval : 0);
  35. else
  36. CV_Error( CV_StsBadFlag, "Unknown/unsupported threshold type");
  37. if( src.isContinuous() && mean.isContinuous() &&dst.isContinuous() )
  38. {
  39. size.width *= size.height;
  40. size.height = 1;
  41. }
  42. for( i = 0; i < size.height; i++ )
  43. {
  44. const uchar* sdata = src.data + src.step*i;
  45. const uchar* mdata = mean.data + mean.step*i;
  46. uchar* ddata = dst.data + dst.step*i;
  47. for( j = 0; j < size.width; j++ )
  48. ddata[j] = tab[sdata[j] - mdata[j] + 255];
  49. }
  50. }

七、综合示例部分

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

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

[cpp] view plaincopy print?
  1. //-----------------------------------【程序说明】----------------------------------------------
  2. //      程序名称::《【OpenCV入门教程之十六】OpenCV角点检测之Harris角点检测》 博文配套源码
  3. //      开发所用IDE版本:Visual Studio 2010
  4. //      开发所用OpenCV版本:   2.4.9
  5. //      2014年6月8日 Created by 浅墨
  6. //      浅墨的微博:@浅墨_毛星云 http://weibo.com/1723155442
  7. //      浅墨的知乎:http://www.zhihu.com/people/mao-xing-yun
  8. //      浅墨的豆瓣:http://www.douban.com/people/53426472/
  9. //----------------------------------------------------------------------------------------------
  10. //-----------------------------------【头文件包含部分】---------------------------------------
  11. //      描述:包含程序所依赖的头文件
  12. //----------------------------------------------------------------------------------------------
  13. #include <opencv2/opencv.hpp>
  14. #include "opencv2/highgui/highgui.hpp"
  15. #include "opencv2/imgproc/imgproc.hpp"
  16. //-----------------------------------【命名空间声明部分】--------------------------------------
  17. //      描述:包含程序所使用的命名空间
  18. //-----------------------------------------------------------------------------------------------
  19. using namespace cv;
  20. using namespace std;
  21. //-----------------------------------【宏定义部分】--------------------------------------------
  22. //  描述:定义一些辅助宏
  23. //------------------------------------------------------------------------------------------------
  24. #define WINDOW_NAME1 "【程序窗口1】"        //为窗口标题定义的宏
  25. #define WINDOW_NAME2 "【程序窗口2】"        //为窗口标题定义的宏
  26. //-----------------------------------【全局变量声明部分】--------------------------------------
  27. //      描述:全局变量声明
  28. //-----------------------------------------------------------------------------------------------
  29. Mat g_srcImage, g_srcImage1,g_grayImage;
  30. int thresh = 30; //当前阈值
  31. int max_thresh = 175; //最大阈值
  32. //-----------------------------------【全局函数声明部分】--------------------------------------
  33. //      描述:全局函数声明
  34. //-----------------------------------------------------------------------------------------------
  35. void on_CornerHarris( int, void* );//回调函数
  36. static void ShowHelpText();
  37. //-----------------------------------【main( )函数】--------------------------------------------
  38. //      描述:控制台应用程序的入口函数,我们的程序从这里开始执行
  39. //-----------------------------------------------------------------------------------------------
  40. int main( int argc, char** argv )
  41. {
  42. //【0】改变console字体颜色
  43. system("color 3F");
  44. //【0】显示帮助文字
  45. ShowHelpText();
  46. //【1】载入原始图并进行克隆保存
  47. g_srcImage = imread( "1.jpg", 1 );
  48. if(!g_srcImage.data ) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); return false; }
  49. imshow("原始图",g_srcImage);
  50. g_srcImage1=g_srcImage.clone( );
  51. //【2】存留一张灰度图
  52. cvtColor( g_srcImage1, g_grayImage, CV_BGR2GRAY );
  53. //【3】创建窗口和滚动条
  54. namedWindow( WINDOW_NAME1, CV_WINDOW_AUTOSIZE );
  55. createTrackbar( "阈值: ", WINDOW_NAME1, &thresh, max_thresh, on_CornerHarris );
  56. //【4】调用一次回调函数,进行初始化
  57. on_CornerHarris( 0, 0 );
  58. waitKey(0);
  59. return(0);
  60. }
  61. //-----------------------------------【on_HoughLines( )函数】--------------------------------
  62. //      描述:回调函数
  63. //----------------------------------------------------------------------------------------------
  64. void on_CornerHarris( int, void* )
  65. {
  66. //---------------------------【1】定义一些局部变量-----------------------------
  67. Mat dstImage;//目标图
  68. Mat normImage;//归一化后的图
  69. Mat scaledImage;//线性变换后的八位无符号整型的图
  70. //---------------------------【2】初始化---------------------------------------
  71. //置零当前需要显示的两幅图,即清除上一次调用此函数时他们的值
  72. dstImage = Mat::zeros( g_srcImage.size(), CV_32FC1 );
  73. g_srcImage1=g_srcImage.clone( );
  74. //---------------------------【3】正式检测-------------------------------------
  75. //进行角点检测
  76. cornerHarris( g_grayImage, dstImage, 2, 3, 0.04, BORDER_DEFAULT );
  77. // 归一化与转换
  78. normalize( dstImage, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );
  79. convertScaleAbs( normImage, scaledImage );//将归一化后的图线性变换成8位无符号整型
  80. //---------------------------【4】进行绘制-------------------------------------
  81. // 将检测到的,且符合阈值条件的角点绘制出来
  82. for( int j = 0; j < normImage.rows ; j++ )
  83. { for( int i = 0; i < normImage.cols; i++ )
  84. {
  85. if( (int) normImage.at<float>(j,i) > thresh+80 )
  86. {
  87. circle( g_srcImage1, Point( i, j ), 5,  Scalar(10,10,255), 2, 8, 0 );
  88. circle( scaledImage, Point( i, j ), 5,  Scalar(0,10,255), 2, 8, 0 );
  89. }
  90. }
  91. }
  92. //---------------------------【4】显示最终效果---------------------------------
  93. imshow( WINDOW_NAME1, g_srcImage1 );
  94. imshow( WINDOW_NAME2, scaledImage );
  95. }
  96. //-----------------------------------【ShowHelpText( )函数】----------------------------------
  97. //      描述:输出一些帮助信息
  98. //----------------------------------------------------------------------------------------------
  99. static void ShowHelpText()
  100. {
  101. //输出一些帮助信息
  102. printf("\n\n\n\t\t\t【欢迎来到Harris角点检测示例程序~】\n\n");
  103. printf("\n\n\n\t请调整滚动条观察图像效果~\n\n");
  104. printf("\n\n\t\t\t\t\t\t\t\t by浅墨"
  105. );
  106. }

放出一些运行效果图。

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

第一组阈值效果图:

 

第二组阈值效果图:

 

第三组阈值效果图:

 

第四组阈值效果图:

 

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

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

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

OpenCV角点检测之Harris角点检测相关推荐

  1. OpenCV与图像处理学习十三——Harris角点检测(含代码)

    OpenCV与图像处理学习十三--Harris角点检测(含代码) 一.角点的概念 二.Harris角点检测的实现过程 三.Harris代码应用 一.角点的概念 角点: 在现实世界中, 角点对应于物体的 ...

  2. 【理解】经典角点检测算法--Harris角点

    目录 什么是角点 角点检测算法的原始思想: Harris角点检测原理 Harris角点算法的基本步骤 实践: Harris角点检测可能会用到的OpenCV API: 手写API: 1.展示图片: 2. ...

  3. 角点检测--基于梯度的方法(Moravec角点检测、Harris角点检测、Shi-Tomasi角点检测)

    Moravec Detector Moravec角点检测是第一个提出兴趣点(interest points)的Paper.它的主要思想是:以每个像素为中心,有一个固定的滑动窗口.该方法计算并在八个方向 ...

  4. OpenCV —— 角点检测之 Harris 角点检测、Shi-Tomasi 角点检测、FAST 角点检测

    角点检测 Harris 角点检测 实现原理 OpenCV 函数 优化 Shi-Tomasi 角点检测 实现原理 OpenCV 函数 FAST 角点检测 实现原理 OpenCV 函数 优化 在图像处理和 ...

  5. OpenCV入门学习笔记之Harris角点检测与SIFT特征匹配算法

    1. 写在前面 这篇文章整理两个图像处理中非常重要的算法,一个是Harris角点检测算法,另一个是SIFT特征匹配算法,这两个算法本质上还是去找图像里面的关键特征点,帮助我们后续更好的理解图像以及做各 ...

  6. 角点检测:Harris角点及Shi-Tomasi角点检测

    角点 特征检测与匹配是Computer Vision 应用总重要的一部分,这需要寻找图像之间的特征建立对应关系.点,也就是图像中的特殊位置,是很常用的一类特征,点的局部特征也可以叫做"关键特 ...

  7. 角点检测(Harris角点检测法)

    博主联系方式: QQ:1540984562 QQ交流群:892023501 群里会有往届的smarters和电赛选手,群里也会不时分享一些有用的资料,有问题可以在群里多问问. 目录 原理讲解 [1]为 ...

  8. 测角误差估计算法matlab,Harris角点检测 及 Matlab实验

    目录 1 基础知识 1.1 图像变化的类型 1.2 提取点特征的作用 1.3 什么是好的角点检测算法? 2 Harris 角点检测 2.1 Harris角点检测基本思想 2.2 Harris角点检测: ...

  9. 计算机视觉——harris角点检测之harris角点响应函数R

    文章目录 一.harris角点检测原理 1.1基本思想 1.2 数学模型 3.关于harris角点响应函数R 二.harris角点检测源代码 2.1 计算harris角点响应函数R 2.2harris ...

最新文章

  1. everything文件搜索_本地文件搜索神器,Everything、Listary、AnyTXT Searcher!
  2. python方法重写_python 怎样实现重写
  3. C 线程的使用~(上)
  4. 补习系列-springboot-使用assembly进行项目打包
  5. JAXB处理java对象与xml格式之间的转换
  6. 修改sharepoint列表样式
  7. GD32Pack包下载地址
  8. oracle exadata X8,ORACLEEXADATA数据库云服务器X8.PDF
  9. java ftl_.ftl文件 是什么文件 freemaker
  10. php imagick 教程,php imagick蒙版做法
  11. 写给大家看的设计书阅读笔记1——设计的四大基本原则
  12. 升级glibc经验谈!!!
  13. 对创建的screen会话进行恢复时出现:There is no screen to be resumed matching XXX 解决办法
  14. LaTeX写一份完整的物理实验报告
  15. AirPods 2支持无限充电只要15分钟充满
  16. Java题目汇总(二)
  17. github clone 代码到本地全步骤
  18. Linux系统中rpm命令安装软件,报错:This program may be freely redistributed under the terms of the GNU GPL
  19. C#面向对象的UML工具:StarUML介绍和入门使用
  20. CAN Bus cable simulation

热门文章

  1. 将xap包嵌入到博客园中
  2. 运算符优先级和结合性
  3. Spring Cloud构建微服务架构-Hystrix依赖隔离
  4. Docker学习总结(6)——通过 Docker 化一个博客网站来开启我们的 Docker 之旅
  5. hdu 1233 还是畅通工程 Kruskal 最小生成树 并查集
  6. CentOS5.8下varnish-2.1.5的安装配置
  7. 2009.5.23软考_系统分析师 上午试题 答案 讨论
  8. ServiceStack.OrmLite使用
  9. 大数据与智能算法(一-基础技术)-SMU在线学习笔记
  10. CentOS创建快捷按钮并设置文件图标