OpenCV Python系列之哈里斯角檢測

2022-09-07 04:57:10 字數 3595 閱讀 8208

我們在上次簡述了opencv的特徵基礎原理,本次我們將步入實戰部分,開始進行特徵的初階檢測。

原理

在上乙個教程中,我們知道了角點是影象中向任意方向發生改變時,都引起影象強烈變動的區域。chris harris 和 mike stephens 在他們2023年的** a combined corner and edge detector 中,做了早期的嘗試,嘗試找出這些角點。因此現在這個演算法被稱為哈里斯角點檢測。他把這個簡單的想法變成了數學的形式。它基本上求出了位移(u,v)在各個方向上的強度差,這表示如下:

視窗函式可以是乙個矩形視窗,也可以是乙個給與它覆蓋畫素權重的高斯視窗。

為了要做角點檢測,我們需要令這個函式 e(u,v) 最大。也就是說二元函式求極限的時間到了。將泰勒展開應用於上述方程,我們可以對下面函式進行一階展開:

那麼:

所以e(u,v)表示式可以更新為:

其中:在此,ix 和 iy 分別是x 和 y方向上影象的導數。(可以被簡單用索貝爾函式算出來 cv.sobel())。(譯者注,m其實就是梯度的協方差矩陣)

然後進入主要的正題。做完這個步驟之後,建立了乙個得分函式,基本上就是乙個等式,它將決定乙個視窗是否包含乙個角。

其中:1、

2、3、λ1 和 λ2 是m的特徵值

然後,這些特徵值決定了乙個區域是角、邊還是平面。

a、當 |r| 較小時,是因為 λ1 和 λ2 都很小,說明這片區域是平面。

b、當 r<0時,是因為 λ1 >> λ2 或者反過來(其中乙個遠大於另外乙個),此時區域是邊。

c、當 r較大時,是因為 λ1 和 λ2 都較大,且 λ1∼λ2,此時這片區域應為角。

它可以用下圖來表示:

所以哈里斯角點檢測演算法的結果,是乙個帶著這些得分的灰度影象,使用乙個合適的閾值,就能給到我們圖中的角點。我們用乙個簡單的影象來做一下實驗。

opencv中的哈里斯角點檢測

我們來看一下opencv中的函式原型:

dst=cv.cornerharris(src,blocksize,ksize,k [,dst [,bordertype]]

img - 輸入影象,它應該是灰度影象,且是 float32 型別的。

blocksize - 它是檢測拐角時所考慮的鄰域大小。

ksize - 在應用索貝爾演算法時使用的孔徑引數。

k - 方程中哈里斯檢測器的自由引數。

我們來看**:

import numpy as np

import cv2 as cv

filename = 'chessboard.png'

img = cv.imread(filename)

gray = cv.cvtcolor(img,cv.color_bgr2gray)

gray = np.float32(gray)

dst = cv.cornerharris(gray,2,3,0.04)

#result is dilated for marking the corners, not important

dst = cv.dilate(dst,none)

# threshold for an optimal value, it may vary depending on the image.

img[dst>0.01*dst.max()]=[0,0,255]

cv.imshow('dst',img)

if cv.waitkey(0) & 0xff == 27:

cv.destroyallwindows()

來看結果:

有時,我們可能需要找到最準確的角點。opencv 有乙個函式 cv.cornersubpix() ,它進一步細化檢測到的角的亞畫素精度。以下是乙個示例。通常,我們還是要先找到哈里斯角。然後我們通過這些角的質心(在乙個角上可能有一堆畫素,我們取它們的質心)來細化它們。哈里斯角用紅色畫素標記,而細化之後的角用綠色畫素標記。對於這個函式,我們必須定義何時停止迭代的條件。我們在指定的迭代次數之後停止它,或者達到了一定的精度,以最先發生的為準。我們還需要定義它將搜尋角落的鄰居的大小:

以下是結果,其中一些重要的位置顯示在縮放視窗中進行視覺化:

OpenCV Python系列之相機校準

在本次教程中,我們將介紹 由相機引起的失真型別,如何找到相機的固有和非固有特性 如何根據這些特性使影象不失真 一些針孔相機會給影象帶來明顯的失真。兩種主要的變形是徑向變形和切向變形。徑向變形會導致直線出現彎曲。距影象中心越遠,徑向畸變越大。例如,下面顯示乙個影象,其中棋盤的兩個邊緣用紅線標記。但是,...

OpenCV Python系列之拉普拉斯運算元

我們在上乙個教程中前面的例子學習了使用sobel邊緣檢測。原理是利用邊緣區域畫素值的跳變。通過求一階導數,可以使邊緣值最大化。如下圖所示 那麼,如果求二階導數會得到什麼呢?可以觀察到二階導數為0的地方。因此,可以利用該方法獲取影象中的邊緣。然而,需要注意的是二級導數為0的不只出現在邊緣地方,還可能是...

OpenCV Python系列 第二十二集 戴面具

tip 實時監測人臉,並戴上面具。coding utf 8 created on tue sep 4 08 50 53 2018 author administrator import cv2 def maskman face mask 獲取面具的寬高 h mask,w mask face mask...