OpenCV3入门(十二)角点检测

1、角点介绍

角点检测(Corner Detection)是计算机视觉系统中用来获得图像特征的一种方法,广泛应用于运动检测、图像匹配、视频跟踪、三维建模和目标识别等领域中,也称为特征点检测。在图像中角点是一个重要的局部特征,它决定了图像中关键区域的形状,体现了图像中重要的特征信息。目前,角点检测方法主要有2大类:

1)基于图像边缘轮廓特征的方法。

2)基于图像灰度信息的方法。此方法主要通过计算曲率及梯度进行角点检测,通过计算边缘的曲率来判断角点的存在性。典型代表有Harris算法、Susan算法、Moravec算法等。

角点通常被定义为两条边的交点,更严格的说,角点的局部邻域应该具有两个不同区域的不同方向的边界。而实际应用中,大多数所谓的角点检测方法检测的是拥有特定特征的图像点,而不仅仅是“角点”。这些特征点在图像中有具体的坐标,并具有某些数学特征,如局部最大或最小灰度、某些梯度特征等。现有的角点检测算法并不是都十分的健壮。很多方法都要求有大量的训练集和冗余数据来防止或减少错误特征的出现。另外,角点检测方法的一个很重要的评价标准是其对多幅图像中相同或相似特征的检测能力,并且能够应对光照变化、图像旋转等图像变化。

2、Harris算法介绍

Harris 是 Harris 和 Stephens 在 1988 年提出,专门针对 Moravec 算子的改进版。Harris 算子,又称 Plessey算子,它基于与 Moravec 相同的角点定义,即定义在各个方向上灰度值变化的点。

角点可以如下图形象的定义,如果在各个方向上移动这个小窗口,窗口内的灰度发生了较大的变化,那么说明窗口内存在角点;如果在各个方向移动,灰度几乎不变,说明是平坦区域;如果只沿着某一个方向移动,灰度几乎不变,说明是直线(边缘)。

设图像窗口平移[u,v] ,产生的灰度变化为E[u,v] ,则:

上式中,窗口函数是一个矩形窗口或高斯窗口,它给在其中的像素加权。

我们必须使边角检测的函数最大化,这意味着,我们必须最大限度地利用第二个参数。

根据角点的定义,平坦区域,像素变化小,那么上式后半部分基本接近为0;在边缘区域,会在沿着边缘方向上差值为一个稳定值;只有在角点处,无论向那个方向移动,都会发生变化。

根据泰勒级数展开:

那么f(x+u, y+v)可以简化为:

f(x+u, y+v) ≈ f(x,y) + ufx(x,y) + vfy(x,y)

Harris算式的可以写成矩阵模式。

Harris算式可以近似得到下面的表达:

其中M为:

其中,表示 Ix 方向的梯度,表示Iy 方向的梯度,为高斯函数。矩阵的特征值是自相关函数的一阶曲率。特征值的大小与特征点的性质息息相关。即当两个特征值都比较小时,则此点可能位于平坦区,不为角点或边界点; 当两个特征值一个较大、而另一个却相对较小时,则此点位于边界上,属于边界点; 当两个特征值均相对较大时,则此点沿任意方向的曲率都较大,为需要提取的角点。

M为梯度的协方差矩阵,在实际应用中为了能够应用更好的编程,定义了角点响应函数R,通过判定R大小来判断像素是否为角点。R取决于M的特征值,对于角点|R|很大,平坦的区域|R|很小,边缘的R为负值。Harris角点检测算法就是对角点响应函数R进行阈值处理:R > threshold,即提取R的局部极大值。

其中,det(M) = λ1* λ1, trace(M) =λ1+ λ1 。k是经验参数,一般取值为0.04~0.06。

当R为大数值正数的时候,表示为角点。如下图所示:

3、Harris实验

OpenCV函数原型:

C++:void cornerHarris( InputArray src, //输入8bit单通道灰度Mat矩阵
                  OutputArray dst, //保存角点检测结果,32位单通道,大小与src相同
                  int blockSize,   //滑块窗口的尺寸、邻域的大小
                  int ksize,        //Sobel边缘检测滤波器大小
                  double k,        //Harris中间参数,经验值0.04~0.06
                  int borderType=BORDER_DEFAULT  //插值类型
                  );

测试实例:

int threshod_val = 30;
int max_threshod_val = 150;
Mat src_img;

void call_back(int, void*)
{
    Mat normImage, scaledImage;
    Mat Img_scr1 = src_img.clone();
    Mat Img_dst = Mat::zeros(src_img.size(), CV_32FC1);

    cornerHarris(src_img, Img_dst, 2, 3, 0.04, BORDER_DEFAULT); //进行角点检测
    normalize(Img_dst, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat()); // 归一化
    convertScaleAbs(normImage, scaledImage);//将归一化后的图线性变换成8位无符号整型

    for (int i = 0; i < normImage.rows; i++)
    {
        for (int j = 0; j < normImage.cols; j++)
        {
            if ((int)normImage.at<float>(i, j) > threshod_val + 100)
            {
                circle(Img_scr1, Point(j, i), 3, Scalar(0, 0, 255), 2, 8, 0);
                circle(scaledImage, Point(j, i), 3, Scalar(0, 0, 255), 2, 8, 0);
            }
        }

    }

    imshow("corner", Img_scr1);
    imshow("scaledImage", scaledImage);
}

int main() {
    src_img = imread("D:\\WORK\\5.OpenCV\\LeanOpenCV\\pic_src\\checkerboard.png");
    imshow("原图", src_img);

    cvtColor(src_img, src_img, COLOR_BGR2GRAY);
    namedWindow("corner");
    createTrackbar("thresh", "corner", &threshod_val, max_threshod_val, call_back);
    call_back(threshod_val, 0);

    waitKey(0);
}

输出结果如下图:

测试2:

4、参考文献

1、A COMBINED CORNER AND EDGE DETECTOR,Chris Harris,Mike Stephens,1988

http://www.bmva.org/bmvc/1988/avc-88-023.pdf

2、Harris Corner Detection

https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_feature2d/py_features_harris/py_features_harris.html

3、Harris 角点检测子

http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/features2d/trackingmotion/harris_detector/harris_detector.html

4、【OpenCV入门教程之十六】OpenCV角点检测之Harris角点检测

https://blog.csdn.net/poem_qianmo/article/details/29356187

5、(四)OpenCV中的特征检测之Harris Corner检测

https://blog.csdn.net/u014403318/article/details/80562785

6、OpenCV学习笔记(八)——Harris角度特征从原理到实现详解

https://blog.csdn.net/weixin_41695564/article/details/79962401

7、《OpenCV3 编程入门》,电子工业出版社,毛星雨著

8、《学习OpenCV》,清华大学出版社,Gary Bradski, Adrian kaehler著

原文地址:https://www.cnblogs.com/pingwen/p/12423976.html

时间: 2024-10-10 02:10:27

OpenCV3入门(十二)角点检测的相关文章

[WebGL入门]十二,模型数据和顶点属性

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正. 顶点属性的意思 上次的文章中,介绍了一下从着色器的生成,编译,到程序对象的生成和着色器的连接.这次,简单的说一下模型数据的定义和顶点属性的处理.另外,介绍一下根据模型数据生成VBO的方法.VBO的使用要比生成难理解一些,但是不要担心,后面会慢慢说明.接下来看一下顶点属性.顶点属性,说的简单点,

Android入门(十二)SQLite事务、升级数据库

原文链接:http://www.orlion.ga/610/ 一.事务 SQLite支持事务,看一下Android如何使用事务:比如 Book表中的数据都已经很老了,现在准备全部废弃掉替换成新数据,可以先使用delete()方法将Book表中的数据删除, 然后再使用insert()方法将新的数据添加到表中.我们要保证的是,删除旧数据和添加新数据的操作必须一起完成,否则就还要继续保留原来的旧数据.                 Button replaceData = (Button) find

ES6入门十二:Module(模块化)

webpack4打包配置babel7转码ES6 Module语法与API的使用 import() Module加载实现原理 Commonjs规范的模块与ES6模块的差异 ES6模块与Nodejs模块相互加载 模块循环加载 一.webpack4打包配置babel7转码ES6 1.webpack.config.js 在webpack中配置babel转码其实就是在我之前的webpack配置解析基础上添加babel的加载器,babel的具体转码配置在之前也有一篇详细的博客做了解析: webpack安装与

OpenCV3入门(二)Mat操作

1.Mat结构 1.1.Mat数据 Mat本质上是由两个数据部分组成的类: 矩阵头:包含信息有矩阵的大小,用于存储的方法,矩阵存储的地址等 数据矩阵指针:指向包含了像素值的矩阵. 矩阵头部的大小是恒定的,矩阵本身的大小因图像的不同而不同,通常是较大的数量级. 在程序中传递图像并在有些时候创建图像副本需要花费很大的代价生成图像矩阵本身,而不是图像的头部.为了解决这一问题 OpenCV 使用引用计数系统.其思想是Mat的每个对象具有其自己的头,但可能他们通过让他们矩阵指针指向同一地址的两个实例之间共

SpringBoot入门 (十二) 定时任务

本文记录在SpringBoot中使用定时任务. 在我们的项目中,经常需要用到定时任务去帮我们做一些事情,比如服务状态监控,业务数据状态的更改等,SpringBoot中实现定时任务有2中方案,一种是自带的,我们只需要加上注解即可:另一种是集成Quartz来实现定时任务. 一 SpringBoot 提供的定时任务 在SpringBoot的starter包中已经提供了对定时任务的支持,我们很容易实现定时任务.修改pom.xml文件,加入如下内容,引入依赖: <dependency> <grou

java web开发入门十二(idea创建maven SSM项目需要解决的问题)基于intellig idea(2019-11-09 11:23)

一.spring mvc action返回string带双引号问题 解决方法: 在springmvc.xml中添加字符串解析器 <!-- 注册string和json解析适配器 --> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"&

Vue入门十二、路由的跳转

路由之间的跳转有再种:1.通过标签<router-link to='/login'>去登录</router-link>实现跳转2.通过js实现:this.$router.push({path:'/buy'})this.$router.replace({path:'/buy'})2.1push与replace的区别push会向history插入新记录replace不会插入history历史记录,如果返回上一页,则会跳转到上上一页中.上一页是不存在的返回上一页面:this.$route

【OpenCV入门教程之十二】OpenCV边缘检测:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑

本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/25560901 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 知乎:http://www.zhihu.com/people/mao-xing-yun 邮箱: [email protected] 写作当前博文时配套使用的OpenCV版本: 2.4.9 本篇文章中,我们将一起学习OpenCV中

Unity3D新手教学,让你十二小时,从入门到掌握!(二) [转]

版权声明:本文为Aries原创文章,转载请标明出处.如有不足之处欢迎提出意见或建议,联系QQ531193915 继续上一讲的内容,首先呢, 为了接下来要做的小游戏,在这里我要小小的修改一下移动的代码. public class PlayerMove : MonoBehaviour { //定义移动的速度 public float MoveSpeed = 8f; void Start () { } void Update () { //如果按下W或上方向键 if(Input.GetKey(KeyC