1. 程式人生 > >Harris角點檢測原理與opencv(python)實現

Harris角點檢測原理與opencv(python)實現

在學習時主要參考了1.http://blog.csdn.net/xiaowei_cqu/article/details/7805206和opencv-python官方的關於harris的文件(http://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_feature2d/py_features_harris/py_features_harris.html#harris-corners)。

1.原理

對於角點的檢測,harris依據一下直觀判斷:角點應該在視窗的各個方向都有變化,而邊界會在某個方向基本不變,而平坦區域在各個方向變化都小。

因此我們要衡量在某個方向上的變化大小,定義

E(u,v) = \sum_{x,y} w(x,y)~[I(x+u, y+v) - I(x,y)]^2

其中,w(x,y)是視窗函式;向量[u, v]表示某個方向,以及在該方向上的位移。由以上公式可知,E(u,v)表示在某個方向上影象灰度的變化。我們首先要研究在那個方向上,灰度變化最大(即令E(u,v)最大)。求解這個問題,我們通過泰勒展開公式(二元公式為:)可以得到:

記上式最後的結果為,則我們可以得到:


注意這個推導過程在http://blog.csdn.net/xiaowei_cqu/article/details/7805206中有一步是錯誤的!

這時我們知道找兩個特徵值中較大的對應的特徵方向就是變化較大的方向。

但是我們考慮的問題不是得到視窗沿[u,v]移動變化最大,而是要衡量這個視窗內各個方向變化是否大。這就需要用特徵值來衡量。

直觀上考慮:

都小 : 區域平坦;

 : 邊界

且都大:角點

基於以上原理,我們定義


這時,

R小,說明兩個特徵值都小,對應區域平坦;

R<0,說明,對應邊界;

R大,說明且都大,對應角點。

所以可以用R>閾值作為條件判斷是否是角點。

2.python程式碼

關鍵命令是:cv2.cornerHarris(src, blocksize, ksize, k [, dst [, borderType ]]) -> dst

引數如下:

ksize:Sobel的孔徑引數(aperture parameter),也就是Sobel核的半徑,如1、3、5、7

k:R公式中的k,預設取0.04

blocksize:視窗大小,示例中取2

【python程式碼如下】

import cv2
import numpy as np

#讀入影象並轉化為float型別,用於傳遞給harris函式
filename = 'Dirk.jpg'

img = cv2.imread(filename)

gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

gray_img = np.float32(gray_img)

#對影象執行harris
Harris_detector = cv2.cornerHarris(gray_img, 2, 3, 0.04)

#腐蝕harris結果
dst = cv2.dilate(Harris_detector, None)

# 設定閾值
thres = 0.01*dst.max()

img[dst > thres] = [255,0,0]

cv2.imshow('show', img)

cv2.waitKey()