赞
踩
本次实验旨在全面了解Harris角点检测算法,具体目标包括:
1.理解Harris角点检测的原理和算法。
2.掌握Harris角点检测的编程实现过程。
3.通过比较不同阈值和K值下的检测效果,评估算法的性能和鲁棒性。
Harris角点检测是一种用于图像处理和计算机视觉的算法,旨在检测图像中的角点特征。该方法通过计算图像梯度矩阵的特征值来评估局部变化,识别出角点,即图像中灰度变化明显且具有显著特征的位置。Harris角点检测器具有鲁棒性高、计算效率高的特点,广泛应用于目标跟踪、图像配准和三维重建等领域。
角点在保留图像图形重要特征的同时,可以有效地减少信息的数据量,使其信息的含量很高,有效地提高了计算的速度,有利于图像的可靠匹配,使得实时处理成为可能。
我们可以直观的概括下角点所具有的特征:
算法的基本思想是在图像上使用一个固定大小的窗口进行滑动,比较滑动前后窗口中像素的灰度变化情况。如果在任何方向上的滑动都引起了较大的灰度变化,那么我们可以认为窗口中存在角点。
当窗口进行[u,v]的移动时,滑动前后窗口中像素点的灰度变化描述如下:
E
(
u
,
v
)
=
∑
x
s
,
y
w
(
x
,
y
)
[
I
(
x
+
u
,
y
+
v
)
−
I
(
x
,
y
)
]
2
.
E(u,v)=\sum_{x_s,y}w(x,y)[I(x+u,y+v)-I(x,y)]^2.
E(u,v)=xs,y∑w(x,y)[I(x+u,y+v)−I(x,y)]2.其中
[
u
,
v
]
[u,v]
[u,v]表示窗口的偏移量,(x,y)表示窗口内对应的像素坐标位置。窗口的大小决定了窗口内有多少个位置,而
w
(
x
,
y
)
w(x,y)
w(x,y)是窗口函数。最简单的情况是,窗口内所有像素的权重系数都相等,即都为1。
然而,在某些情况下,我们会将窗口函数
w
(
x
,
y
)
w(x,y)
w(x,y)设定为以窗口中心为原点的二维正态分布。如果窗口中心是角点,那么移动前后,该点的灰度变化应该是最显著的,因此该点的权重系数可以设置得更大,表示在窗口移动时,该点对灰度变化的贡献更大;而远离窗口中心(即角点)的点,这些点的灰度变化较为缓和,它们的权重系数可以设置得较小,表示这些点对灰度变化的贡献较小。因此,我们自然地想到使用二维高斯函数来表示窗口函数。因此,通常窗口函数具有以下两种形式:
根据上述表达式,在窗口滑动到平坦区域时,我们可以想象到灰度不会发生变化,因此
E
(
u
,
v
)
=
0
E(u,v) = 0
E(u,v)=0;而当窗口滑动到纹理丰富的区域时,灰度变化会较大。算法的最终思想就是计算出灰度发生较大变化时所对应的位置,这种较大变化指的是在任意方向上的滑动时的变化情况,而不是单一方向上的变化。
I
(
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
+
I
y
v
+
O
(
u
2
,
v
2
)
I(x+u,y+v)=I(x,y)+I_xu+I_yv+O(u^2,v^2)
I(x+u,y+v)=I(x,y)+Ixu+Iyv+O(u2,v2)当发生微小位移时,忽略无穷小量,写成矩阵形式:
E
(
u
,
v
)
=
∑
w
[
u
,
v
]
[
I
x
2
I
x
I
y
I
x
I
y
I
y
2
]
[
u
v
]
=
[
u
,
v
]
M
[
u
v
]
.
E(u,v)=\sum_w[u,v][I2xIxIyIxIyI2y][uv]=[u,v]M[uv].
E(u,v)=w∑[u,v][Ix2IxIyIxIyIy2][uv]=[u,v]M[uv].所以
E
(
u
,
v
)
E(u,v)
E(u,v)表达式可以更新为:
E
(
u
,
v
)
≅
[
u
v
]
M
[
u
v
]
ω
E(u,v)\cong[uv]M[uv]_\omega
E(u,v)≅[uv]M[uv]ω矩阵
M
M
M为:
M
(
x
,
y
)
=
Σ
w
[
I
x
2
I
x
I
y
I
x
I
y
I
y
2
]
M(x,y)=\Sigma_w[I2xIxIyIxIyI2y]
M(x,y)=Σw[Ix2IxIyIxIyIy2]
E
(
u
,
v
)
E(u,v)
E(u,v)是一个二次型,而由线性代数定理可知:
对于给定二次型 f = ∑ i , j = 1 n a i j x i x j ( a i j = a j i ) f=\sum_{i,j=1}^{n}a_{ij}x_{i}x_{j}(a_{ij}=a_{ji}) f=∑i,j=1naijxixj(aij=aji),总有正交变换 x = P y x=Py x=Py使得 f f f化为标准型 f = λ 1 y 1 2 + λ 2 y 2 2 + ⋯ + λ n y n 2 f=λ_1 y_1^2+λ_2 y_2^2+⋯+λ_n y_n^2 f=λ1y12+λ2y22+⋯+λnyn2,其中 λ 1 , λ 2 … λ n λ_1,λ_2…λ_n λ1,λ2…λn为 f f f的矩阵 A = ( a i j ) A=(a_{ij}) A=(aij)的特征值。
因此 M M M分解可为: M = X Σ X T = X [ λ 1 0 0 λ 2 ] X T M=X\Sigma X^T=X[λ100λ2]X^T M=XΣXT=X[λ100λ2]XT
令
E
(
u
,
v
)
E(u,v)
E(u,v)=常数,我们可用一个椭圆来描绘这一函数
椭圆的长短轴与结构张量
M
M
M的两个特征值相关联。通过对这些情况的判断,我们可以区分出“flat”、“edge”和“corner”这三种区域,因为最直观的印象是(如下图):
代码构造可分五步
步骤说明:
import cv2 import numpy as np def convert_rgb_to_gray(image): # 将RGB图像转为灰度图像 return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) def sobel_grad_direction(image_source): # 利用Sobel算子计算图像x,y方向梯度 sobel_x = cv2.Sobel(image_source, cv2.CV_32F, 1, 0, ksize=3) sobel_y = cv2.Sobel(image_source, cv2.CV_32F, 0, 1, ksize=3) return sobel_x, sobel_y def sobel_xx(image_grad_x): # 计算Ixx return image_grad_x * image_grad_x def sobel_yy(image_grad_y): # 计算Iyy return image_grad_y * image_grad_y def sobel_xy(image_grad_x, image_grad_y): # 计算Ixy return image_grad_x * image_grad_y def my_gaussian_blur(src_image, size): # 高斯滤波函数平滑操作 return cv2.GaussianBlur(src_image, (size, size), 0) def harris_response(gauss_xx, gauss_yy, gauss_xy, k): # 计算角点响应值 result_data = gauss_xx * gauss_yy - gauss_xy * gauss_xy - k * (gauss_xx + gauss_yy) * (gauss_xx + gauss_yy) return result_data def check(result_data, src_gray, k_size): # 检查提取角点像素 result_image = cv2.cvtColor(src_gray, cv2.COLOR_GRAY2BGR) # 将灰度图转回RGB图像 r = k_size // 2 for i in range(r, result_image.shape[0] - r): for j in range(r, result_image.shape[1] - r): if result_data[i, j] > 1e9: # 这里R阈值设为1e9 result_image[i, j] = [0, 0, 255] # 将附合要求的点颜色设为红色 return result_image # 加载图像 path1 = r'../Data_Test1/Data/building.png' path2 = r'../Data_Test1/Data/chessboard.JPG' src_image = cv2.imread(path1) # 将彩色图转为灰度图 src_gray = convert_rgb_to_gray(src_image) # 计算x,y方向梯度 image_sobel_x, image_sobel_y = sobel_grad_direction(src_gray) # 计算IXX, IYY, IXY image_sobel_xx = sobel_xx(image_sobel_x) image_sobel_yy = sobel_yy(image_sobel_y) image_sobel_xy = sobel_xy(image_sobel_x, image_sobel_y) # 高斯平滑,去除噪声 gaussian_xx = my_gaussian_blur(image_sobel_xx, 3) gaussian_yy = my_gaussian_blur(image_sobel_yy, 3) gaussian_xy = my_gaussian_blur(image_sobel_xy, 3) # 计算角点响应值 其中k=0.05 harris_respond = harris_response(gaussian_xx, gaussian_yy, gaussian_xy, 0.05) # 提取附合要求的像素 result_image = check(harris_respond, src_gray, 3) # 结果展示 cv2.imshow("Result Image", result_image) cv2.waitKey(0) cv2.destroyAllWindows()
在opencv,skimage等第三方库中封装了harris角点检测模块,也可以直接调用。
Opencv调用代码如下:
import cv2 import numpy as np # 读取图片,并转为灰度图 path1 = '../Data_Test1/Data/building.png' path2 = '../Data_Test1/Data/chessboard.JPG' img = cv2.imread(path1) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) cv2.imwrite("building_gray.jpg", gray) # Harris角点检测 dst = cv2.cornerHarris(gray, 2, 3, 0.02) # dst值大于0.01 * dst.max() 的像素点值赋为 [0,0,255]。 img[dst > 0.01*dst.max()] = [0, 0, 255] cv2.imwrite("building_harris.jpg", img) cv2.imshow('img', img) cv2.waitKey(0)
k=0.05,响应阈值为1e9时角点检测结果如图
2.1 在K=0.04时,分别取阈值为0、1e3、1e6、1e9、1e12结果比较:
实验发现:随着阈值提高,检测到的角点数量在减少,角点典型性提高,算法质量得到提高,直至无像素点被识别为角点。
2.2在阈值为1e6时,K分别取0.05,0.10,0.15,0.20,0.25结果比较:
实验发现:较小的K值对边缘敏感,点沿着线分布(如道路)现象显著,而较大的K值则对角点更敏感,点位较为分散,多为角点。随着K值增加,检测到的像素数量减少,角点的典型性提高,直至无像素点被识别。
通过本次对Harris角点检测算法的学习和实践,我们得到了以下结论:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。