Harris与Shi-Tomasi 角点检测原理
Shi-Tomasi角点是根据Harris改进而来的。所以本文首先介绍Harris的原理。
Harris角点检测算法基本思想是使用一个固定窗口在图像上进行任意方向上的滑动,比较滑动前与滑动后窗口中的像素灰度变化程度,如果存在任意方向上的滑动,都有着较大灰度变化,那么我们可以认为该窗口中存在角点。
Harris角点检测器
将Harris角点检测算法分为三步:
- 当窗口同时向x和y两个方向移动时,计算窗口内部的像素值变化量为 E ( u , v ) E(u,v) E(u,v)
- 对于每个窗口都计算其对应的一个角点响应函数 (得分);
- 然后对该函数进行阈值处理,如果 >threshold,则表示该窗口对应一个角点特征。
接下来对每一步进行细化。
第一步:
让一个窗口的中心位于灰度图像的一个位置 ( x , y ) (x,y) (x,y) ,此坐标的灰度值为 I ( x , y ) I(x,y) I(x,y) ,让这个窗口分别向x和y方向位移u和v,到一个新的位置 ( x + u , y + v ) (x + u,y + v) (x+u,y+v) ,此坐标的灰度值为 I ( x + u , y + v ) I(x + u,y + v) I(x+u,y+v)。
[ I ( x , y ) − I ( x + u , y + v ) ] [I(x,y) - I(x + u,y + v)] [I(x,y)−I(x+u,y+v)] 就是窗口移动引起的灰度值的变化值。
设 w ( x , y ) w(x,y) w(x,y)为位置 ( x , y ) (x,y) (x,y) 处的窗口函数,表示窗口内各像素的权重,最简单的就是把窗口内所有像素的权重都设为1。
有时也会把 w ( x , y ) w(x,y) w(x,y)设定为以窗口中心为原点的高斯分布(二元正态分布)。如果窗口中心点像素是角点,那么窗口移动前后,中心点的灰度值变化非常强烈,所以该点权重系数应该设大一点,表示该点对灰度变化的贡献较大;而离窗口中心(角点)较远的点,这些点的灰度变化比较小,于是将权重系数设小一点,表示该点对灰度变化的贡献较小。
则窗口在各个方向上移动 所造成的像素灰度值的变化量公式如下:
E ( u , v ) = ∑ ( x , y ) { w ( x , y ) × [ I ( x , y ) − I ( x + u , y + v ) ] 2 } E(u,v) = \sum\limits_{(x,y)} {\{ w(x,y)} \times {[I(x,y) - I(x + u,y + v)]^2}\} E(u,v)=(x,y)∑{w(x,y)×[I(x,y)−I(x+u,y+v)]2}
对于一个角点来说, E ( u , v ) E(u,v) E(u,v)会非常大。因此,我们可以最大化上面这个函数来得到图像中的角点。
用上面的函数直接去计算会很慢,下面将用另一个式子去代替。
首先我们下利用泰勒展开式去代替 I ( x + u , y + v ) I(x + u,y + v) I(x+u,y+v)。
对于二阶泰勒展开公式为:
T ( x , y ) ≈ f ( u , v ) + ( x − u ) f x ( u , v ) + ( y − v ) f y ( u , v ) + . . . T(x,y) \approx f(u,v) + (x - u){f_x}(u,v) + (y - v){f_y}(u,v) + ... T(x,y)≈f(u,v)+(x−u)fx(u,v)+(y−v)fy(u,v)+...
将 I ( x + u , y + v ) I(x + u,y + v) I(x+u,y+v)套用上面的公式得到:
I ( x + u , y + v ) ≈ I ( u , v ) + u I x + v I y I(x + u,y + v) \approx I(u,v) + u{I_x} + v{I_y} I(x+u,y+v)≈I(u,v)+uIx+vIy
其中 I x {I_x} Ix和 I y {I_y} Iy是 的偏微分, I \ I I就是图像在x和y方向的梯度图。
将上式代入 E ( u , v ) E(u,v) E(u,v)中,可得:
E ( u , v ) = ∑ ( x , y ) [ w ( x , y ) × ( u 2 I x 2 + v 2 I y 2 + 2 u v I x I y ) ] E(u,v) = \sum\limits_{(x,y)} {[w(x,y)} \times ({u^2}{I_x}^2 + {v^2}{I_y}^2 + 2uv{I_x}{I_y})] E(u,v)=(x,y)∑[w(x,y)×(u2Ix2+v2Iy2+2uvIxIy)]
将u和v拿出来,矩阵的形式就变成:
再经过对矩阵对角化可以变成:
最后是把实对称矩阵对角化处理后的结果,可以把T成旋转因子,其不影响两个正交方向的变化分量。
经对角化处理后,将两个正交方向的变化分量提取出来,就是
λ
1
\ {\lambda _1}
λ1和
λ
2
\ {\lambda _2}
λ2(特征值)。
第二步:
灰度值变化的大小则取决于矩阵M,那么如何找到这些窗口,我们可以使用矩阵的特征值来实现。
计算每个窗口对应的得分(角点响应函数R):
R
=
det
(
M
)
−
k
(
t
r
a
c
e
(
M
)
)
2
=
λ
1
λ
2
−
k
(
λ
1
+
λ
2
)
2
=
(
1
−
2
k
)
λ
1
λ
2
−
k
λ
1
2
−
k
λ
2
2
\begin{array}{l} R = \det (M) - k{(trace(M))^2}\\ = {\lambda _1}{\lambda _2} - k{({\lambda _1} + {\lambda _2})^2}\\ = (1 - 2k){\lambda _1}{\lambda _2} - k{\lambda _1}^2 - k{\lambda _2}^2 \end{array}
R=det(M)−k(trace(M))2=λ1λ2−k(λ1+λ2)2=(1−2k)λ1λ2−kλ12−kλ22
det是矩阵的行列式,trace是矩阵的迹,k是一个经验常数,在范围 (0.04, 0.06) 之间。
第三步:
根据 R 的值,将这个窗口所在的区域划分为平面、边缘或角点。为了得到最优的角点,我们还可以使用非极大值抑制。
Harris 检测器具有旋转不变性,但不具有尺度不变性,也就是说尺度变化可能会导致角点变为边缘,如下图所示:
因为特征值 和 决定了 R 的值,所以我们可以用特征值来决定一个窗口是平面、边缘还是角点:
平面:该窗口在平坦区域上滑动,窗口内的灰度值基本不会发生变化,所以
∣
R
∣
\left| R \right|
∣R∣的值非常小,在水平和竖直方向变化量均较小,即
I
x
\ I_x
Ix和
I
y
\ I_y
Iy都较小,那么 和 都较小;
边缘:R为负数,仅在垂直或者水平方向有较大的变化量,即
I
x
\ I_x
Ix和
I
y
\ I_y
Iy只有一个较大,也就是
λ
1
\lambda _1
λ1>>
λ
2
\lambda _2
λ2或者
λ
2
\lambda _2
λ2>>
λ
1
\lambda _1
λ1;
角点:R值很大,在垂直和水平方向均有较大的变化点,即
I
x
\ I_x
Ix和
I
y
\ I_y
Iy都较大,也就是
λ
1
\lambda _1
λ1 和
λ
2
\lambda _2
λ2都较大;
Harris 角点检测的结果是带有这些分数 R 的灰度图像,设定一个阈值,分数大于这个阈值的像素就对应角点。
Shi-Tomasi 角点检测器
Shi-Tomasi 角点检测器是Jianbo Shi和 Carlo Tomasi 《Good features to track》中提出了Harris 角点检测器的改进版。Shi-Tomasi 方法在很多情况下可以得到比 Harris 算法更好的结果。
由于 Harris 角点检测算法的稳定性和 k 值有关,而 k 是个经验值,不好设定最佳值。
Shi-Tomasi 发现,角点的稳定性其实和矩阵 M 的较小特征值有关,于是直接用较小的那个特征值作为分数。这样就不用调整k值了。
所以 Shi-Tomasi 将分数公式改为如下形式:
R
=
min
(
λ
1
,
λ
2
)
\ R = \min ({\lambda _1},{\lambda _2})
R=min(λ1,λ2)
和 Harris 一样,如果该分数大于设定的阈值,我们就认为它是一个角点。
OpenCV中的函数:
cv::gapi::goodFeaturesToTrack (const GMat &image,
int maxCorners,
double qualityLevel,
double minDistance,
const Mat &mask = Mat(),
int blockSize = 3,
bool useHarrisDetector = false,
double k = 0.04
)
Parameters | 说明 |
---|---|
image | 输入8位或浮点32位,单通道图像。 |
maxCorners | 最大角点数,如果角点比较多就返回最强的。maxCorners≤0代表没有角点数的限制,返回全部角点。 |
qualityLevel | 质量系数(小于1.0的正数,一般在0.01-0.1之间),表示可接受角点的最低质量水平。该系数乘以最好的角点分数(也就是上面较小的那个特征值),作为可接受的最小分数;例如,如果最好的角点分数值为1500且质量系数为0.01,那么所有质量分数小于15的角都将被忽略。 |
minDistance | 角点之间的最小的欧氏距离,忽略小于此距离的点。 |
mask | 掩膜,指定检测区域 |
blockSize | 用于计算每个像素邻域上导数协变矩阵的平均块的大小。 See cornerEigenValsAndVecs . |
useHarrisDetector | 指示是否使用Harris检测器的参数(see cornerHarrisor cornerMinEigenVal.) |
k | 默认为0.04,Harris角点检测时使用。 |
Returns | 说明 |
---|---|
vector of detected corners. | 检测出的角点向量 |