绝点检测(1):Harris角点检测

一,兴趣点与角点;

二,角点检测;

三,harris角点检测;

四,实现Harris角点检测: cornerHarris()函数;

五,综合示例: harris角点检测与绘制;

一,兴趣点与角点

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

·边缘
      ·角点(感兴趣关键点)

·斑点(Blobs)(感兴趣区域)
       其中,角点是个很特殊的存在。如果某一点在任意方向的一个微小变动都会引起灰度很大的变化,那么我们就把它称之为角点。角点作为图像上的特征点,包含有重要的信息,在图像融合和目标跟踪及三维重建中有重要的应用价值。它们在图像中可以轻易地定位,同时,在人造物体场景,比如门、窗、桌等处也随处可见。因为角点位于两条边缘的交点处,代表了两个边缘变化的方向上的点,所以它们是可以精确定位的二维特征,甚至可以达到亚像素的精度。又由于其图像梯度有很高的变化,这种变化是可以用来帮助检测角点的。需要注意的是,角点与位于相同强度区域上的点不同,与物体轮廓上的点也不同,因为轮廓点难以在相同的其他物体上精确定位。
       另外,关于角点的具体描述可以有如下几种:
       一阶导数(即灰度的梯度)的局部最大所对应的像素点;

·两条及两条以上边缘的交点;
      ·图像中梯度值和梯度方向的变化速率都很高的点;
      ·角点处的一阶导数最大,二阶导数为零,它指示了物体边缘变化不连续的方向。

二,角点检测

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

·基于灰度图像的角点检测
      ·基于二值图像的角点检测·基于轮廓曲线的角点检测
        而基于灰度图像的角点检测又可分为基于梯度、基于模板和基于模板梯度组合三类方法。其中基于模板的方法主要考虑像素领域点的灰度变化,即图像亮度的变化,将与邻点亮度对比足够大的点定义为角点。常见的基于模板的角点检测算法有Kitchen-Rosenfeld 角点检测算法,Harris 角点检测算法、KLT角点检测算法及SUSAN角点检测算法。
        接下来,让我们一起来了解harris角点检测。

三,harris角点检测

harris角点检测是一种直接基于灰度图像的角点提取算法,稳定性高,尤其对L型角点检测精度高。但由于采用了高斯滤波,运算速度相对较慢,角点信息有丢失和位置偏移的现象,而且角点提取有聚簇现象。

四,实现Harris角点检测: cornerHarris()函数

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

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

·第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可,且须为单通道8位或者浮点型图像。
       ·第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放 Harris角点检测的输出结果,和源图片有一样的尺寸和类型。
       ·第三个参数,int类型的 blockSize,表示邻域的大小,更多详细信息在cornerEigen ValsAnd Vecs(中有讲到。
        第四个参数,int类型的ksize,表示 Sobel()算子的孔径大小。第五个参数,double类型的k,Harris参数。
       第六个参数,int类型的borderType,图像像素的边界模式。注意它有默认值BORDER_DEFAULT。更详细的解释,参考borderInterpolate()函数。

讲解完这个函数,我们看一个 Harris角点检测示例程序,其中还用到了之前讲到的threshold函数。

代码如下:

#include <opencv2/opencv.hpp>
#include<opencv2/core/core.hpp>
#include"opencv2/highgui/highgui.hpp"
#include<opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/utils/logger.hpp>
#include<iostream>
#include<time.h>
#include<vector>
using namespace std;
using namespace cv;int main()
{cv::utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);//控制台不在输出日志文件Mat srcImage = imread("E:/pictures/2.jpg", 0);imshow("原始图", srcImage);Mat cornerStrength;cornerHarris(srcImage, cornerStrength, 10, 3, 0.01);Mat harrisCorner;threshold(cornerStrength, harrisCorner, 0.00001, 255, THRESH_BINARY);imshow("角点检测后的效果图", harrisCorner);waitKey();return 0;
}

运行结果:

五,综合示例: harris角点检测与绘制

代码如下:

#include <opencv2/opencv.hpp>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <opencv2/core/utils/logger.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)
{cv::utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);//控制台不在输出日志文件//【0】改变console字体颜色system("color 3F");//【0】显示帮助文字ShowHelpText();//【1】载入原始图并进行克隆保存g_srcImage = imread("E:/pictures/3.2.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, COLOR_BGR2GRAY);//【3】创建窗口和滚动条namedWindow(WINDOW_NAME1, 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()
{//输出欢迎信息和OpenCV版本printf("\n\n\t\t\t   当前使用的OpenCV版本为:" CV_VERSION);printf("\n\n  ----------------------------------------------------------------------------\n");//输出一些帮助信息printf("\n\n\n\t【欢迎来到Harris角点检测示例程序~】\n\n");printf("\n\t请调整滚动条观察图像效果~\n\n");
}

运行结果:

OpenCV学习(76)相关推荐

  1. 【opencv学习笔记八】创建TrackBar轨迹条

    createTrackbar这个函数我们以后会经常用到,它创建一个可以调整数值的轨迹条,并将轨迹条附加到指定的窗口上,使用起来很方便.首先大家要记住,它往往会和一个回调函数配合起来使用.先看下他的函数 ...

  2. OpenCV 学习笔记03 boundingRect、minAreaRect、minEnclosingCircle、boxPoints、int0、circle、rectangle函数的用法...

    函数中的代码是部分代码,详细代码在最后 1 cv2.boundingRect 作用:矩形边框(boundingRect),用于计算图像一系列点的外部矩形边界. cv2.boundingRect(arr ...

  3. opencv学习笔记(二):基于肤色的人手检测

    opencv学习笔记(二):基于肤色的人手检测 原文:http://blog.csdn.net/wzmsltw/article/details/50849810 先写了人手的检测程序,下一步基于检测程 ...

  4. Python+OpenCV学习(17)---摄像机标定

    Python+OpenCV学习(17)---摄像机标定 原文:http://blog.csdn.net/firemicrocosm/article/details/48594897 利用python学 ...

  5. OpenCV学习之六: 使用方向梯度直方图估计图像旋转角度

    OpenCV学习之六: 使用方向梯度直方图估计图像旋转角度 原文:http://blog.csdn.net/zhjm07054115/article/details/26964275 下面的代码通过计 ...

  6. python做直方图-python OpenCV学习笔记实现二维直方图

    本文介绍了python OpenCV学习笔记实现二维直方图,分享给大家,具体如下: 官方文档 – https://docs.opencv.org/3.4.0/dd/d0d/tutorial_py_2d ...

  7. OpenCV学习--saturate_cast防止数据溢出

    在OpenCV学习中经常看见saturate_cast的使用,下面的代码会展示它的作用,详细的代码可以参见文章http://blog.csdn.net/mjlsuccess/article/detai ...

  8. OpenCV学习笔记大集锦

    转载自: OpenCV学习笔记大集锦 – 视觉机器人 http://www.cvrobot.net/collect-opencv-resource-learn-study-note-chinese/ ...

  9. OpenCV学习笔记(五十六)——InputArray和OutputArray的那些事core OpenCV学习笔记(五十七)——在同一窗口显示多幅图片 OpenCV学习笔记(五十八)——读《Mast

    OpenCV学习笔记(五十六)--InputArray和OutputArray的那些事core 看过OpenCV源代码的朋友,肯定都知道很多函数的接口都是InputArray或者OutputArray ...

  10. OpenCV学习笔记(五十一)——imge stitching图像拼接stitching OpenCV学习笔记(五十二)——号外:OpenCV 2.4.1 又出来了。。。。。 OpenCV学习笔记(五

    OpenCV学习笔记(五十一)--imge stitching图像拼接stitching stitching是OpenCV2.4.0一个新模块,功能是实现图像拼接,所有的相关函数都被封装在Stitch ...

最新文章

  1. PyTorch: 序列到序列模型(Seq2Seq)实现机器翻译实战
  2. Oracke nls Parameters
  3. 如何成为linux内核维护人员,Linux内核维护人员Greg Kroah-Hartman拒绝明尼苏达大学的道歉...
  4. 再见,2014;你好2015
  5. 读《构建之法》13--17章有感
  6. Windows下VTK6.0.0安装详解(CMake使用说明)
  7. 【暴力】I Liked Matrix!
  8. 基于jQuery焦点图片新闻代码(JS+CSS)
  9. idea中配置maven仓库
  10. java中==与equals的区别及理解_Java开发中常量池的理解与归纳
  11. react入门(一)
  12. t_user is not mapped [from t_user as u where u.loginname = :loginname and u.password =:password]
  13. 计算机找不到ie浏览器,IE浏览器不见了怎么办?找回IE浏览器的方法
  14. linux 如何把文件夹压缩文件,如何在Ubuntu桌面中将文件/文件夹压缩为.zip,tar.xz和7z格式...
  15. 在线App开发平台——应用之星傻瓜式开发平台
  16. Anaconda安装教程
  17. 解析DNA甲基化临床科研 | 无论什么科室,一定要有project的经典视角|易基因
  18. 未来5年互联网,运营将成比产品更加有前途的职业?
  19. 万能RecyclerView分割线扩展
  20. python听歌识曲爬虫_Python爬取网易云音乐热门评论的搜索结果-阿里云开发者社区...

热门文章

  1. 程序创新大会报名表1.0(html)
  2. linux dp接口显示,什么是DP接口?DP接口有哪些用处?
  3. Linux进程 exec族函数(execl,execlp,execle,execv,execvp,execcvpe)
  4. 字符串截取的三种方式!
  5. GitHub 生成秘钥及配置
  6. react 路由监听
  7. 保存的流程图怎么找不到_别找了,找不到了!最赞的流程图工具都在这!
  8. 华为面向全球发布HiCampus园区解决方案
  9. 零度之下代码输入不了_鸿图之下礼包码领取方法 新手开荒攻略保护器详解_游戏频道...
  10. Pandas读取文件的OSError: Initializing from file failed错误解决