Harris角点检测
date
Sep 26, 2021
Last edited time
Nov 20, 2021 02:16 PM
status
Published
slug
Harris角点检测
tags
CV
summary
总结了Harris角点检测算法的主要步骤, 以及如何自己实现Harris 角点检测算法
type
Post
Field
Plat
Harris算子介绍
Harris角点算子的简历如下:
- 提出者:Harris and Stephens
- 提出时间:1988
- 总结: Moravec算子的改进版,更加稳定
角点
什么是角点
角点的定义:
- 一阶导数 (即灰度的梯度) 的局部最大所对应的像素点;
- 两条及两条以上边缘的交点;
- 图像中梯度值和梯度方向的变化速率都很高的点;
- 角点处的一阶导数最大,二阶导数为零,指示物体边缘变化不连续的方向。

在上面的倒五边形中,从上到下分别取 1/2/3 三部分,他们分别代表了:
- 边缘
- 团块
- 角点
如何识别角点?
基本思想是使用一个固定窗口在图像上进行任意方向上的滑动,比较滑动前与滑动后两种情况,窗口中的像素灰度变化程度,如果存在任意方向上的滑动,都有着较大灰度变化,那么我们可以认为该窗口中存在角点。
角点的特性下面的图更清晰:

而且当然不用我等工程狗去根据这种特征来设计算法,跟边缘检测一样,大神们早就做过了,单识别角点的算法,比较有名的就有:
- Harri 算法
- Shi-Tomasi 算法
- 亚像素级角点检测
等好多种,我们这里先拿 Harri 开刀尝试剖析一下。
Harri 角点检测
公式推导
我们参考上图,用窗口在一张图片上移动的梯度变化再把三个区域定义梳理一下:
- 平坦区域:窗口移动在所有方向没有明显的梯度变化。
- 边缘区域:窗口移动在某个方向有明显梯度变化。
- 角度边缘:窗口移动在各个方向梯度值都有明显变化。
有了这个差异就好办了,我们设窗口平移 产生灰度变化 ,可以找到公式
其中:
- 和 :窗口偏移量
- 和 :窗口内像素坐标
- :窗口函数,内含权重信息,常用的有权重为 1 和呈二元高斯正太分布的权重,意在突出像素值变化明显的程度
- 函数 :像素密度函数,类比与像素值
当窗口处在平坦区域上滑动,可以想象的到,灰度不会发生变化,那么 ;如果窗口处在比纹理比较丰富的区域上滑动,那么灰度变化会很大。算法最终思想就是计算灰度发生较大变化时所对应的位置,当然这个较大是指针任意方向上的滑动,并非单指某个方向。
公式变换
下面的核心就是找到 的最大值,对于给定的窗口函数 ,我们就是要找 的最大值。
我们先回忆一下泰勒展开式:
所以,
那么
这里的 是矩阵
这里 和 是图像在 和 方向的导数
矩阵 M 的关键性
这个时候问题的关键转到了矩阵 上,它是怎么影响 的值得呢?Harris 角点检测是通过对窗口内的每个像素的 方向上的梯度与 方向上的梯度进行统计分析。这里以
和 为坐标轴,因此每个像素的梯度坐标可以表示成 ( )。针对平坦区域,边缘区域以及角点区域三种情形进行分析:

第一步:对 和 方向分别求导
第二步:梯度绘制

第三步:圈中数据集

可以认为:
: 轴方向的偏导的特征值;
: 轴方向的偏导的特征值;
第四步:对 和 为坐标区分边缘、平坦、角点

结论:
- 特征值都比较大时,即窗口中含有角点
- 特征值一个较大,一个较小,窗口中含有边缘
- 特征值都比较小,窗口处在平坦区域
OpenCV 引入新公式
OpenCV 中会直接引入一个新的公式,它以上面的知识为基础,以经验函数为模型,做了 R 的函数:
当仅有一个点的时候
不要问我为什么用这个公式,看图,别说话。。。

其中:
- :矩阵行列式,
- :矩阵的迹,
- :Harri 系数,一般取值为
所以,Harris 的基本步骤就是:
- 求两个方向梯度,并计算出矩阵
- 对矩阵 计算特征值、行列式和迹
- 根据特征值的关系并使用阈值确定图像特征

好了,长舒一口气。看懂都难,真不知道这些人当年是怎么想起来的。不过,老规矩,OpenCv 早就给我们做好了 API
dst
:Harri 算法的输出矩阵(输出图像),CV_32FC1 类型,与 src 有同样的尺寸
src
:输入图像,单通道,8 位或浮点型
blockSize
:邻域大小
ksize
:Sobel 算子的孔径大小
k
:Harri 算法系数,即第二种表达式中的
下面就让我们试试这个算法的效果吧。。。
注意点:
cornerHarris 转化出来的 Dst 是 CV_32FC1 类型,最好经过归一化和 ABS 处理。
运行结果:
