OpenCV-Harris和Shi-Tomasi角点检测

Harris参考文章:【MQ笔记】Harris角点检测2:算法实现(OpenCV+自主实现)

Harris角点检测步骤:
在这里插入图片描述Harris:

import cv2
import numpy as np


def harris_detect(img, ksize=3, k0=0.04):
    '''
    params:
        img:灰度图片
        ksize:Sobel算子窗口大小
        k0:响应函数
    return:
        corner:与源图像一样大小,角点处像素值设置为255
    '''
    k = k0  # 响应函数k
    threshold = 0.01  # 设定阈值
    WITH_NMS = False  # 是否非极大值抑制

    # 1、使用Sobel计算像素点x,y方向的梯度
    h, w = img.shape[:2]  # 提取图片宽、高
    grad = np.zeros((h, w, 2), dtype=np.float32)  # 创建梯度矩阵
    grad[:, :, 0] = cv2.Sobel(img, cv2.CV_16S, 1, 0, ksize=3)  # 取x方向的梯度
    grad[:, :, 1] = cv2.Sobel(img, cv2.CV_16S, 0, 1, ksize=3)  # 取y方向的梯度

    # 2、计算Ix^2,Iy^2,Ix*Iy
    m = np.zeros((h, w, 3), dtype=np.float32)
    m[:, :, 0] = grad[:, :, 0] ** 2
    m[:, :, 1] = grad[:, :, 1] ** 2
    m[:, :, 2] = grad[:, :, 0] * grad[:, :, 1]

    # 3、利用高斯函数对Ix^2,Iy^2,Ix*Iy进行滤波,得到矩阵m
    m[:, :, 0] = cv2.GaussianBlur(m[:, :, 0], ksize=(ksize, ksize), sigmaX=2)
    m[:, :, 1] = cv2.GaussianBlur(m[:, :, 1], ksize=(ksize, ksize), sigmaX=2)
    m[:, :, 2] = cv2.GaussianBlur(m[:, :, 2], ksize=(ksize, ksize), sigmaX=2)
    m = [np.array([[m[i, j, 0], m[i, j, 2]], [m[i, j, 2], m[i, j, 1]]]) for i in range(h) for j in range(w)]

    # 4、计算局部特征结果矩阵M的特征值和响应函数R(i,j)=det(M)-k(trace(M))^2  0.04<=k<=0.06
    D, T = list(map(np.linalg.det, m)), list(map(np.trace, m))
    R = np.array([d - k * t ** 2 for d, t in zip(D, T)])

    # 5、将计算出响应函数的值R进行非极大值抑制,滤除一些不是角点的点,同时要满足大于设定的阈值
    # 获取最大的R值
    R_max = np.max(R)
    # print(R_max)
    # print(np.min(R))
    R = R.reshape(h, w)
    corner = np.zeros_like(R, dtype=np.uint8)
    for i in range(h):
        for j in range(w):
            if WITH_NMS:
                # 除了进行进行阈值检测 还对3x3邻域内非极大值进行抑制(导致角点很小,会看不清)
                if R[i, j] > R_max * threshold and R[i, j] == np.max(
                        R[max(0, i - 1):min(i + 2, h - 1), max(0, j - 1):min(j + 2, w - 1)]):
                    corner[i, j] = 255
            else:
                # 只进行阈值检测
                if R[i, j] > R_max * threshold:
                    corner[i, j] = 255
    return corner


if __name__ == '__main__':
    img = cv2.imread('D:/testimage/word.jpg')
    # 转换为灰度图像
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    dst = harris_detect(gray)
    img[dst > 0.01 * dst.max()] = [0, 0, 255]
    cv2.imwrite('D:/testimage/FindCorner.jpg', img)
    cv2.imshow('FindCorner', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

结果:在这里插入图片描述

Shi-Tomasi:

import cv2 as cv
import numpy as np

if __name__=='__main__':
    img=cv.imread("D:/testimage/animal.jpg")
    gray_img=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
    result_img=img.copy()
    corners=cv.goodFeaturesToTrack(gray_img,100,0.01,10,blockSize=3,useHarrisDetector=False,k=0.04)
    #从float型转化为int型
    Corners=np.int0(corners)
    #print(Corners)
    for i in Corners:
        #将数组降维
        x,y=i.ravel()
        cv.circle(result_img,(x,y),2,(0,0,255),2)
    cv.imshow("original image", img)
    cv.imshow("result image",result_img)
    cv.imwrite("D:/testimage/result numbers.jpg",result_img)
    cv.waitKey(0)
    cv.destroyAllWindows()

结果:在这里插入图片描述

posted @ 2020-04-14 18:56  code_witness  阅读(44)  评论(0)    收藏  举报