OpenCV 圖像特徵提取——Harris角點檢測

OpenCV 圖像特徵提取

Harris 角點檢測


1、什麼是角點

  同角點並列的還有邊界點、平面點。看下面的圖可以看出來三者之間的位置關係。

從上面的圖片我們可以看出來:

  • 平面:A, B
  • 邊界:C, D
  • 角點:E, F

簡化一點就是下面三種情況:

2、如何區分角點、邊界和平面

我們使用肉眼觀察很方便,但是輸入到計算機裏面就需要相應的算法進行識別。

三種基本情況
  • 平面: 之所以叫平面,是因爲在圖像窗口任意移動過程中,像素值不會發生明顯的變化,趨於平滑。

  • 邊界: 當圖像窗口在邊界範圍移動時,像素值會沿一個方向基本不變,在垂直的方向發生巨大變化。可以看中間的圖片,當沿 y 軸運動時,像素值不會發生大的變化。當沿 x 軸移動時會發生像素值會發生巨大變化。

  • 角點: 不同於平面和邊界,圖像窗口處於角點位置時,沿任意方向都會發生巨大變化。

利用上面的規則我們就可以區分角點、邊界和平面。

3、角點公式推導

我們在實際中主要是觀察移動前後像素值的變化情況。
1、 當圖像在 (x,y)(x, y) 處平移 (Δx,Δy)(\Delta x, \Delta y) 後的自相似性:

c(x,y;Δx,Δy)=u,vW(x,y)w(u,v)(I(u,v)I(u+Δx,v+Δy))2 c(x,y;\Delta x,\Delta y) = \sum_{u,v\in W(x,y)}w(u,v)(I(u,v)-I(u+\Delta x, v+\Delta y))^2

其中 w(x,y)w(x,y) 是以點 (x,y)(x, y) 爲中心的窗口,這裏既可以取常數,或者是高斯加權的函數(推薦)。

2、 對上面的部分式子進行化簡,泰勒展開:

I(u+Δx,v+Δy)=I(u,v)+Ix(u,v)Δx+Iy(u,v)Δy+O(Δx2,Δy2)I(u,v)+Ix(u,v)Δx+Iy(u,v)Δy I(u+\Delta x, v+\Delta y)=I(u,v)+I_x(u,v)\Delta x + I_y(u,v)\Delta y + O(\Delta x^2, \Delta y^2) \approx I(u,v)+ I_x(u, v)\Delta x + I_y(u,v)\Delta y

其中 Ix,IyI_x,I_y 分別是 x,yx, y 的偏導數。

3、 進一步化簡關於 c 的方程,近似可得:

c(x,y;Δx,Δy)w(Ix(u,v)Δx+Iy(u,v)Δy)2=[Δx,Δy]M(x,y)[ΔxΔy] c(x,y;\Delta x,\Delta y) \approx\sum_w (I_x(u, v)\Delta x + I_y(u,v)\Delta y)^2 = [\Delta x , \Delta y]M(x,y)\begin{bmatrix} \Delta x \\ \Delta y \end{bmatrix}

我們發現上賣弄的式子是一個平方項,我們可以使用二次型對結果進行化簡,提取二次型矩陣。

4、二次型矩陣
M(x,y)=w[Ix(x,y)2Ix(x,y)Iy(x,y)Ix(x,y)Iy(x,y)Iy(x,y)2]=[wIx(x,y)2wIx(x,y)Iy(x,y)wIx(x,y)Iy(x,y)wIy(x,y)2]=[ABBC] M(x, y) = \sum_w\begin{bmatrix} I_x(x,y)^2 & I_x(x, y)I_y(x, y) \\ I_x(x, y)I_y(x, y) & I_y(x, y)^2 \end{bmatrix} = \begin{bmatrix} \sum_w I_x(x,y)^2 & \sum_w I_x(x,y)I_y(x,y)\\ \sum_w I_x(x,y)I_y(x,y) & \sum_w I_y(x,y)^2 \end{bmatrix}=\begin{bmatrix} A & B \\ B & C \end{bmatrix}
化簡可得:
c(x,y;Δx,Δy)AΔx2+2CΔxΔy+BΔy2 c(x,y;\Delta x,\Delta y) \approx A\Delta x^2+2C\Delta x \Delta y + B \Delta y^2

{A=Ix2B=IxIyC=Iy2\begin{cases} A=I_x^2\\ B=I_x I_y\\ C=I_y^2 \end{cases}

5、 形狀估計

我們可以看得出來二次項函數是一個橢圓函數,類似於:x2a2+y2b2=c\frac{x^2}{a^2}+\frac{y^2}{b^2} = c,只不過是一個不過圓心的橢圓函數。
而且橢圓的大小隨着Δx,Δy\Delta x , \Delta y的變化而變化。類似於一個錐體。

我們最後希望檢測角點,我們上面提到,它的變化越大,說明是角點的可能性越大。也就是說在單位Δx,Δy\Delta x , \Delta y變化中,角點所在位置一般就是$A, B, C $較大值的點。實際中我們並不好利用三個值來進行判斷是否是邊界,平面還是角點。所以我們根據性質來減少自變量

6、 減少自變量

根據我們之前學的高數,裏面有一個定理:

實對稱矩陣一定可以對角化

我們的 MM 矩陣是一個實對稱矩陣( MT=MM^T = M ),那麼它一定可以對角化,並且一定存在一組特徵值( λ1,λ2\lambda_1, \lambda_2 ),那麼就將矩陣對角化。這樣自變量由三個變成了兩個,我們就方便來區分三者。

從上圖我們可以分析出來:

  • 平面:λ1,λ2\lambda_1,\lambda_2均小,也就說梯度不怎麼變化
  • 邊界:λ1λ2λ1λ2\lambda_1 \gg \lambda_2,\lambda_1 \ll \lambda_2,也就是說梯度只沿一個方向變化快,垂直方向變化慢。
  • 角點:λ1,λ2\lambda_1,\lambda_2 均大,也就是沿任意方向變化均快。

7、 角點響應值

上面我們只是分析了依靠λ1,λ2\lambda_1,\lambda_2來區分三者,那麼需要更加準確的表達式來進行判別。
R=detMα(traceM)2 R=detM - \alpha(traceM)^2
其中detM=λ1λ2:traceM=λ1+λ2detM = \lambda_1\lambda_2:行列式的值 \quad traceM=\lambda_1+\lambda_2:跡

4、OpenCV相關函數

cv2.cornerHarris(img, blockSize, ksize, k)
  • img:輸入圖像。類型爲float32
  • blockSize:角點檢測中指定的區域大小
  • ksize:Soble求導中使用窗口的大小
  • k:取值爲[0.04-0.06]

5、角點檢測程序實現

程序實現:

def cv_show(src):
    cv2.imshow('',src) 
    cv2.waitKey(0) 
    cv2.destroyAllWindows()

img_copy = img.copy()
img = cv2.imread('Pic/check.jpg')  # 棋盤圖片
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 轉換爲灰度圖
dst = cv2.cornerHarris(gray, 2, 3, 0.04)  # 角點檢測
img[dst>0.0005*dst.max()]=[0,0,255]  # 標記角點
res = np.hstack((img_copy, img))
cv_show(res)

結果如下:

結果

最後

更多精彩內容,大家可以轉到我的主頁:曲怪曲怪的主頁

或者關注我的微信公衆號:TeaUrn

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章