CV基础 | 基于Harris 和Eigenvalue 的角点检测算法

本文介绍了如何实现角点检测,主要使用到了两种方法:基于Harris 角点检测器以及基于 H 矩阵最小特征值的检测方法。[1]

包含方法原理与步骤、代码、结果比对。

如果觉得有帮助,请点赞关注我。

角点

        角点是指图像中在两个或多个方向上都有较大灰度变化的像素点。从数学角度来看,角点是图像函数的局部极值点,其在某个邻域内具有显著的梯度变化。通常可以认为,角点是图像中两条边缘相交的点,可以用来表示图像中物体结构变化的显著特征。

        角点检测在计算机视觉领域有着广泛的应用,例如图像匹配、目标识别、三维重建和运动估计等。


Harris 角点检测器

        Harris 角点检测器是一种经典的角点检测方法,由Chris Harris和Mike Stephens在 1988 年提出。该方法通过分析图像的梯度信息来识别角点。

步骤


基于H矩阵最小特征值的角点检测器

        这种方法也是基于图像的梯度信息,但它直接使用H矩阵的特征值来确定角点。

 步骤


 代码

def corner_detect(img, block_size, nms_size, method, k): 
    # 计算图像的梯度 
    dx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) 
    dy = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3) 
    # 计算自相关矩阵的分量 
    Ixx = dx * dx 
    Ixy = dx * dy 
    Iyy = dy * dy 
    # 对自相关矩阵进行高斯滤波,以减小噪声的影响 
    window_size = block_size  # 使用block_size作为高斯滤波的窗口大小 
    ksize = (window_size, window_size) 
    Ixx = cv2.GaussianBlur(Ixx, ksize, 0) 
    Ixy = cv2.GaussianBlur(Ixy, ksize, 0) 
    Iyy = cv2.GaussianBlur(Iyy, ksize, 0) 
    # 初始化角点响应图 
    R = np.zeros_like(img, dtype=np.float32) 
    if method == 'harris': 
        det_H = Ixx * Iyy - Ixy * Ixy 
        trace_H = Ixx + Iyy 
        R = det_H - k * (trace_H ** 2) 
    elif method == 'eigenvalue': 
        # 对每个像素点计算H矩阵的特征值 
        for y in range(block_size, img.shape[0] - block_size):
            for x in range(block_size, img.shape[1] - block_size): 
                # 构建单个像素点的自相关矩阵 
                H = np.array([[Ixx[y, x], Ixy[y, x]], [Ixy[y, x], Iyy[y, x]]]) 
                # 计算特征值 
                eig_vals = np.linalg.eigvals(H) 
                # 保存最小特征值 
                min_eig = min(eig_vals) 
                R[y, x] = min_eig 
    # 根据阈值筛选角点 
    threshold = 0.01  
    corners = (R > threshold* R.max()).astype(np.uint8) * 255 
        # 应用非最大值抑制 
        for y in range(nms_size, img.shape[0] - nms_size): 
            for x in range(nms_size, img.shape[1] - nms_size): 
                if corners[y, x] == 255: 
                    local_max = True 
                    for dy in range(-nms_size, nms_size + 1): 
                        for dx in range(-nms_size, nms_size + 1): 
                            if corners[y, x] < corners[y + dy, x + dx]: 
                                local_max = False 
                                break 
                        if not local_max: 
                            break 
                    if local_max: 
                        corners[y, x] = 255 
                    else: 
                        corners[y, x] = 0 
        return corners, R

        在这个函数中基本的处理就是使用cv2.Sobel来计算横向以及纵向的梯度,然后按照前面的公式计算计算自相关矩阵H的分量,并对这些分量进行高斯滤波,使用blo ck_size作为高斯滤波的窗口大小。

        在这里如果method == 'harris',那么按照R的计算公式计算每一个像素值是角点的可能性,如果method == 'eigenvalue',那么构建每一个像素点的H矩阵,求解其特征值,选择最小的那个特征值作为R。

        阈值的选取是选择R中最大值乘以threshold。Threshold值会影响后面角点的检测,其越大检测到的角点数就越小。corners = (R > threshold* R.max()).astype(np.uint8) * 255这句代码使用了布尔索引,将角点响应图R中高于阈值的像素值设置为255(白色), 其余设置为0(黑色),从而生成一个二值图像corners,其中白色点表示检测到的角点, 应用非最大值抑制来减少噪声,最后返回结果。 

def image_read(): 
    # 读取图像 
    image = cv2.imread('your_img.jpg') 
    print(image.shape) 
    if image is None: 
        print("Error: Image not found.") 
        exit() 
    # 将图像转换为灰度图 
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 
    # 调用Harris角点检测函数 
    corners, R = corner_detect(gray_image,5, 3, 'harris', 0.05) 
    print(corners.shape) 
    # 在原图上标注角点 
    for y in range(corners.shape[0]): 
        for x in range(corners.shape[1]): 
            if corners[y, x] == 255: 
                # 将角点位置的像素值设为红色 
                image[y, x] = [0, 0, 255] 
    # 显示结果 
    cv2.imshow('Harris Corner Detection', image) 
    cv2.waitKey(0) 
    cv2.destroyAllWindows() 
    # 保存图像 
    cv2.imwrite('harris_corners_detected.jpg', image)

        这段代码的逻辑很简单,使用cv2读取图片,并将图像转换为灰度图,调用 corner _detect 函数进行 Harris 角点检测。参数解释:传入灰度图像,邻域大小为5,非最大值抑制大小为3,方法('harris'或'eigenvalue')和 Harris 参数 k为0.05。


结果展示

运行代码,选择method为harris,得到检测结果:

保持其它参数不变,将前面提到的threshold改为0.02,运行代码得到检测结果:

运行代码,选择method为eigenvalue,得到检测结果:

调用现成函数cv2.cornerHarris 进行检测,代码来源网络教程[2] ,得到检测结果:


[1] Harris C G , Stephens M J .A combined corner and edge detector[C]//Alvey visio n conference.1988.DOI:10.5244/C.2.23.

[2] (2024) Opencv之图像SIFT 特征检测与Harris角点检测. Available at: Opencv之图像SIFT 特征检测与Harris角点检测_harris 焦点检测器-CSDN博客 (Accessed: 25 February 2025).

以下是Harris检测算法Eigenvalue检测算法的介绍: 1. Harris检测算法 Harris检测算法是一种常用的检测算法,它通过计算图像中每个像素的响应函数来检测。该算法的基本思想是:对于一个窗口内的像素,如果它在不同方向上移动一个很小的距离,其灰度值的变化都很大,那么这个像素就是一个Harris检测算法的响应函数R的计算公式如下: R = det(M) - k * (trace(M))^2 其中,M是一个2x2的矩阵,表示窗口内像素的梯度信息,k是一个常数,一般取值为0.04~0.06。当R的值很大时,表示该像素是一个;当R的值很小时,表示该像素是一个边缘;当R的值为负数时,表示该像素是一个平坦区域。 2. Eigenvalue检测算法 Eigenvalue检测算法是一种基于图像局部结构的检测算法,它通过计算图像中每个像素的结构张量的特征值来检测。该算法的基本思想是:对于一个窗口内的像素,如果它在某个方向上的梯度变化很大,而在另一个方向上的梯度变化很小,那么这个像素就是一个Eigenvalue检测算法的结构张量T的计算公式如下: T = [∑(∂Ix)^2 ∑∂Ix∂Iy] [∑∂Ix∂Iy ∑(∂Iy)^2] 其中,IxIy分别表示像素在xy方向上的梯度,∂表示偏导数。计算出结构张量T后,可以通过求解其特征值来判断像素的类型。当特征值中的较小值很小时,表示该像素是一个;当特征值中的较小值很大时,表示该像素是一个边缘;当特征值中的较小值较大值都很小时,表示该像素是一个平坦区域。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值