238. Harris 角点检测

13. 特征提取

  • 角是直线方向的快速变化。
    角点通常被定义为两条边的交点,或者说角点的邻域应该具有两个不同区域的不同方向的边界。

  • 角是高度有效的特征。
    角点检测(Corner Detection)广泛应用于运动检测、图像匹配、视频跟踪、三维重建和目标识别。

一、哈里斯-斯蒂芬斯角检测器(Harris)

  • 在基于灰度变换的角点检测算法中,Harris 算法重复性良好、检测效率较高,应用较为广泛。

  • 哈里斯-斯蒂芬斯角检测器(Harris and Stephens)的原理是,通过检测窗口在图像上移动,计算移动前后窗口中像素的灰度变化。角点是两条边的交点,其特征是检测窗口沿任意方向移动都会导致灰度的显著变化。
    对于点(x,y),令w(x,y) 为矩形检测窗口或高斯检测窗口,I(x,y) 是检测窗口在点(x,y) 的灰度值,I(x+u,y+v) 是检测窗口滑动(u,v) 距离之后的灰度值。
    计算窗口w(x,y) 滑动(u,v) 距离之后的灰度变化:


    对于很小的位移(u,v),使用一阶泰勒展开进行简化:

    I_x ,I_y分别是在 x, y 方向的导数,可以由 Sobel 梯度算子求出。
    记 M 为梯度的协方差矩阵:

    在几何模型中通过判断两个特征值的大小,来判定像素的属性。矩阵 M 是I_x,I_y 的二次函数,可以表示为椭圆形状,椭圆的长短半轴由矩阵 M 的特征值\lambda _1,\lambda_2决定,方向由特征向量决定。
    定义角点响应函数 R:

    k 是调节参数(通常取 0.04~0.06)。
    角点响应函数 R 只与矩阵 M 的特征值 \lambda _1,\lambda_2有关,可以用来判断区域是拐角、边缘还是平坦:
    \lambda _1,\lambda_2较小时,∣R∣ 较小,即各个方向上灰度基本不变,表明检测器处于平坦区域;
    \lambda _1 >> \lambda _2\lambda _2 >> \lambda _1 时,R<0 ,即灰度在某个方向变化,但在其正交方向不变化,表明检测器处于边缘区域;
    \lambda _1,\lambda _2 较大且\lambda _1 \sim \lambda _2 时,∣R∣ 很大,即灰度在所有方向都发生重大变化,表明检测器包含角点(或孤立点。

二、OpenCV 中的 Harris 角检测器

  • OpenCV 中提供了 Harris 角点检测函数 cv.cornerHarris()。

cv.cornerHarris(src, blockSize, ksize, k[, dst=None, borderType=BORDER_DEFAULT] ) → dst
cv.cornerEigenValsAndVecs(src, blockSize, ksize[, dst=None, borderType=BORDER_DEFAULT]) → dst
cv.cornerMinEigenVal(src, blockSize[, dst=None, ksize=3, borderType=BORDER_DEFAULT]) → dst

  • 函数 cv.cornerHarris 运行 Harris 角检测器。

  • 函数 cv.cornerEigenValsAndVecs 计算图像矩阵的特征值和特征向量。

  • 函数 cv.cornerMinEigenVal 计算用于角点检测的梯度矩阵的最小特征值。

  • 对于每个像素 (x,y) 计算梯度协方差矩阵M(x,y)。然后计算特征:



    则角点在特征响应图像中是局部极大值。 实践中定义当 R 大于设定阈值,且为局部最大值的点为角点 。

参数说明:

  • src:输入图像,单通道的 8位图像或浮点数图像
  • dst:输出图像,Harris 检测器的响应,大小与 src 相同,格式为 CV_32FC1
  • blockSize:邻域尺寸
  • ksize:Sobel 算子的孔径参数
  • k:Harris 检测器调节参数,通常取 0.04~0.06
  • borderType:边界扩充类型
    cv.BORDER_CONSTANT
    cv.BORDER_REPLICATE
    cv.BORDER_REFLECT
    cv.BORDER_REFLECT_101
    cv.BORDER_TRANSPARENT

注意事项:

  • 函数 cv.cornerMinEigenVal 类似于 cv.cornerEigenValsAndVecs,但它仅计算和保存矩阵 M 的最小特征值,即min(\lambda_1, \lambda_2)

三、例程

  • 14.19:特征检测之 Harris 角检测器
import cv2
import numpy as np
from matplotlib import pyplot as plt

# 14.19 角点检测之 Harris 算法
img = cv2.imread(r"E:/OpenCV/plane.jpg", flags=1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # (600, 540)
# gray = np.float32(gray)  # uint8,float32 都支持

blockSize = [2, 3, 5]  # 滑动窗口大小
ksize = [3, 5, 9]  # Sobel 核函数大小
plt.figure(figsize=(9, 9))
for i in range(len(blockSize)):
    for j in range(len(ksize)):
        dst = cv2.cornerHarris(gray, blockSize[i], ksize[j], k=0.04)
        imgCorner = np.copy(img)
        imgCorner[dst > 0.01*dst.max()] = [0, 0, 255]  # 筛选角点,红色标记
        plt.subplot(3,3,i*len(ksize)+j+1), plt.axis('off')
        plt.imshow(cv2.cvtColor(imgCorner, cv2.COLOR_BGR2RGB))
        plt.title("blockSize={},ksize={}".format(blockSize[i], ksize[j]))

plt.tight_layout()
plt.show()

四、资料

youcans_的博客:
https://blog.csdn.net/youcans/article/details/125820758
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容