Harris運算元總結
一. Harris基本原理
Harris運算元是一種基於訊號的點特徵提取運算元,它是對Moravec運算元的改進。其基本思想是:在影象中設計一個區域性
檢測視窗,當該視窗沿各個方向做微小移動時,考察視窗的平均能量變化,當該能量變化超過設定的閾值時,就將窗
口的中心畫素點提取為角點。
二. Harris計算過程
Harris運算元數學方程,如下所示:
進行泰勒級數展開等,矩陣形成如下所示:
其中,和是影象在和方向的導數,可使用cv2.Sobel()計算結果。
根據一個用來判定視窗內是否包含角點的等式進行打分。如下所示:
其中,,,和是矩陣的特徵值。
根據這些特徵值,可以判斷一個區域是否是角點,邊界或者是平面,如下所示:
1. 當和都小時,也小,表示這個區域是一個平坦區域。
2. 當或時,小於0,表示這個區域是邊緣。
3. 當和都很大,並且時,也很大(和中的最小值都大於閾值),表示這個區域是角點。
Harris角點檢測的結果是一個由角點分數構成的灰度影象,選取適當的閾值對結果影象進行二值化就檢測到了影象中
的角點。
三. OpenCV中的Harris運算元
函式原型:cv2.cornerHarris(src, blockSize, ksize, k[, dst[, borderType]]) → dst。其中,img表示資料型別為float32的
輸入影象。blockSize表示角點檢測中要考慮的領域大小。ksize表示Sobel求導中使用的視窗大小。k表示Harris角點檢
測方程中的自由引數。
結果輸出,如下所示:import cv2 import numpy as np filename = 'chessboard.jpg' img = cv2.imread(filename) gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) gray = np.float32(gray) dst = cv2.cornerHarris(gray,2,3,0.04) # result is dilated for marking the corners, not important dst = cv2.dilate(dst,None) # threshold for an optimal value, it may vary depending on the image img[dst>0.01*dst.max()]=[0,0,255] cv2.imshow('dst',img) if cv2.waitKey(0) & 0xff == 27: cv2.destroyAllWindows()
四. 亞畫素級精確度的角點
OpenCV中的函式cv2.cornerSubPix()可以提供亞畫素級別的角點檢測。首先找到Harris角點,然後將角點的重心傳給
該函式進行修正。Harris角點用紅色畫素標出,綠色畫素是修正後的畫素。如下所示:
import cv2
import numpy as np
filename = 'chessboard2.jpg'
img = cv2.imread(filename)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# find Harris corners
gray = np.float32(gray)
dst = cv2.cornerHarris(gray,2,3,0.04)
dst = cv2.dilate(dst,None)
ret, dst = cv2.threshold(dst,0.01*dst.max(),255,0)
dst = np.uint8(dst)
# find centroids
ret, labels, stats, centroids = cv2.connectedComponentsWithStats(dst)
# define the criteria to stop and refine the corners
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.001)
corners = cv2.cornerSubPix(gray,np.float32(centroids),(5,5),(-1,-1),criteria)
# now draw them
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]
cv2.imwrite('subpixel5.png',img)
為了方便檢視對角點的部分進行了放大,如下所示:
1. cv2.connectedComponentsWithStats(OpenCV 3.X)
解析:函式原型int connectedComponentsWithStats(InputArray image, OutputArray labels, OutputArray stats,
OutputArray centroids, int connectivity=8, int ltype=CV_32S)。
2. cv2.cornerSubPix
解析:函式原型void cornerSubPix(InputArray image, InputOutputArray corners, Size winSize, Size zeroZone,
TermCriteria criteria)。
參考文獻:[1] A Combined Corner and Edge Detector