Opencv哈里斯角检测

文章目录

  • 1 理论
  • 2 测试图像
  • 3 检测
  • 4 SubPixel精度的转角

1 理论

  是图像中各个方向上强度变化很大的区域,Harris等人做了一些找到这些角的尝试,并变成如下数学形式:

E ( u , v ) = ∑ x , y w ( x , y ) ⏟ window function   [ I ( x + u , y + v ) ⏟ shifted intensity − I ( x , y ) ⏟ intensity ] 2 . E(u,v) = \sum_{x,y} \underbrace{w(x,y)}_\text{window function} \, [\underbrace{I(x+u,y+v)} _\text{shifted intensity}-\underbrace{I(x,y)}_\text{intensity}]^2. E(u,v)=x,ywindow function w(x,y)[shifted intensity I(x+u,y+v)intensity I(x,y)]2.  以上函数基本找到了 ( u , v ) (u, v) (u,v)在所有方向上位移的强度差异。角检测时,需要最大化上式,其泰勒展开如下:
E ( u , v ) ≈ [ u v ] M [ u v ] , E(u,v) \approx \begin{bmatrix} u & v \end{bmatrix} M \begin{bmatrix} u \\ v \end{bmatrix}, E(u,v)[uv]M[uv],其中
M = ∑ x , y w ( x , y ) [ I x I x I x I y I x I y I y I y ] , M = \sum_{x,y} w(x,y) \begin{bmatrix}I_x I_x & I_x I_y \\ I_x I_y & I_y I_y \end{bmatrix}, M=x,yw(x,y)[IxIxIxIyIxIyIyIy],其中 I x , I y I_x, I_y Ix,Iy x x x y y y方向上的图像导数,可以使用cv.Sobel() 找到。
  接下来创建一个等式,用于判断一个窗口是否可以包含一个角:
R = d e t ( M ) − k ( t r a c e ( M ) ) 2 , R = det(M) - k(trace(M))^2, R=det(M)k(trace(M))2,其中
d e t ( M ) = λ 1 λ 2 ; t r a c e ( M ) = λ 1 + λ 2 , det(M)=\lambda_1\lambda_2;\\ trace(M)=\lambda_1+\lambda_2, det(M)=λ1λ2;trace(M)=λ1+λ2,其中 λ 1 \lambda_1 λ1 λ 2 \lambda_2 λ2 M M M的特征值。
  因此,这些特征值决定了给定区域是拐角、边缘还是平坦
  1)当 ∣ R ∣ |R| R较小时,平坦;
  2) R < 0 R<0 R<0,边;
  3) R R R很大,角。
  最终,哈夫角检测的结果就是具有 R R R值的灰度图像。

2 测试图像

Opencv哈里斯角检测_第1张图片

3 检测

# coding: utf-8
import cv2 as cv
import numpy as np


def test(file_name):
    """"""
    img = cv.imread(file_name)
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    gray = np.float32(gray)
    # 输入参数包括灰度图、检测时的邻域大小、sobel导数的光圈参数、检测器自由参数
    dst = cv.cornerHarris(gray, 3, 3, 0.1)
    dst = cv.dilate(dst, None)
    img[dst > 0.01 * dst.max()] = [0, 0, 255]
    cv.imshow("", img)
    cv.waitKey()


if __name__ == '__main__':
    file_name = "shudu.png"
    test(file_name)

  输出如下:
Opencv哈里斯角检测_第2张图片

4 SubPixel精度的转角

  找到最精确的角落:

# coding: utf-8
import cv2 as cv
import numpy as np


def test(file_name):
    """"""
    img = cv.imread(file_name)
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    gray = np.float32(gray)
    # 输入参数包括灰度图、检测时的邻域大小、sobel导数的光圈参数、检测器自由参数
    dst = cv.cornerHarris(gray, 3, 3, 0.1)
    dst = cv.dilate(dst, None)
    _, dst = cv.threshold(dst, 0.01 * dst.max(), 255, 0)
    dst = np.uint8(dst)
    # 寻找质心
    ret, labels, stats, centroids = cv.connectedComponentsWithStats(dst)
    # 定义停止和完善拐角的条件
    criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 100, 0.001)
    corners = cv.cornerSubPix(gray, np.float32(centroids), (5, 5), (-1, -1), criteria)
    res = np.hstack((centroids, corners))
    res = np.int0(res)
    img[res[:, 1], res[:, 0]] = [0, 0, 255]
    img[res[:, 3], res[:, 2]] = [0, 255, 0]
    cv.imshow("", img)
    cv.waitKey()


if __name__ == '__main__':
    file_name = "shudu.png"
    test(file_name)

  输出如下:
Opencv哈里斯角检测_第3张图片

你可能感兴趣的:(Python,Opencv,哈里斯角检测,因吉)