Shi-Tomasi 算法是一种用于在图像中寻找“好的跟踪特征”的角点检测算法。 它是 Harris 角点检测算法的改进版本,在某些情况下比 Harris 算法更稳定。
1.原理
与 Harris 算法类似,Shi-Tomasi 算法也基于图像的梯度信息。 但与 Harris 算法使用角点响应函数 R = det(M) - k*(trace(M))^2 不同,Shi-Tomasi 算法直接使用矩阵 M 的最小特征值 λmin 作为角点响应值。
算法认为,当 λmin 大于某个阈值时,该点被认为是好的角点。 这里的 M 矩阵和 Harris 算法中的定义相同:
M = | Σ Gx*Gx Σ Gx*Gy |
| Σ Gx*Gy Σ Gy*Gy |
其中 Σ 表示在以该像素点为中心的邻域内求和,Gx 和 Gy 分别是图像在 x 和 y 方向上的梯度。
2. 算法步骤
步骤1 计算图像梯度:与 Harris 算法相同,计算图像在 x 和 y 方向上的梯度 (Gx 和 Gy)。
步骤2 计算梯度乘积:计算 Gx\*Gx, Gy\*Gy 和 Gx\*Gy。
步骤3 高斯滤波:对梯度乘积进行高斯滤波,以减少噪声的影响。
步骤4 计算最小特征值: 对于每个像素点,计算矩阵 M 的最小特征值 λmin。
步骤5 阈值处理: 将 λmin 的值与一个阈值进行比较。 如果 λmin 的值大于阈值,则该像素点被认为是角点。
步骤6 非极大值抑制: 对检测到的角点进行非极大值抑制,以消除重复的角点。
3. 函数
OpenCV 提供了 `cv2.goodFeaturesToTrack()` 函数来实现 Shi-Tomasi 角点检测。
corners = cv2.goodFeaturesToTrack(image, maxCorners, qualityLevel, minDistance, mask, blockSize, useHarrisDetector, k)
`image`: 输入图像,必须是灰度图像。
`maxCorners`: 要检测的最大角点数量。 如果设置为 0,则检测所有符合条件的角点。
`qualityLevel`: 角点质量等级。 它是角点响应值的乘数,用于设置阈值。 只有大于 `qualityLevel * best_corner_response` 的角点才会被保留,其中 `best_corner_response` 是图像中最佳角点响应值。
`minDistance`: 角点之间的最小距离。 如果两个角点之间的距离小于 `minDistance`,则只保留响应值最高的角点。
`mask`: 可选参数,用于指定感兴趣区域 (ROI)。 只有在 ROI 内的像素点才会被检测。
`blockSize`: 用于计算角点响应函数的邻域大小。
`useHarrisDetector`: 可选参数,用于指定是否使用 Harris 角点检测算法。 如果设置为 `True`,则使用 Harris 算法;如果设置为 `False` (默认值),则使用 Shi-Tomasi 算法。
`k`: 如果 `useHarrisDetector` 设置为 `True`,则此参数是 Harris 角点检测算法中的自由参数 k。
`corners`: 返回的角点坐标,是一个 NumPy 数组,形状为 `(N, 1, 2)`,其中 N 是检测到的角点数量。
4. 特点
比 Harris 算法更稳定:** 在某些情况下,Shi-Tomasi 算法比 Harris 算法更稳定,能够检测到更可靠的角点。
参数更直观: `qualityLevel` 和 `minDistance` 等参数更直观,更容易调整。
计算效率高: 算法计算速度较快,适用于实时应用。
良好的跟踪特征: 检测到的角点通常是良好的跟踪特征,可以用于物体跟踪等应用。
5. 应用
物体跟踪: 在视频中跟踪物体的运动。
运动估计: 估计视频中物体的运动。
视频拼接: 将多段视频拼接成一段更长的视频。
三维重建: 利用角点信息进行三维重建。
机器人导航: 在机器人导航中使用角点信息进行定位和地图构建。
6. 代码示例
以下是一个使用 OpenCV 实现 Shi-Tomasi 角点检测的示例代码:
import cv2
import numpy as np
# 1. 读取图像
img = cv2.imread('./image/tv.jpg') # 替换为你的图像文件名
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2. Shi-Tomasi 角点检测
corners = cv2.goodFeaturesToTrack(gray, maxCorners=1000, qualityLevel=0.01, minDistance=10)
# 3. 绘制角点
if corners is not None:
corners = np.int0(corners) # 将角点坐标转换为整数
for i in corners:
x, y = i.ravel()
cv2.circle(img, (x, y), 3, (0, 0, 255), -1) # BGR 颜色空间
# 4. 显示结果
cv2.imshow('Shi-Tomasi Corners', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
7. 代码解释
读取图像和灰度转换: 读取图像,并将其转换为灰度图像。
Shi-Tomasi 角点检测: 调用 `cv2.goodFeaturesToTrack()` 函数进行角点检测。
`gray`: 输入的灰度图像。
`maxCorners=25`: 最多检测 25 个角点。
`qualityLevel=0.01`: 角点质量等级设置为 0.01。
`minDistance=10`: 角点之间的最小距离设置为 10 像素。
绘制角点: 将检测到的角点在图像上绘制出来。
显示结果: 显示带有角点标记的图像。
8. 总结
Shi-Tomasi 角点检测是一种优秀的角点检测算法,特别适合于需要跟踪特征的应用。 它通过计算矩阵 M 的最小特征值来确定角点,并且具有比 Harris 算法更稳定的特性。 通过调整 `maxCorners`、`qualityLevel` 和 `minDistance` 等参数,可以控制角点检测的数量和质量。 `cv2.goodFeaturesToTrack()` 函数是 OpenCV 中实现 Shi-Tomasi 角点检测的便捷工具。