Harris 角点检测是一种用于在图像中寻找角点的算法。 角点是指图像中局部区域内,在多个方向上梯度都有明显变化的像素点。 简单来说,角点是图像中比较独特且易于识别的点。
1.原理
Harris 角点检测基于图像灰度强度的二阶导数(即 Hessian 矩阵)来寻找角点。 该算法通过计算一个角点响应函数 (Corner Response Function, CRF) 来衡量像素点周围区域的角点强度。 如果 CRF 的值大于某个阈值,则该像素点被认为是角点。
2. 算法步骤
步骤1 计算图像梯度
使用 Sobel 算子或其他梯度算子计算图像在 x 和 y 方向上的梯度 (Gx 和 Gy)。
步骤2 计算梯度乘积: 计算 Gx*Gx, Gy*Gy 和 Gx*Gy。
步骤3 高斯滤波:对梯度乘积进行高斯滤波,以减少噪声的影响。
步骤4 计算角点响应函数 (CRF): 对于每个像素点,计算以下矩阵 M:
M = | Σ Gx*Gx Σ Gx*Gy |
| Σ Gx*Gy Σ Gy*Gy |
其中 Σ 表示在以该像素点为中心的邻域内求和。 然后,计算角点响应函数 (CRF):
`det(M) = (Σ Gx*Gx) * (Σ Gy*Gy) - (Σ Gx*Gy)^2` (M 的行列式)
`trace(M) = Σ Gx*Gx + Σ Gy*Gy` (M 的迹)
`k` 是一个经验常数,通常取值在 0.04 到 0.06 之间。
步骤5 阈值处理:将 CRF 的值与一个阈值进行比较。 如果 CRF 的值大于阈值,则该像素点被认为是角点。
步骤6 非极大值抑制:对检测到的角点进行非极大值抑制,以消除重复的角点。
3. 函数
OpenCV 提供了 `cv2.cornerHarris()` 函数来实现 Harris 角点检测。
`src`: 输入图像,必须是灰度图像且为 float32 类型。
`blockSize`: 用于计算角点响应函数的邻域大小。
`ksize`: Sobel 算子的核大小,用于计算图像梯度。
`k`: 角点检测的自由参数,取值范围通常在 0.04 到 0.06 之间。
`dst`: 返回的角点响应图像。
4. 特点
简单易懂:算法原理简单,易于实现。
计算效率高:算法计算速度较快,适用于实时应用。
旋转不变性:Harris 角点检测对旋转具有一定的鲁棒性。
尺度敏感:Harris 角点检测对尺度变化比较敏感。
5. 应用
图像配准: 通过检测图像中的角点,可以实现图像的配准。
物体跟踪: 在视频中跟踪物体的运动。
三维重建: 利用角点信息进行三维重建。
运动检测: 检测视频中的运动物体。
图像拼接: 将多幅图像拼接成一幅更大的图像。
6.代码示例
以下是一个使用 OpenCV 实现 Harris 角点检测的示例代码:
import cv2
import numpy as np
# 1. 读取图像
img = cv2.imread('./image/chessboard.jpg') # 替换为你的图像文件名
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray) # 转换为 float32 类型
# 2. Harris 角点检测
dst = cv2.cornerHarris(gray, 2, 3, 0.04)
# 3. 膨胀角点
dst = cv2.dilate(dst, None)
# 4. 设置阈值,将角点标记为红色
img[dst > 0.001 * dst.max()] = [0, 0, 255] # BGR 颜色空间
# 5. 显示结果
cv2.imshow('Harris Corners', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
代码解释:
读取图像和灰度转换: 读取图像,并将其转换为灰度图像。 注意:`cv2.cornerHarris()` 函数要求输入图像为灰度图像,并且数据类型为 `float32`。
Harris 角点检测: 调用 `cv2.cornerHarris()` 函数进行角点检测。
`gray`: 输入的灰度图像。
`2`: `blockSize`,表示用于角点检测的邻域大小为 2x2。
`3`: `ksize`,表示 Sobel 算子的核大小为 3x3。
`0.04`: `k`,Harris 角点检测的自由参数。
膨胀角点: 使用 `cv2.dilate()` 函数对角点进行膨胀,使其更加明显。
设置阈值: 将角点响应图像 `dst` 的值与一个阈值进行比较。 如果 `dst` 的值大于阈值,则将该像素点标记为红色。 这里阈值设置为 `0.01 * dst.max()`,即角点响应图像最大值的 1%。
显示结果: 显示带有角点标记的图像。
7. 总结
Harris 角点检测是一种简单而有效的角点检测算法。 它基于图像灰度强度的二阶导数来寻找角点,具有旋转不变性和计算效率高的优点。 通过调整 `blockSize`、`ksize` 和 `k` 等参数,可以控制角点检测的灵敏度。 然而,Harris 角点检测对尺度变化比较敏感,因此在某些应用中可能需要结合其他技术来提高鲁棒性。