OpenCV开发教程之shi-tomasi角点检测

11人浏览 / 0人评论 / 添加收藏

Shi-Tomasi 角点检测是 OpenCV 中一种非常流行且强大的角点检测算法,它是对 Harris 角点检测的改进,能以更快的速度选出图像中更“强”的角点。

🔍 原理简介(一句话)

Harris 算法通过一个响应函数 R = λ1λ2 - k(λ1+λ2)² 判断窗口区域是否为角点,而 Shi-Tomasi 直接取两个特征值 λ1 和 λ2 的最小值,只要这个最小值大于阈值,就认为是角点。这使得 Shi-Tomasi 能选出更稳定、更尖锐的角点,且速度通常更快。

🧪 OpenCV 中的用法

Shi-Tomasi 检测器对应函数 cv2.goodFeaturesToTrack(),它背后的原始实现就是 Shi-Tomasi(或 Harris,通过参数指定)。这个名字也暗示了它的另一个重要用途:光流跟踪

调用函数:

corners = cv2.goodFeaturesToTrack(
   image,          # 输入灰度图像(8-bit 或 32-bit 浮点)
   maxCorners,     # 希望返回的最大角点数量(按质量排序)
   qualityLevel,   # 最小可接受的质量阈值(0~1,越大角点越少)
   minDistance,    # 角点之间的最小欧氏距离(避免太近)
   mask=None,      # 可选掩膜,只检测特定区域
   blockSize=3,    # 计算导数自相关矩阵的邻域大小(通常 3)
   useHarrisDetector=False,   # 是否使用 Harris 检测器(默认 False 即 Shi-Tomasi)
   k=0.04          # Harris 检测器用到的自由参数(仅在 useHarrisDetector=True 时有效)
)

返回值 corners 是形状为 (N, 1, 2) 的浮点型数组,每个角点坐标表示为 (x, y)

演示代码如下:

# Shi-Tomasim检测
# Shi-Tomasi是Harris角点检测的改进
# Harris角点检测计算的稳定性和K有关,而K是一个经验值,不太好设定最佳的K值Shi-Tomasi发现。
#   角点的稳定性其实和矩阵M的较小特征值有关,于是直接用较小的那个特征值作为分数。这样就不用调整k值了。
#   Shi-Tomasi 将分数公式改为如下形式:R=min(入1A2)。和Harris一样,如果该分数大于设定的阈值,我们就认为它是一个角点
#   goodFeaturesToTrack(image, maxCorners, qualityLevel, minDistancel, cornersL, maskl, blockSizel,useHarrisDetectorl, k]llll)
#   maxCorners:角点的最大数,值为0表示无限制
#   qualityLevel:角点质量,小于1.0的整数,一般在0.01-0.1之间.
#   minDistance:角之间最小欧式距离,忽略小于此距离的点.
# omask:感兴趣的区域
#   blockSize:检测窗口大小
#   useHarrisDetector: 是否使用Harris算法.
#   ok:默是0.04


import cv2
import numpy as np


img = cv2.imread('./images/hand.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

#shi-tomasi角点检测
# corners = cv2.goodFeaturesToTrack(gray, maxCorners=0, qualityLevel=0.01, minDistance=10)
corners = cv2.goodFeaturesToTrack(gray, maxCorners=1000, qualityLevel=0.01, minDistance=10)
# print(corners)
print(corners.shape)
# corners = np.int0(corners)
corners = np.round(corners).astype('int64')

# 画出角点
for i in corners:
   x, y = i.ravel()
   cv2.circle(img, (x, y), 3, (0, 0, 255), -1)


cv2.imshow('shi-tomasi', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行后效果图如下:


 

全部评论