Harris角点检测
提示:有添加超链接,点击跳转
视频推荐:小破站,会飞的吴克:点击跳转
opencv:简述
强烈推荐:CSE486, Penn State
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
提示:以下是本篇文章正文内容,下面案例可供参考
一、基本原理
左侧图,窗口W在平坦区域的运动,当位移比较小时,没有差值
中间图,窗口W只有在edge垂直方向,会有较大差值
右侧图,窗口W向任何方向移动,都会有较大的差值
公式:
E
(
u
,
v
)
=
∑
(
x
,
y
)
ϵ
W
w
(
x
,
y
)
[
I
(
x
+
u
,
y
+
v
)
−
I
(
x
,
y
)
]
2
(公式
1
)
对
I
(
x
+
u
,
y
+
v
)
进行泰勒展开。
I
(
x
+
u
,
y
+
v
)
=
I
(
x
,
y
)
+
∂
I
∂
x
u
+
∂
I
∂
y
u
+
o
(
)
I
(
x
+
u
,
y
+
v
)
≈
I
(
x
,
y
)
+
∂
I
∂
x
u
+
∂
I
∂
y
u
≈
I
(
x
,
y
)
+
[
I
x
I
y
]
[
u
v
]
(
公式
3
)
E(u,v) = \sum_{(x,y)\epsilon W} w(x,y)[I(x+u,y+v) - I(x,y)]^2 \space(公式1)\\ 对I(x+u,y+v)进行泰勒展开。\\ I(x+u,y+v) = I(x,y)+\frac{\partial I}{\partial x}u+\frac{\partial I}{\partial y}u+o() \\ I(x+u,y+v) \approx I(x,y)+\frac{\partial I}{\partial x}u+\frac{\partial I}{\partial y}u \approx I(x,y) + \begin{bmatrix} I_x&I_y \end{bmatrix} \begin{bmatrix} u \\ v \end{bmatrix} (公式3)
E(u,v)=(x,y)ϵW∑w(x,y)[I(x+u,y+v)−I(x,y)]2 (公式1)对I(x+u,y+v)进行泰勒展开。I(x+u,y+v)=I(x,y)+∂x∂Iu+∂y∂Iu+o()I(x+u,y+v)≈I(x,y)+∂x∂Iu+∂y∂Iu≈I(x,y)+[IxIy][uv](公式3)
将公式3代入公式1,得到:
E
(
u
,
v
)
≈
∑
(
x
,
y
)
ϵ
W
w
(
x
,
y
)
[
[
I
x
I
y
]
[
u
v
]
]
2
=
∑
(
x
,
y
)
ϵ
W
w
(
x
,
y
)
[
u
v
]
[
I
x
2
I
x
I
y
I
y
I
x
I
y
2
]
[
u
v
]
(
公式
4
)
E(u,v) \approx \sum_{(x,y)\epsilon W} w(x,y)[ \begin{bmatrix} I_x&I_y \end{bmatrix} \begin{bmatrix} u \\ v\end{bmatrix} ]^2 \\= \sum_{(x,y)\epsilon W} w(x,y) \begin{bmatrix} u&v \end{bmatrix} \begin{bmatrix} I_x^2 &I_xI_y \\ I_yI_x & I_y^2 \end{bmatrix} \begin{bmatrix} u\\v \end{bmatrix} (公式4)
E(u,v)≈(x,y)ϵW∑w(x,y)[[IxIy][uv]]2=(x,y)ϵW∑w(x,y)[uv][Ix2IyIxIxIyIy2][uv](公式4)
对公式4接着进行展开,实对称矩阵相似对角化
E
(
u
,
v
)
=
[
u
v
]
∑
w
(
x
,
y
)
[
I
x
2
I
x
I
y
I
y
I
x
I
y
2
]
[
u
v
]
=
[
u
v
]
P
[
λ
1
0
0
λ
2
]
P
T
[
u
v
]
T
=
[
u
′
v
′
]
[
λ
1
0
0
λ
2
]
[
u
′
v
′
]
T
=
λ
1
u
′
2
+
λ
2
v
′
2
上式展开
=
u
′
2
1
λ
1
+
v
′
2
1
λ
2
(公式
5
)
E(u,v) = \begin{bmatrix} u&v \end{bmatrix} \sum w(x,y) \begin{bmatrix} I_x^2 & I_xI_y \\ I_yI_x & I_y^2 \end{bmatrix} \begin{bmatrix} u\\v \end{bmatrix} \\ = \begin{bmatrix} u&v \end{bmatrix} P \begin{bmatrix} \lambda _1 & 0 \\ 0 & \lambda_2 \end{bmatrix} P^T \begin{bmatrix} u&v \end{bmatrix} ^T \\ = \begin{bmatrix} u'&v' \end{bmatrix} \begin{bmatrix} \lambda _1 & 0 \\ 0 & \lambda_2 \end{bmatrix} \begin{bmatrix} u'&v' \end{bmatrix} ^T ~~~~~~~ \\ = \lambda _1u'^2+\lambda _2v'^2 \qquad ~~~~~~~~~~上式展开\\ = \frac{u'^2}{\frac{1}{\lambda _1} } + \frac{v'^2}{\frac{1}{\lambda _2} } \qquad ~~~~~~~~~~~~~(公式5)
E(u,v)=[uv]∑w(x,y)[Ix2IyIxIxIyIy2][uv]=[uv]P[λ100λ2]PT[uv]T=[u′v′][λ100λ2][u′v′]T =λ1u′2+λ2v′2 上式展开=λ11u′2+λ21v′2 (公式5)
由公式4可知,当中间的二维矩阵(M)特征值最大时,即得到角点。
由公式5,就是一个椭圆公式,当椭圆成圆的时候面积是最大的,即偏差E(u,v)最大。
M = ∑ w ( x , y ) [ I x 2 I x I y I y I x I y 2 ] M = \sum w(x,y) \begin{bmatrix} I_x^2 & I_xI_y \\ I_yI_x & I_y^2 \end{bmatrix} M=∑w(x,y)[Ix2IyIxIxIyIy2]
如何更方便的表示E最大呢?
Corner Response Measure
R
=
d
e
t
(
M
)
−
k
[
t
r
a
c
e
(
M
)
]
2
d
e
t
(
M
)
=
λ
1
∗
λ
2
t
r
a
c
e
(
M
)
=
λ
1
+
λ
2
R = det(M)-k[trace(M)]^2\\ det(M) = \lambda_1*\lambda_2\\ trace(M) = \lambda_1+\lambda_2
R=det(M)−k[trace(M)]2det(M)=λ1∗λ2trace(M)=λ1+λ2
k为一个经验值,k = 0.04~0.06
所以,只用求得矩阵M的行列式和迹,便可以表示R
最后,在对R进行非极大值抑制,便得到key point
二、代码实现
1.自己实现的高斯函数和卷积
def gaussian_kernel_2d(size, sigma_x, sigma_y=None):
if sigma_y is None:
sigma_y = sigma_x
x, y = np.meshgrid(np.linspace(-(size//2), size//2, size),
np.linspace(-(size//2), size//2, size))
kernel_2d = (1 / (2 * np.pi * sigma_x * sigma_y)) * np.exp(-(x ** 2 / (2 * sigma_x ** 2) + y ** 2 / (2 * sigma_y ** 2)))
# 归一化
kernel_2d /= kernel_2d.sum()
return kernel_2d
def conv2d(image, kernel):
image = np.array(image, dtype=np.float64)
kernel = np.array(kernel, dtype=np.float64)
im_height, im_width = image.shape
ker_height, ker_width = kernel.shape
padded_image = np.zeros((im_height + ker_height - 1, im_width + ker_width - 1))
padded_image[:im_height, :im_width] = image
result = np.zeros_like(image)
for i in range(im_height):
for j in range(im_width):
# 计算当前像素周围与内核大小一致区域内的卷积结果
window = padded_image[i:i+ker_height, j:j+ker_width]
conv_result = np.sum(window * kernel)
result[i, j] = conv_result
return result
2.计算R, Response Measure
代码如下(示例):
def harris_response(im, k=0.04, window_size=3, threshold=0.1):
im.astype(np.float32)
x_kernel = np.array([[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]])
y_kernel = np.array([[-1, -2, -1],
[0, 0, 0],
[1, 2, 1]])
gaussian_k = gaussian_kernel_2d(3, 2)
Ix = conv2d(im, x_kernel)
Iy = conv2d(im, y_kernel)
Ixx = Ix * Ix
Iyy = Iy * Iy
Ixy = Ix * Iy
Ixx = conv2d(Ixx, gaussian_k)
Iyy = conv2d(Iyy, gaussian_k)
Ixy = conv2d(Ixy, gaussian_k)
R_ = np.zeros(im.shape)
for i in range(im.shape[0]):
for j in range(im.shape[1]):
M = np.array([[Ixx[i, j], Ixy[i, j]], [Ixy[i, j], Iyy[i, j]]])
R_[i, j] = np.linalg.det(M) - k * np.trace(M) ** 2
return R_
3. main
import cv2
import numpy as np
if __name__ == '__main__':
in_filename = "./126007.jpg"
im = cv2.imread(in_filename,cv2.IMREAD_ANYCOLOR)
R = harris_response(cv2.cvtColor(im, cv2.COLOR_BGR2GRAY))
print(R.mean())
im[R > R.mean()] = [0,0,255]
cv2.imwrite("harris.jpg", im)
原图
im[R > R.mean()] = [0,0,255] 效果图:
这里先简单的im[R > 10*R.mean()] = [0,0,255] 进行处理。简单粗暴,harris基本上掌握了~
也可以通过归一化、滤波器对相应函数R进行处理,再进行非极大值抑制,减少冗余检测点。
参考
提示:这里对文章进行总结:
https://blog.csdn.net/LeoEdwin/article/details/127539497
https://www.cse.psu.edu/~rtc12/CSE486/lecture06.pdf