這是opencv3.0.0的python版官方文檔,原文在這里
目標(biāo)
這一章節(jié),將
- 理解Harris角點(diǎn)檢測算法背后的原理
- 學(xué)習(xí)兩個(gè)函數(shù):
cv2.cornerHarris()、cv2.cornerSubPix()
理論
上一章,我們知道了角點(diǎn)是圖像中各個(gè)方向亮度(intensity,0~255)變化都很大的區(qū)域。最早嘗試做角點(diǎn)檢測的是Chris Harris和Mike Stephens,1988年,記錄在文獻(xiàn)《A Combined Corner and Edge Detector》中,因此現(xiàn)在叫做Harris角點(diǎn)檢測。他把這個(gè)簡單的想法用數(shù)學(xué)形式表達(dá)了出來。它基本找到了(u, v)在各個(gè)方向上位移后明亮度(Intensity)的差異,公式為:

window function是一個(gè)矩形窗口或者高斯窗口,是像素的權(quán)重。
為了檢測角點(diǎn),我們必須讓E(u, v)最大化。也就是說,我們要讓第二項(xiàng)最大。將Taylor Expansion應(yīng)用于上述方程并使用一些數(shù)學(xué)步驟(請(qǐng)參考您喜歡的任何標(biāo)準(zhǔn)教科書進(jìn)行完全推導(dǎo)),我們得到最終的等式:

其中

這里,Ix和Iy分別是x和y方向的導(dǎo)數(shù)。(可以很容易的通過
cv2.Sobel()得到)。
接下來就是重點(diǎn)部分。上述操作結(jié)束后,會(huì)得到一個(gè)分?jǐn)?shù),基于一個(gè)用來決定窗口內(nèi)是否包含角點(diǎn)的等式。

其中

所以這些特征值決定了這個(gè)區(qū)域是角點(diǎn),還是邊緣,還是flat。
- 當(dāng)|R|比較小時(shí),也就是lambda 1和lambda 2比較小,區(qū)域是flat
- 當(dāng)R<0時(shí), 也就是lambda 1遠(yuǎn)大于lambda 2或反之亦然,區(qū)域是邊緣
- 當(dāng)R比較大時(shí),也就是lambda 1和lambda2都大且相似,區(qū)域是角點(diǎn)
可以用下面的圖來表示

所以Harris角點(diǎn)檢測的結(jié)果是一個(gè)帶著這些分?jǐn)?shù)的灰度圖。圖像角點(diǎn)檢測需要一個(gè)合適的閾值。我們將用一個(gè)簡單的圖來實(shí)現(xiàn)
Opencv中的Harris角點(diǎn)檢測
Opencv中有一個(gè)函數(shù)cv2.cornerHarris()用來實(shí)現(xiàn)這個(gè)算法,參數(shù)是:
- img - 輸入圖片,需要灰度圖且類型float32
- blockSize - 是角點(diǎn)檢測考慮的鄰域大小
- ksize - sobel所用參數(shù)
- k - Harris檢測器中的自由參數(shù)
看下面的例子:
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()
下面是三個(gè)結(jié)果圖:
